From df9871064e8b564d9ae2e56d561b64434fd004af Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 26 Jul 2008 08:56:23 +1000 Subject: radeon: add initial atombios modesetting and GEM -> TTM translation layer. This is an initial import of the atom bios parser with modesetting support for r500 hw using atombios. It also includes a simple memory manager layer that translates a radeon GEM style interface onto TTM internally. So far this memory manager has only been used for pinned object allocation for the DDX to test modesetting. --- linux-core/radeon_gem.c | 687 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 687 insertions(+) create mode 100644 linux-core/radeon_gem.c (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c new file mode 100644 index 00000000..d536aed2 --- /dev/null +++ b/linux-core/radeon_gem.c @@ -0,0 +1,687 @@ +/* + * Copyright 2008 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Dave Airlie + */ +#include "drmP.h" +#include "drm.h" + +#include "radeon_drm.h" +#include "radeon_drv.h" + +int radeon_gem_init_object(struct drm_gem_object *obj) +{ + struct drm_radeon_gem_object *obj_priv; + + obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER); + if (!obj_priv) { + return -ENOMEM; + } + + obj->driver_private = obj_priv; + obj_priv->obj = obj; + + return 0; +} + +void radeon_gem_free_object(struct drm_gem_object *obj) +{ + + struct drm_radeon_gem_object *obj_priv = obj->driver_private; + + /* tear down the buffer object - gem holds struct mutex */ + drm_bo_takedown_vm_locked(obj_priv->bo); + drm_bo_usage_deref_locked(&obj_priv->bo); + drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); +} + +int radeon_gem_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_radeon_gem_info *args = data; + + args->vram_start = dev_priv->mm.vram_offset; + args->vram_size = dev_priv->mm.vram_size; + args->vram_visible = dev_priv->mm.vram_visible; + + args->gart_start = dev_priv->mm.gart_start; + args->gart_size = dev_priv->mm.gart_size; + + return 0; +} + +struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, int alignment, + int initial_domain) +{ + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + int ret; + uint32_t flags; + + DRM_DEBUG("size 0x%x, alignment %d, initial_domain %d\n", size, alignment, initial_domain); + obj = drm_gem_object_alloc(dev, size); + if (!obj) + return NULL;; + + obj_priv = obj->driver_private; + if (initial_domain == RADEON_GEM_DOMAIN_VRAM) + flags = DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE; + else + flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE; + + flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE; + /* create a TTM BO */ + ret = drm_buffer_object_create(dev, + size, drm_bo_type_device, + flags, 0, alignment, + 0, &obj_priv->bo); + if (ret) + goto fail; + + return obj; +fail: + + return NULL; +} + +int radeon_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_radeon_gem_create *args = data; + struct drm_radeon_gem_object *obj_priv; + struct drm_gem_object *obj; + int ret = 0; + uint32_t flags; + int handle; + + /* create a gem object to contain this object in */ + args->size = roundup(args->size, PAGE_SIZE); + + obj = radeon_gem_object_alloc(dev, args->size, args->alignment, args->initial_domain); + if (!obj) + return -EINVAL; + + obj_priv = obj->driver_private; + DRM_DEBUG("obj is %p bo is %p, %d\n", obj, obj_priv->bo, obj_priv->bo->num_pages); + ret = drm_gem_handle_create(file_priv, obj, &handle); + mutex_lock(&dev->struct_mutex); + drm_gem_object_handle_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + if (ret) + goto fail; + + args->handle = handle; + + return 0; +fail: + drm_gem_object_unreference(obj); + + return ret; +} + +int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + /* transition the BO to a domain - just validate the BO into a certain domain */ + struct drm_radeon_gem_set_domain *args = data; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + int ret; + /* for now if someone requests domain CPU - just make sure the buffer is finished with */ + + /* just do a BO wait for now */ + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + obj_priv = obj->driver_private; + + mutex_lock(&obj_priv->bo->mutex); + ret = drm_bo_wait(obj_priv->bo, 0, 1, 0, 0); + mutex_unlock(&obj_priv->bo->mutex); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENOSYS; +} + +int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENOSYS; +} + +int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_radeon_gem_mmap *args = data; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + loff_t offset; + unsigned long addr; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + offset = args->offset; + + DRM_DEBUG("got here %p\n", obj); + obj_priv = obj->driver_private; + + DRM_DEBUG("got here %p %p %lld %ld\n", obj, obj_priv->bo, args->size, obj_priv->bo->num_pages); + if (!obj_priv->bo) { + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + down_write(¤t->mm->mmap_sem); + addr = do_mmap_pgoff(file_priv->filp, 0, args->size, + PROT_READ | PROT_WRITE, MAP_SHARED, + obj_priv->bo->map_list.hash.key); + up_write(¤t->mm->mmap_sem); + + DRM_DEBUG("got here %p\n", obj); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + if (IS_ERR((void *)addr)) + return addr; + + args->addr_ptr = (uint64_t) addr; + + return 0; + +} + +int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_radeon_gem_pin *args = data; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + int ret; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + obj_priv = obj->driver_private; + + DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); + /* validate into a pin with no fence */ + + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, + 0, NULL); + + args->offset = obj_priv->bo->offset; + DRM_DEBUG("got here %p %p\n", obj, obj_priv->bo); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_radeon_gem_unpin *args = data; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + int ret; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + obj_priv = obj->driver_private; + + /* validate into a pin with no fence */ + + ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, + 0, NULL); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return ret; +} + +int radeon_gem_busy(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return 0; +} + +int radeon_gem_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -ENOSYS; + + +} + +int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_radeon_gem_indirect *args = data; + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + uint32_t start, end; + int ret; + RING_LOCALS; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + obj_priv = obj->driver_private; + + DRM_DEBUG("got here %p %d\n", obj, args->used); + //RING_SPACE_TEST_WITH_RETURN(dev_priv); + //VB_AGE_TEST_WITH_RETURN(dev_priv); + + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + 0 , 0, NULL); + if (ret) + return ret; + + /* Wait for the 3D stream to idle before the indirect buffer + * containing 2D acceleration commands is processed. + */ + BEGIN_RING(2); + + RADEON_WAIT_UNTIL_3D_IDLE(); + + ADVANCE_RING(); + + start = 0; + end = args->used; + + if (start != end) { + int offset = (dev_priv->gart_vm_start + + + obj_priv->bo->offset + start); + int dwords = (end - start + 3) / sizeof(u32); + +#if 0 + /* Indirect buffer data must be an even number of + * dwords, so if we've been given an odd number we must + * pad the data with a Type-2 CP packet. + */ + if (dwords & 1) { + u32 *data = (u32 *) + ((char *)dev->agp_buffer_map->handle + + buf->offset + start); + data[dwords++] = RADEON_CP_PACKET2; + } +#endif + /* Fire off the indirect buffer */ + BEGIN_RING(3); + + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(offset); + OUT_RING(dwords); + + ADVANCE_RING(); + } + + COMMIT_RING(); + + /* we need to fence the buffer */ + ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &obj_priv->fence); + if (ret) { + + drm_putback_buffer_objects(dev); + ret = 0; + goto fail; + } + + /* dereference he fence object */ + drm_fence_usage_deref_unlocked(&obj_priv->fence); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + ret = 0; + fail: + return ret; +} + +/* + * Depending on card genertation, chipset bugs, etc... the amount of vram + * accessible to the CPU can vary. This function is our best shot at figuring + * it out. Returns a value in KB. + */ +static uint32_t radeon_get_accessible_vram(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t aper_size; + u8 byte; + + if (dev_priv->chip_family >= CHIP_R600) + aper_size = RADEON_READ(R600_CONFIG_APER_SIZE) / 1024; + else + aper_size = RADEON_READ(RADEON_CONFIG_APER_SIZE) / 1024; + + /* Set HDP_APER_CNTL only on cards that are known not to be broken, + * that is has the 2nd generation multifunction PCI interface + */ + if (dev_priv->chip_family == CHIP_RV280 || + dev_priv->chip_family == CHIP_RV350 || + dev_priv->chip_family == CHIP_RV380 || + dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_RV410 || + dev_priv->chip_family >= CHIP_RS600) { + uint32_t temp = RADEON_READ(RADEON_HOST_PATH_CNTL); + temp |= RADEON_HDP_APER_CNTL; + RADEON_WRITE(RADEON_HOST_PATH_CNTL, temp); + return aper_size * 2; + } + + /* Older cards have all sorts of funny issues to deal with. First + * check if it's a multifunction card by reading the PCI config + * header type... Limit those to one aperture size + */ + pci_read_config_byte(dev->pdev, 0xe, &byte); + if (byte & 0x80) + return aper_size; + + /* Single function older card. We read HDP_APER_CNTL to see how the BIOS + * have set it up. We don't write this as it's broken on some ASICs but + * we expect the BIOS to have done the right thing (might be too optimistic...) + */ + if (RADEON_READ(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) + return aper_size * 2; + + return aper_size; +} + +/* code from the DDX - do memory sizing */ +void radeon_vram_setup(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t vram; + uint32_t accessible, bar_size; + + if ((dev_priv->chip_family <= CHIP_RV515) && (dev_priv->flags & RADEON_IS_IGP)) { + uint32_t tom = RADEON_READ(RADEON_NB_TOM); + + vram = (((tom >> 16) - (tom & 0xffff) + 1) << 6); + RADEON_WRITE(RADEON_CONFIG_MEMSIZE, vram * 1024); + } else { + if (dev_priv->chip_family >= CHIP_R600) + vram = RADEON_READ(R600_CONFIG_MEMSIZE) / 1024; + else { + vram = RADEON_READ(RADEON_CONFIG_MEMSIZE) / 1024; + + /* Some production boards of m6 will return 0 if it's 8 MB */ + if (vram == 0) { + vram = 8192; + RADEON_WRITE(RADEON_CONFIG_MEMSIZE, 0x800000); + } + } + } + + accessible = radeon_get_accessible_vram(dev); + + bar_size = drm_get_resource_len(dev, 0) / 1024; + if (bar_size == 0) + bar_size = 0x20000; + if (accessible > bar_size) + accessible = bar_size; + + DRM_INFO("Detected VRAM RAM=%dK, accessible=%uK, BAR=%uK\n", + vram, accessible, bar_size); + + dev_priv->mm.vram_offset = dev_priv->fb_aper_offset; + dev_priv->mm.vram_size = vram * 1024; + dev_priv->mm.vram_visible = accessible * 1024; + + +} + +static int radeon_gart_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + u32 base = 0; + + /* setup a 32MB GART */ + dev_priv->gart_size = dev_priv->mm.gart_size; + +#if __OS_HAS_AGP + /* setup VRAM vs GART here */ + if (dev_priv->flags & RADEON_IS_AGP) { + base = dev->agp->base; + if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { + DRM_INFO("Can't use agp base @0x%08xlx, won't fit\n", + dev->agp->base); + base = 0; + } + } +#endif + + if (base == 0) { + base = dev_priv->fb_location + dev_priv->fb_size; + if (base < dev_priv->fb_location || + ((base + dev_priv->gart_size) & 0xfffffffful) < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + /* start on the card */ + dev_priv->gart_vm_start = base & 0xffc00000u; + if (dev_priv->gart_vm_start != base) + DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", + base, dev_priv->gart_vm_start); + + /* if on PCIE we need to allocate an fb object for the PCIE GART table */ + if (dev_priv->flags & RADEON_IS_PCIE) { + ret = drm_buffer_object_create(dev, RADEON_PCIGART_TABLE_SIZE, + drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, + 0, 1, 0, &dev_priv->mm.pcie_table); + if (ret) + return -EINVAL; + + DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table, dev_priv->mm.pcie_table->offset); + ret = drm_bo_kmap(dev_priv->mm.pcie_table, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, + &dev_priv->mm.pcie_table_map); + if (ret) + return -EINVAL; + + dev_priv->pcigart_offset_set = 2; + dev_priv->gart_info.bus_addr = dev_priv->fb_location + dev_priv->mm.pcie_table->offset; + dev_priv->gart_info.addr = dev_priv->mm.pcie_table_map.virtual; + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; + dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; + memset(dev_priv->gart_info.addr, 0, RADEON_PCIGART_TABLE_SIZE); + } else if (!(dev_priv->flags & RADEON_IS_AGP)) { + /* allocate PCI GART table */ + dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); + ret = drm_ati_alloc_pcigart_table(dev, &dev_priv->gart_info); + if (ret) { + DRM_ERROR("cannot allocate PCI GART page!\n"); + return -EINVAL; + } + + dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + if (dev_priv->flags & RADEON_IS_IGPGART) + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; + else + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; + dev_priv->gart_info.addr = NULL; + dev_priv->gart_info.bus_addr = 0; + } + + /* gart values setup - start the GART */ + if (dev_priv->flags & RADEON_IS_AGP) { + radeon_set_pcigart(dev_priv, 0); + } else { + radeon_set_pcigart(dev_priv, 1); + } + + return 0; +} + +int radeon_alloc_gart_objects(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + + ret = drm_buffer_object_create(dev, RADEON_DEFAULT_RING_SIZE, + drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, + 0, 1, 0, &dev_priv->mm.ring); + if (ret) { + DRM_ERROR("failed to allocate ring\n"); + return -EINVAL; + } + + ret = drm_bo_kmap(dev_priv->mm.ring, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, + &dev_priv->mm.ring_map); + if (ret) { + DRM_ERROR("failed to map ring\n"); + return -EINVAL; + } + + ret = drm_buffer_object_create(dev, PAGE_SIZE, + drm_bo_type_kernel, + DRM_BO_FLAG_WRITE |DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, + 0, 1, 0, &dev_priv->mm.ring_read_ptr); + if (ret) { + DRM_ERROR("failed to allocate ring read\n"); + return -EINVAL; + } + + ret = drm_bo_kmap(dev_priv->mm.ring_read_ptr, 0, + PAGE_SIZE >> PAGE_SHIFT, + &dev_priv->mm.ring_read_ptr_map); + if (ret) { + DRM_ERROR("failed to map ring read\n"); + return -EINVAL; + } + + DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n", + dev_priv->mm.ring, dev_priv->mm.ring->offset, dev_priv->mm.ring_map.virtual, + dev_priv->mm.ring_read_ptr, dev_priv->mm.ring_read_ptr->offset, dev_priv->mm.ring_read_ptr_map.virtual); + + return 0; + +} + +/* init memory manager - start with all of VRAM and a 32MB GART aperture for now */ +int radeon_gem_mm_init(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + + /* size the mappable VRAM memory for now */ + radeon_vram_setup(dev); + + drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, /*dev_priv->mm.vram_offset >> PAGE_SHIFT,*/ + (dev_priv->mm.vram_visible) >> PAGE_SHIFT, + 0); + + + dev_priv->mm.gart_size = (32 * 1024 * 1024); + dev_priv->mm.gart_start = 0; + ret = radeon_gart_init(dev); + if (ret) + return -EINVAL; + + drm_bo_init_mm(dev, DRM_BO_MEM_TT, 0, + dev_priv->mm.gart_size >> PAGE_SHIFT, + 0); + + /* need to allocate some objects in the GART */ + /* ring + ring read ptr */ + ret = radeon_alloc_gart_objects(dev); + if (ret) + return -EINVAL; + return 0; +} + +void radeon_gem_mm_fini(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + mutex_lock(&dev->struct_mutex); + + if (dev_priv->mm.ring_read_ptr) { + drm_bo_kunmap(&dev_priv->mm.ring_read_ptr_map); + drm_bo_usage_deref_locked(&dev_priv->mm.ring_read_ptr); + } + + if (dev_priv->mm.ring) { + drm_bo_kunmap(&dev_priv->mm.ring_map); + drm_bo_usage_deref_locked(&dev_priv->mm.ring); + } + + if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { + DRM_DEBUG("delaying takedown of TTM memory\n"); + } + + if (dev_priv->flags & RADEON_IS_PCIE) { + if (dev_priv->mm.pcie_table) { + drm_bo_kunmap(&dev_priv->mm.pcie_table_map); + drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table); + } + } + + if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) { + DRM_DEBUG("delaying takedown of TTM memory\n"); + } + + mutex_unlock(&dev->struct_mutex); +} + +int radeon_gem_object_pin(struct drm_gem_object *obj, + uint32_t alignment) +{ + struct drm_radeon_gem_object *obj_priv; + int ret; + + obj_priv = obj->driver_private; + + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, 0, NULL); + + return ret; +} + -- cgit v1.2.3 From 38835f9cd2b44cfb6587a52ba1bfe292b958d0e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 28 Jul 2008 15:21:13 +1000 Subject: radeon command submission start take code from Jerome munge into a TTM IB re-use --- linux-core/radeon_gem.c | 211 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 188 insertions(+), 23 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index d536aed2..021bb9f9 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -27,6 +27,9 @@ #include "radeon_drm.h" #include "radeon_drv.h" +static int radeon_gem_ib_init(struct drm_device *dev); +static int radeon_gem_ib_destroy(struct drm_device *dev); + int radeon_gem_init_object(struct drm_gem_object *obj) { struct drm_radeon_gem_object *obj_priv; @@ -513,19 +516,19 @@ static int radeon_gart_init(struct drm_device *dev) ret = drm_buffer_object_create(dev, RADEON_PCIGART_TABLE_SIZE, drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, - 0, 1, 0, &dev_priv->mm.pcie_table); + 0, 1, 0, &dev_priv->mm.pcie_table.bo); if (ret) return -EINVAL; - DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table, dev_priv->mm.pcie_table->offset); - ret = drm_bo_kmap(dev_priv->mm.pcie_table, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, - &dev_priv->mm.pcie_table_map); + DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset); + ret = drm_bo_kmap(dev_priv->mm.pcie_table.bo, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, + &dev_priv->mm.pcie_table.kmap); if (ret) return -EINVAL; dev_priv->pcigart_offset_set = 2; - dev_priv->gart_info.bus_addr = dev_priv->fb_location + dev_priv->mm.pcie_table->offset; - dev_priv->gart_info.addr = dev_priv->mm.pcie_table_map.virtual; + dev_priv->gart_info.bus_addr = dev_priv->fb_location + dev_priv->mm.pcie_table.bo->offset; + dev_priv->gart_info.addr = dev_priv->mm.pcie_table.kmap.virtual; dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; memset(dev_priv->gart_info.addr, 0, RADEON_PCIGART_TABLE_SIZE); @@ -566,14 +569,14 @@ int radeon_alloc_gart_objects(struct drm_device *dev) drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, - 0, 1, 0, &dev_priv->mm.ring); + 0, 1, 0, &dev_priv->mm.ring.bo); if (ret) { DRM_ERROR("failed to allocate ring\n"); return -EINVAL; } - ret = drm_bo_kmap(dev_priv->mm.ring, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, - &dev_priv->mm.ring_map); + ret = drm_bo_kmap(dev_priv->mm.ring.bo, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT, + &dev_priv->mm.ring.kmap); if (ret) { DRM_ERROR("failed to map ring\n"); return -EINVAL; @@ -583,24 +586,26 @@ int radeon_alloc_gart_objects(struct drm_device *dev) drm_bo_type_kernel, DRM_BO_FLAG_WRITE |DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, - 0, 1, 0, &dev_priv->mm.ring_read_ptr); + 0, 1, 0, &dev_priv->mm.ring_read.bo); if (ret) { DRM_ERROR("failed to allocate ring read\n"); return -EINVAL; } - ret = drm_bo_kmap(dev_priv->mm.ring_read_ptr, 0, + ret = drm_bo_kmap(dev_priv->mm.ring_read.bo, 0, PAGE_SIZE >> PAGE_SHIFT, - &dev_priv->mm.ring_read_ptr_map); + &dev_priv->mm.ring_read.kmap); if (ret) { DRM_ERROR("failed to map ring read\n"); return -EINVAL; } DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n", - dev_priv->mm.ring, dev_priv->mm.ring->offset, dev_priv->mm.ring_map.virtual, - dev_priv->mm.ring_read_ptr, dev_priv->mm.ring_read_ptr->offset, dev_priv->mm.ring_read_ptr_map.virtual); + dev_priv->mm.ring.bo, dev_priv->mm.ring.bo->offset, dev_priv->mm.ring.kmap.virtual, + dev_priv->mm.ring_read.bo, dev_priv->mm.ring_read.bo->offset, dev_priv->mm.ring_read.kmap.virtual); + /* init the indirect buffers */ + radeon_gem_ib_init(dev); return 0; } @@ -634,6 +639,8 @@ int radeon_gem_mm_init(struct drm_device *dev) ret = radeon_alloc_gart_objects(dev); if (ret) return -EINVAL; + + return 0; } @@ -641,16 +648,19 @@ void radeon_gem_mm_fini(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; + radeon_gem_ib_destroy(dev); + mutex_lock(&dev->struct_mutex); - if (dev_priv->mm.ring_read_ptr) { - drm_bo_kunmap(&dev_priv->mm.ring_read_ptr_map); - drm_bo_usage_deref_locked(&dev_priv->mm.ring_read_ptr); + + if (dev_priv->mm.ring_read.bo) { + drm_bo_kunmap(&dev_priv->mm.ring_read.kmap); + drm_bo_usage_deref_locked(&dev_priv->mm.ring_read.bo); } - if (dev_priv->mm.ring) { - drm_bo_kunmap(&dev_priv->mm.ring_map); - drm_bo_usage_deref_locked(&dev_priv->mm.ring); + if (dev_priv->mm.ring.bo) { + drm_bo_kunmap(&dev_priv->mm.ring.kmap); + drm_bo_usage_deref_locked(&dev_priv->mm.ring.bo); } if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) { @@ -658,9 +668,9 @@ void radeon_gem_mm_fini(struct drm_device *dev) } if (dev_priv->flags & RADEON_IS_PCIE) { - if (dev_priv->mm.pcie_table) { - drm_bo_kunmap(&dev_priv->mm.pcie_table_map); - drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table); + if (dev_priv->mm.pcie_table.bo) { + drm_bo_kunmap(&dev_priv->mm.pcie_table.kmap); + drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table.bo); } } @@ -685,3 +695,158 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, return ret; } +#define RADEON_IB_MEMORY (1*1024*1024) +#define RADEON_IB_SIZE (65536) + +#define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) + +int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) +{ + int i, index = -1; + int ret; + drm_radeon_private_t *dev_priv = dev->dev_private; + + for (i = 0; i < RADEON_NUM_IB; i++) { + if (!(dev_priv->ib_alloc_bitmap & (1 << i))){ + index = i; + break; + } + } + + /* if all in use we need to wait */ + if (index == -1) { + for (i = 0; i < RADEON_NUM_IB; i++) { + if (dev_priv->ib_alloc_bitmap & (1 << i)) { + mutex_lock(&dev_priv->ib_objs[i]->bo->mutex); + ret = drm_bo_wait(dev_priv->ib_objs[i]->bo, 0, 1, 0, 0); + mutex_unlock(&dev_priv->ib_objs[i]->bo->mutex); + if (ret) + continue; + dev_priv->ib_alloc_bitmap &= ~(1 << i); + index = i; + break; + } + } + } + + if (index == -1) { + DRM_ERROR("Major case fail to allocate IB from freelist %x\n", dev_priv->ib_alloc_bitmap); + return -EINVAL; + } + + + if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) + return -EINVAL; + + *ib = dev_priv->ib_objs[index]->kmap.virtual; + dev_priv->ib_alloc_bitmap |= (1 << i); + return 0; +} + +static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_fence_object *fence; + int ret; + int i; + RING_LOCALS; + + for (i = 0; i < RADEON_NUM_IB; i++) { + + if (dev_priv->ib_objs[i]->kmap.virtual == ib) { + ret = drm_bo_do_validate(dev_priv->ib_objs[i]->bo, 0, + DRM_BO_FLAG_NO_EVICT, + 0, 0, NULL); + if (ret) + DRM_ERROR("FAiled to validate\n"); + + DRM_DEBUG("validated IB %x, %d\n", dev_priv->ib_objs[i]->bo->offset, dwords); + BEGIN_RING(4); + + OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); + OUT_RING(dev_priv->gart_vm_start + dev_priv->ib_objs[i]->bo->offset); + OUT_RING(dwords); + OUT_RING(CP_PACKET2()); + + ADVANCE_RING(); + + COMMIT_RING(); + + /* emit a fence object */ + ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); + if (ret) { + + drm_putback_buffer_objects(dev); + } + /* dereference the fence object */ + if (fence) + drm_fence_usage_deref_unlocked(&fence); + } + } + +} + +static int radeon_gem_ib_destroy(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int i; + + if (dev_priv->ib_objs) { + for (i = 0; i < RADEON_NUM_IB; i++) { + if (dev_priv->ib_objs[i]) { + drm_bo_kunmap(&dev_priv->ib_objs[i]->kmap); + drm_bo_usage_deref_unlocked(&dev_priv->ib_objs[i]->bo); + } + drm_free(dev_priv->ib_objs[i], sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); + } + drm_free(dev_priv->ib_objs, RADEON_NUM_IB*sizeof(struct radeon_mm_obj *), DRM_MEM_DRIVER); + } + dev_priv->ib_objs = NULL; + return 0; +} + +/* allocate 1MB of 64k IBs the the kernel can keep mapped */ +static int radeon_gem_ib_init(struct drm_device *dev) +{ + + drm_radeon_private_t *dev_priv = dev->dev_private; + int i; + int ret; + + dev_priv->ib_objs = drm_calloc(RADEON_NUM_IB, sizeof(struct radeon_mm_obj *), DRM_MEM_DRIVER); + if (!dev_priv->ib_objs) + goto free_all; + + for (i = 0; i < RADEON_NUM_IB; i++) { + dev_priv->ib_objs[i] = drm_calloc(1, sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); + if (!dev_priv->ib_objs[i]) + goto free_all; + + ret = drm_buffer_object_create(dev, RADEON_IB_SIZE, + drm_bo_type_kernel, + DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_MAPPABLE, 0, + 0, 0, &dev_priv->ib_objs[i]->bo); + if (ret) + goto free_all; + + ret = drm_bo_kmap(dev_priv->ib_objs[i]->bo, 0, RADEON_IB_SIZE >> PAGE_SHIFT, + &dev_priv->ib_objs[i]->kmap); + + if (ret) + goto free_all; + } + + dev_priv->ib_alloc_bitmap = 0; + + dev_priv->cs.ib_get = radeon_gem_ib_get; + dev_priv->cs.ib_free = radeon_gem_ib_free; + + radeon_cs_init(dev); + return 0; + +free_all: + radeon_gem_ib_destroy(dev); + return -ENOMEM; +} + -- cgit v1.2.3 From 4234f82acc70f41e005d8cc301da56634352425c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Jul 2008 16:51:47 +1000 Subject: radeon_cs: add relocate hook for mm and non-mm relocations --- linux-core/radeon_gem.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 021bb9f9..859c1656 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -805,10 +805,45 @@ static int radeon_gem_ib_destroy(struct drm_device *dev) return 0; } +static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_priv, + uint32_t *reloc, uint32_t *offset) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + /* relocate the handle */ + int domains = reloc[2]; + struct drm_gem_object *obj; + int flags = 0; + int ret; + struct drm_radeon_gem_object *obj_priv; + + obj = drm_gem_object_lookup(dev, file_priv, reloc[1]); + if (!obj) + return false; + + obj_priv = obj->driver_private; + if (domains == RADEON_GEM_DOMAIN_VRAM) { + flags = DRM_BO_FLAG_MEM_VRAM; + } else { + flags = DRM_BO_FLAG_MEM_TT; + } + + ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0, NULL); + if (ret) + return ret; + + if (flags == DRM_BO_FLAG_MEM_VRAM) + *offset = obj_priv->bo->offset + dev_priv->fb_location; + else + *offset = obj_priv->bo->offset + dev_priv->gart_vm_start; + + /* BAD BAD BAD - LINKED LIST THE OBJS and UNREF ONCE IB is SUBMITTED */ + drm_gem_object_unreference(obj); + return 0; +} + /* allocate 1MB of 64k IBs the the kernel can keep mapped */ static int radeon_gem_ib_init(struct drm_device *dev) { - drm_radeon_private_t *dev_priv = dev->dev_private; int i; int ret; @@ -843,6 +878,7 @@ static int radeon_gem_ib_init(struct drm_device *dev) dev_priv->cs.ib_free = radeon_gem_ib_free; radeon_cs_init(dev); + dev_priv->cs.relocate = radeon_gem_relocate; return 0; free_all: -- cgit v1.2.3 From 0452be882607f2d1601f4e592a11ccf543f5f9ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 29 Jul 2008 18:05:11 +1000 Subject: radeon: move code around putting emit into cs --- linux-core/radeon_gem.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 859c1656..9d122ac5 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -700,7 +700,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, #define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) -int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) +int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32_t *card_offset) { int i, index = -1; int ret; @@ -738,6 +738,15 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords) if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) return -EINVAL; + ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0, + DRM_BO_FLAG_NO_EVICT, + 0, 0, NULL); + if (ret) { + DRM_ERROR("Failed to validate IB %d\n", index); + return -EINVAL; + } + + *card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; *ib = dev_priv->ib_objs[index]->kmap.virtual; dev_priv->ib_alloc_bitmap |= (1 << i); return 0; @@ -754,24 +763,6 @@ static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords for (i = 0; i < RADEON_NUM_IB; i++) { if (dev_priv->ib_objs[i]->kmap.virtual == ib) { - ret = drm_bo_do_validate(dev_priv->ib_objs[i]->bo, 0, - DRM_BO_FLAG_NO_EVICT, - 0, 0, NULL); - if (ret) - DRM_ERROR("FAiled to validate\n"); - - DRM_DEBUG("validated IB %x, %d\n", dev_priv->ib_objs[i]->bo->offset, dwords); - BEGIN_RING(4); - - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(dev_priv->gart_vm_start + dev_priv->ib_objs[i]->bo->offset); - OUT_RING(dwords); - OUT_RING(CP_PACKET2()); - - ADVANCE_RING(); - - COMMIT_RING(); - /* emit a fence object */ ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); if (ret) { -- cgit v1.2.3 From fb5542aaa87aca9b6b312968abe0a6044812cf0e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 30 Jul 2008 17:06:11 +1000 Subject: radeon: hack gem to get an offset back for Mesa. --- linux-core/radeon_gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 9d122ac5..e06cba5b 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -243,9 +243,12 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); /* validate into a pin with no fence */ - ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, - 0, NULL); + if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, + 0, NULL); + } else + ret = 0; args->offset = obj_priv->bo->offset; DRM_DEBUG("got here %p %p\n", obj, obj_priv->bo); -- cgit v1.2.3 From 9b8d71b5eb09857b07409731d3de182751f712a2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 31 Jul 2008 12:54:48 +1000 Subject: TTM: remove API and userspace objects. This removes all the TTM userspace API and all userspace objects. It also removes the drm_bo_lock.c code --- linux-core/radeon_gem.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index e06cba5b..1aa3afbf 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -245,8 +245,7 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, - 0, NULL); + DRM_BO_HINT_DONT_FENCE, 0); } else ret = 0; @@ -276,8 +275,7 @@ int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, /* validate into a pin with no fence */ ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, - 0, NULL); + DRM_BO_HINT_DONT_FENCE, 0); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); @@ -321,7 +319,7 @@ int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, //VB_AGE_TEST_WITH_RETURN(dev_priv); ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - 0 , 0, NULL); + 0 , 0); if (ret) return ret; @@ -693,7 +691,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, obj_priv = obj->driver_private; ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, 0, NULL); + DRM_BO_HINT_DONT_FENCE, 0); return ret; } @@ -743,7 +741,7 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32 ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0, DRM_BO_FLAG_NO_EVICT, - 0, 0, NULL); + 0, 0); if (ret) { DRM_ERROR("Failed to validate IB %d\n", index); return -EINVAL; @@ -761,7 +759,6 @@ static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords struct drm_fence_object *fence; int ret; int i; - RING_LOCALS; for (i = 0; i < RADEON_NUM_IB; i++) { @@ -821,7 +818,7 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri flags = DRM_BO_FLAG_MEM_TT; } - ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0, NULL); + ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0); if (ret) return ret; -- cgit v1.2.3 From 8c042a0b0531117f2663ae6932d299cb47941607 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 6 Aug 2008 15:59:31 +1000 Subject: radeon: fixup PCI GART table with GEM enabled --- linux-core/radeon_gem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 1aa3afbf..1ee48514 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -485,6 +485,7 @@ static int radeon_gart_init(struct drm_device *dev) /* setup a 32MB GART */ dev_priv->gart_size = dev_priv->mm.gart_size; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; #if __OS_HAS_AGP /* setup VRAM vs GART here */ @@ -547,8 +548,8 @@ static int radeon_gart_init(struct drm_device *dev) dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; else dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; - dev_priv->gart_info.addr = NULL; - dev_priv->gart_info.bus_addr = 0; + dev_priv->gart_info.addr = dev_priv->gart_info.table_handle->vaddr; + dev_priv->gart_info.bus_addr = dev_priv->gart_info.table_handle->busaddr; } /* gart values setup - start the GART */ @@ -843,7 +844,7 @@ static int radeon_gem_ib_init(struct drm_device *dev) if (!dev_priv->ib_objs) goto free_all; - for (i = 0; i < RADEON_NUM_IB; i++) { + for (i = 0; i < RADEON_NUM_IB; i++) { dev_priv->ib_objs[i] = drm_calloc(1, sizeof(struct radeon_mm_obj), DRM_MEM_DRIVER); if (!dev_priv->ib_objs[i]) goto free_all; -- cgit v1.2.3 From 957c71ff52e93bb2c1bc01b99d29d763d0ef3899 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:10:11 +1000 Subject: radeon: FEDORA: add old DMA buffers on top of GEM This really shouldn't go upstream, it just lets me run the old 3D driver on GEM setup system --- linux-core/radeon_gem.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 1ee48514..250e6852 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -29,6 +29,8 @@ static int radeon_gem_ib_init(struct drm_device *dev); static int radeon_gem_ib_destroy(struct drm_device *dev); +static int radeon_gem_dma_bufs_init(struct drm_device *dev); +static void radeon_gem_dma_bufs_destroy(struct drm_device *dev); int radeon_gem_init_object(struct drm_gem_object *obj) { @@ -608,6 +610,7 @@ int radeon_alloc_gart_objects(struct drm_device *dev) /* init the indirect buffers */ radeon_gem_ib_init(dev); + radeon_gem_dma_bufs_init(dev); return 0; } @@ -650,6 +653,7 @@ void radeon_gem_mm_fini(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; + radeon_gem_dma_bufs_destroy(dev); radeon_gem_ib_destroy(dev); mutex_lock(&dev->struct_mutex); @@ -878,3 +882,247 @@ free_all: return -ENOMEM; } +#define RADEON_DMA_BUFFER_SIZE (64 * 1024) +#define RADEON_DMA_BUFFER_COUNT (16) + + +/** + * Cleanup after an error on one of the addbufs() functions. + * + * \param dev DRM device. + * \param entry buffer entry where the error occurred. + * + * Frees any pages and buffers associated with the given entry. + */ +static void drm_cleanup_buf_error(struct drm_device * dev, + struct drm_buf_entry * entry) +{ + int i; + + if (entry->seg_count) { + for (i = 0; i < entry->seg_count; i++) { + if (entry->seglist[i]) { + drm_pci_free(dev, entry->seglist[i]); + } + } + drm_free(entry->seglist, + entry->seg_count * + sizeof(*entry->seglist), DRM_MEM_SEGS); + + entry->seg_count = 0; + } + + if (entry->buf_count) { + for (i = 0; i < entry->buf_count; i++) { + if (entry->buflist[i].dev_private) { + drm_free(entry->buflist[i].dev_private, + entry->buflist[i].dev_priv_size, + DRM_MEM_BUFS); + } + } + drm_free(entry->buflist, + entry->buf_count * + sizeof(*entry->buflist), DRM_MEM_BUFS); + + entry->buf_count = 0; + } +} + +static int radeon_gem_addbufs(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + struct drm_device_dma *dma = dev->dma; + struct drm_buf_entry *entry; + struct drm_buf *buf; + unsigned long offset; + unsigned long agp_offset; + int count; + int order; + int size; + int alignment; + int page_order; + int total; + int byte_count; + int i; + struct drm_buf **temp_buflist; + + if (!dma) + return -EINVAL; + + count = RADEON_DMA_BUFFER_COUNT; + order = drm_order(RADEON_DMA_BUFFER_SIZE); + size = 1 << order; + + alignment = PAGE_ALIGN(size); + page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; + total = PAGE_SIZE << page_order; + + byte_count = 0; + agp_offset = dev_priv->mm.dma_bufs.bo->offset; + + DRM_DEBUG("count: %d\n", count); + DRM_DEBUG("order: %d\n", order); + DRM_DEBUG("size: %d\n", size); + DRM_DEBUG("agp_offset: %lu\n", agp_offset); + DRM_DEBUG("alignment: %d\n", alignment); + DRM_DEBUG("page_order: %d\n", page_order); + DRM_DEBUG("total: %d\n", total); + + if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) + return -EINVAL; + if (dev->queue_count) + return -EBUSY; /* Not while in use */ + + spin_lock(&dev->count_lock); + if (dev->buf_use) { + spin_unlock(&dev->count_lock); + return -EBUSY; + } + atomic_inc(&dev->buf_alloc); + spin_unlock(&dev->count_lock); + + mutex_lock(&dev->struct_mutex); + entry = &dma->bufs[order]; + if (entry->buf_count) { + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; /* May only call once for each order */ + } + + if (count < 0 || count > 4096) { + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -EINVAL; + } + + entry->buflist = drm_alloc(count * sizeof(*entry->buflist), + DRM_MEM_BUFS); + if (!entry->buflist) { + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + memset(entry->buflist, 0, count * sizeof(*entry->buflist)); + + entry->buf_size = size; + entry->page_order = page_order; + + offset = 0; + + while (entry->buf_count < count) { + buf = &entry->buflist[entry->buf_count]; + buf->idx = dma->buf_count + entry->buf_count; + buf->total = alignment; + buf->order = order; + buf->used = 0; + + buf->offset = (dma->byte_count + offset); + buf->bus_address = dev_priv->gart_vm_start + agp_offset + offset; + buf->address = (void *)(agp_offset + offset); + buf->next = NULL; + buf->waiting = 0; + buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); + buf->file_priv = NULL; + + buf->dev_priv_size = dev->driver->dev_priv_size; + buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); + if (!buf->dev_private) { + /* Set count correctly so we free the proper amount. */ + entry->buf_count = count; + drm_cleanup_buf_error(dev, entry); + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + + memset(buf->dev_private, 0, buf->dev_priv_size); + + DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); + + offset += alignment; + entry->buf_count++; + byte_count += PAGE_SIZE << page_order; + } + + DRM_DEBUG("byte_count: %d\n", byte_count); + + temp_buflist = drm_realloc(dma->buflist, + dma->buf_count * sizeof(*dma->buflist), + (dma->buf_count + entry->buf_count) + * sizeof(*dma->buflist), DRM_MEM_BUFS); + if (!temp_buflist) { + /* Free the entry because it isn't valid */ + drm_cleanup_buf_error(dev, entry); + mutex_unlock(&dev->struct_mutex); + atomic_dec(&dev->buf_alloc); + return -ENOMEM; + } + dma->buflist = temp_buflist; + + for (i = 0; i < entry->buf_count; i++) { + dma->buflist[i + dma->buf_count] = &entry->buflist[i]; + } + + dma->buf_count += entry->buf_count; + dma->seg_count += entry->seg_count; + dma->page_count += byte_count >> PAGE_SHIFT; + dma->byte_count += byte_count; + + DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); + DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); + + mutex_unlock(&dev->struct_mutex); + + dma->flags = _DRM_DMA_USE_SG; + atomic_dec(&dev->buf_alloc); + return 0; +} + +static int radeon_gem_dma_bufs_init(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + int size = RADEON_DMA_BUFFER_SIZE * RADEON_DMA_BUFFER_COUNT; + int ret; + + ret = drm_dma_setup(dev); + if (ret < 0) + return ret; + + ret = drm_buffer_object_create(dev, size, drm_bo_type_device, + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_NO_EVICT | + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE, 0, + 0, 0, &dev_priv->mm.dma_bufs.bo); + if (ret) { + DRM_ERROR("Failed to create DMA bufs\n"); + return -ENOMEM; + } + + ret = drm_bo_kmap(dev_priv->mm.dma_bufs.bo, 0, size >> PAGE_SHIFT, + &dev_priv->mm.dma_bufs.kmap); + if (ret) { + DRM_ERROR("Failed to mmap DMA buffers\n"); + return -ENOMEM; + } + DRM_DEBUG("\n"); + radeon_gem_addbufs(dev); + + DRM_DEBUG("%x %d\n", dev_priv->mm.dma_bufs.bo->map_list.hash.key, size); + dev->agp_buffer_token = dev_priv->mm.dma_bufs.bo->map_list.hash.key << PAGE_SHIFT; + dev_priv->mm.fake_agp_map.handle = dev_priv->mm.dma_bufs.kmap.virtual; + dev_priv->mm.fake_agp_map.size = size; + + dev->agp_buffer_map = &dev_priv->mm.fake_agp_map; + + return 0; +} + +static void radeon_gem_dma_bufs_destroy(struct drm_device *dev) +{ + + struct drm_radeon_private *dev_priv = dev->dev_private; + drm_dma_takedown(dev); + + drm_bo_kunmap(&dev_priv->mm.dma_bufs.kmap); + drm_bo_usage_deref_unlocked(&dev_priv->mm.dma_bufs.bo); +} -- cgit v1.2.3 From 18020e5e9647e218caf8f1566cdc053aac126f23 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:12:36 +1000 Subject: radeon: make buffer swap for older drivers work again on GEM --- linux-core/radeon_gem.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 250e6852..058131e9 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1126,3 +1126,50 @@ static void radeon_gem_dma_bufs_destroy(struct drm_device *dev) drm_bo_kunmap(&dev_priv->mm.dma_bufs.kmap); drm_bo_usage_deref_unlocked(&dev_priv->mm.dma_bufs.bo); } + + +static struct drm_gem_object *gem_object_get(struct drm_device *dev, uint32_t name) +{ + struct drm_gem_object *obj; + + spin_lock(&dev->object_name_lock); + obj = idr_find(&dev->object_name_idr, name); + if (obj) + drm_gem_object_reference(obj); + spin_unlock(&dev->object_name_lock); + return obj; +} + +void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_master_private *master_priv = master->driver_priv; + drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + + /* update front_pitch_offset and back_pitch_offset */ + DRM_ERROR("old front %x back %x\n", dev_priv->front_pitch_offset, dev_priv->back_pitch_offset); + obj = gem_object_get(dev, sarea_priv->front_handle); + if (obj) { + obj_priv = obj->driver_private; + + dev_priv->front_offset = obj_priv->bo->offset; + dev_priv->front_pitch_offset = (((sarea_priv->front_pitch / 64) << 22) | + ((obj_priv->bo->offset + + dev_priv->fb_location) >> 10)); + drm_gem_object_unreference(obj); + } + + obj = gem_object_get(dev, sarea_priv->back_handle); + if (obj) { + obj_priv = obj->driver_private; + dev_priv->back_offset = obj_priv->bo->offset; + dev_priv->back_pitch_offset = (((sarea_priv->back_pitch / 64) << 22) | + ((obj_priv->bo->offset + + dev_priv->fb_location) >> 10)); + drm_gem_object_unreference(obj); + } + dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; + +} -- cgit v1.2.3 From b0ee12e6bb55655c92184483a065780529c8aa63 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:14:14 +1000 Subject: radeon: use mm_enabled variable to denote memory manager running --- linux-core/radeon_gem.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 058131e9..ebba3cfe 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -645,7 +645,7 @@ int radeon_gem_mm_init(struct drm_device *dev) if (ret) return -EINVAL; - + dev_priv->mm_enabled = true; return 0; } @@ -685,6 +685,9 @@ void radeon_gem_mm_fini(struct drm_device *dev) } mutex_unlock(&dev->struct_mutex); + + drm_bo_driver_finish(dev); + dev_priv->mm_enabled = false; } int radeon_gem_object_pin(struct drm_gem_object *obj, -- cgit v1.2.3 From 58df2fa0ecc7e4dac83b4e7a72d70c3ea41c7ed2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:14:56 +1000 Subject: radeon: remove debugging --- linux-core/radeon_gem.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index ebba3cfe..4b9b1d38 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1152,7 +1152,6 @@ void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master struct drm_radeon_gem_object *obj_priv; /* update front_pitch_offset and back_pitch_offset */ - DRM_ERROR("old front %x back %x\n", dev_priv->front_pitch_offset, dev_priv->back_pitch_offset); obj = gem_object_get(dev, sarea_priv->front_handle); if (obj) { obj_priv = obj->driver_private; -- cgit v1.2.3 From 0580785030714f10f624ad329354dc7c688c32ad Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 09:15:28 +1000 Subject: radeon: FEDORA: patch to make 3D driver work set gart buffers start --- linux-core/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 4b9b1d38..df4ed4ce 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1116,7 +1116,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) dev_priv->mm.fake_agp_map.size = size; dev->agp_buffer_map = &dev_priv->mm.fake_agp_map; - + dev_priv->gart_buffers_offset = dev_priv->mm.dma_bufs.bo->offset + dev_priv->gart_vm_start; return 0; } -- cgit v1.2.3 From 30ff279e42b3b0608e8ff6620d2958c174449798 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 14 Aug 2008 14:43:51 +1000 Subject: radeon: add support for memory map init --- linux-core/radeon_gem.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index df4ed4ce..bf8fb2e9 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -615,6 +615,90 @@ int radeon_alloc_gart_objects(struct drm_device *dev) } +static void radeon_init_memory_map(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 mem_size, aper_size; + + dev_priv->mc_fb_location = radeon_read_fb_location(dev_priv); + radeon_read_agp_location(dev_priv, &dev_priv->mc_agp_loc_lo, &dev_priv->mc_agp_loc_hi); + + if (dev_priv->chip_family >= CHIP_R600) { + mem_size = RADEON_READ(R600_CONFIG_MEMSIZE); + aper_size = RADEON_READ(R600_CONFIG_APER_SIZE); + } else { + mem_size = RADEON_READ(RADEON_CONFIG_MEMSIZE); + aper_size = RADEON_READ(RADEON_CONFIG_APER_SIZE); + } + + /* M6s report illegal memory size */ + if (mem_size == 0) + mem_size = 8 * 1024 * 1024; + + /* for RN50/M6/M7 - Novell bug 204882 */ + if (aper_size > mem_size) + mem_size = aper_size; + + if ((dev_priv->chip_family != CHIP_RS600) && + (dev_priv->chip_family != CHIP_RS690) && + (dev_priv->chip_family != CHIP_RS740)) { + if (dev_priv->flags & RADEON_IS_IGP) + dev_priv->mc_fb_location = RADEON_READ(RADEON_NB_TOM); + else { + uint32_t aper0_base; + + if (dev_priv->chip_family >= CHIP_R600) + aper0_base = RADEON_READ(R600_CONFIG_F0_BASE); + else + aper0_base = RADEON_READ(RADEON_CONFIG_APER_0_BASE); + + + /* Some chips have an "issue" with the memory controller, the + * location must be aligned to the size. We just align it down, + * too bad if we walk over the top of system memory, we don't + * use DMA without a remapped anyway. + * Affected chips are rv280, all r3xx, and all r4xx, but not IGP + */ + if (dev_priv->chip_family == CHIP_RV280 || + dev_priv->chip_family == CHIP_R300 || + dev_priv->chip_family == CHIP_R350 || + dev_priv->chip_family == CHIP_RV350 || + dev_priv->chip_family == CHIP_RV380 || + dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_RV410) + aper0_base &= ~(mem_size - 1); + + if (dev_priv->chip_family >= CHIP_R600) { + dev_priv->mc_fb_location = (aper0_base >> 24) | + (((aper0_base + mem_size - 1) & 0xff000000U) >> 8); + } else { + dev_priv->mc_fb_location = (aper0_base >> 16) | + ((aper0_base + mem_size - 1) & 0xffff0000U); + } + } + } + + if (dev_priv->chip_family >= CHIP_R600) + dev_priv->fb_location = (dev_priv->mc_fb_location & 0xffff) << 24; + else + dev_priv->fb_location = (dev_priv->mc_fb_location & 0xffff) << 16; + + if (radeon_is_avivo(dev_priv)) { + if (dev_priv->chip_family >= CHIP_R600) + RADEON_WRITE(R600_HDP_NONSURFACE_BASE, (dev_priv->mc_fb_location << 16) & 0xff0000); + else + RADEON_WRITE(AVIVO_HDP_FB_LOCATION, dev_priv->mc_fb_location); + } + + radeon_write_fb_location(dev_priv, dev_priv->mc_fb_location); + + dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; + dev_priv->fb_size = + ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) + - dev_priv->fb_location; + +} + /* init memory manager - start with all of VRAM and a 32MB GART aperture for now */ int radeon_gem_mm_init(struct drm_device *dev) { @@ -624,6 +708,8 @@ int radeon_gem_mm_init(struct drm_device *dev) /* size the mappable VRAM memory for now */ radeon_vram_setup(dev); + radeon_init_memory_map(dev); + drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, /*dev_priv->mm.vram_offset >> PAGE_SHIFT,*/ (dev_priv->mm.vram_visible) >> PAGE_SHIFT, 0); -- cgit v1.2.3 From 2030db75328b7d896a5dd030fc171020b33149e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 15 Aug 2008 09:56:42 +1000 Subject: radeon: reserve 64k of VRAM for now for text mode so we don't trample it need to revisit this later I'm sure --- linux-core/radeon_gem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index bf8fb2e9..6a7529cd 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -704,14 +704,18 @@ int radeon_gem_mm_init(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; int ret; + u32 pg_offset; /* size the mappable VRAM memory for now */ radeon_vram_setup(dev); radeon_init_memory_map(dev); - drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, /*dev_priv->mm.vram_offset >> PAGE_SHIFT,*/ - (dev_priv->mm.vram_visible) >> PAGE_SHIFT, +#define VRAM_RESERVE_TEXT (64*1024) + dev_priv->mm.vram_visible -= VRAM_RESERVE_TEXT; + pg_offset = VRAM_RESERVE_TEXT >> PAGE_SHIFT; + drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, pg_offset, /*dev_priv->mm.vram_offset >> PAGE_SHIFT,*/ + ((dev_priv->mm.vram_visible) >> PAGE_SHIFT) - 16, 0); -- cgit v1.2.3 From aed70622ab33500721a30b06ec3783c581615cbb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 17 Aug 2008 18:09:07 -0400 Subject: radeon: first pass at bios scratch regs - todo: updated connected status --- linux-core/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 6a7529cd..d572008a 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -225,7 +225,7 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, args->addr_ptr = (uint64_t) addr; return 0; - + } int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, -- cgit v1.2.3 From 361ab10d2fb0c7ad73e54d92af2563194dbf7080 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 26 Aug 2008 17:39:00 +1000 Subject: radeon: fixup domains and use them properly --- linux-core/radeon_gem.c | 143 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 37 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index d572008a..eceb5207 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -82,16 +82,18 @@ struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, int ret; uint32_t flags; - DRM_DEBUG("size 0x%x, alignment %d, initial_domain %d\n", size, alignment, initial_domain); obj = drm_gem_object_alloc(dev, size); if (!obj) return NULL;; obj_priv = obj->driver_private; + flags = DRM_BO_FLAG_MAPPABLE; if (initial_domain == RADEON_GEM_DOMAIN_VRAM) - flags = DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE; + flags |= DRM_BO_FLAG_MEM_VRAM; + else if (initial_domain == RADEON_GEM_DOMAIN_GTT) + flags |= DRM_BO_FLAG_MEM_TT; else - flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE; + flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED; flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE; /* create a TTM BO */ @@ -102,6 +104,7 @@ struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, if (ret) goto fail; + DRM_DEBUG("%p : size 0x%x, alignment %d, initial_domain %d\n", obj_priv->bo, size, alignment, initial_domain); return obj; fail: @@ -144,6 +147,55 @@ fail: return ret; } +int radeon_gem_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain, uint32_t *flags_p, bool unfenced) +{ + struct drm_device *dev = obj->dev; + drm_radeon_private_t *dev_priv = dev->dev_private; + struct drm_radeon_gem_object *obj_priv; + uint32_t flags = 0; + int ret; + + obj_priv = obj->driver_private; + + /* work out where to validate the buffer to */ + if (write_domain) { /* write domains always win */ + if (write_domain == RADEON_GEM_DOMAIN_VRAM) + flags = DRM_BO_FLAG_MEM_VRAM; + else if (write_domain == RADEON_GEM_DOMAIN_GTT) + flags = DRM_BO_FLAG_MEM_TT; // need a can write gart check + else + return -EINVAL; // we can't write to system RAM + } else { + /* okay for a read domain - prefer wherever the object is now or close enough */ + if ((read_domains == 0) || (read_domains == RADEON_GEM_DOMAIN_CPU)) + return -EINVAL; + + /* simple case no choice in domains */ + if (read_domains == RADEON_GEM_DOMAIN_VRAM) + flags = DRM_BO_FLAG_MEM_VRAM; + else if (read_domains == RADEON_GEM_DOMAIN_GTT) + flags = DRM_BO_FLAG_MEM_TT; + else if ((obj_priv->bo->mem.mem_type == DRM_BO_MEM_VRAM) && (read_domains & RADEON_GEM_DOMAIN_VRAM)) + flags = DRM_BO_FLAG_MEM_VRAM; + else if ((obj_priv->bo->mem.mem_type == DRM_BO_MEM_TT) && (read_domains & RADEON_GEM_DOMAIN_GTT)) + flags = DRM_BO_FLAG_MEM_TT; + else if (read_domains & RADEON_GEM_DOMAIN_VRAM) + flags = DRM_BO_FLAG_MEM_VRAM; + else if (read_domains & RADEON_GEM_DOMAIN_GTT) + flags = DRM_BO_FLAG_MEM_TT; + } + + ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM | DRM_BO_FLAG_CACHED, + unfenced ? DRM_BO_HINT_DONT_FENCE : 0, 0); + if (ret) + return ret; + + if (flags_p) + *flags_p = flags; + return 0; + +} + int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -152,6 +204,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_gem_object *obj; struct drm_radeon_gem_object *obj_priv; int ret; + /* for now if someone requests domain CPU - just make sure the buffer is finished with */ /* just do a BO wait for now */ @@ -161,9 +214,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, obj_priv = obj->driver_private; - mutex_lock(&obj_priv->bo->mutex); - ret = drm_bo_wait(obj_priv->bo, 0, 1, 0, 0); - mutex_unlock(&obj_priv->bo->mutex); + ret = radeon_gem_set_domain(obj, args->read_domains, args->write_domain, NULL, true); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); @@ -180,7 +231,41 @@ int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - return -ENOSYS; + struct drm_radeon_gem_pwrite *args = data; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + int ret; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + obj_priv = obj->driver_private; + + /* check where the buffer is first - if not in VRAM + fallback to userspace copying for now */ + mutex_lock(&obj_priv->bo->mutex); + if (obj_priv->bo->mem.mem_type != DRM_BO_MEM_VRAM) { + ret = -EINVAL; + goto out_unlock; + } + + DRM_ERROR("pwriting data->size %lld %llx\n", args->size, args->offset); + ret = -EINVAL; + +#if 0 + /* so need to grab an IB, copy the data into it in a loop + and send them to VRAM using HDB */ + while ((buf = radeon_host_data_blit(dev, cpp, w, dst_pitch_off, &buf_pitch, + x, &y, (unsigned int*)&h, &hpass)) != 0) { + radeon_host_data_blit_copy_pass(dev, cpp, buf, (uint8_t *)src, + hpass, buf_pitch, src_pitch); + src += hpass * src_pitch; + } +#endif +out_unlock: + mutex_unlock(&obj_priv->bo->mutex); + return ret; } int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, @@ -215,7 +300,7 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, obj_priv->bo->map_list.hash.key); up_write(¤t->mm->mmap_sem); - DRM_DEBUG("got here %p\n", obj); + DRM_DEBUG("got here %p %d\n", obj, obj_priv->bo->mem.mem_type); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -246,8 +331,8 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, /* validate into a pin with no fence */ if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { - ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - DRM_BO_HINT_DONT_FENCE, 0); + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, 0); } else ret = 0; @@ -342,18 +427,6 @@ int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, + obj_priv->bo->offset + start); int dwords = (end - start + 3) / sizeof(u32); -#if 0 - /* Indirect buffer data must be an even number of - * dwords, so if we've been given an odd number we must - * pad the data with a Type-2 CP packet. - */ - if (dwords & 1) { - u32 *data = (u32 *) - ((char *)dev->agp_buffer_map->handle - + buf->offset + start); - data[dwords++] = RADEON_CP_PACKET2; - } -#endif /* Fire off the indirect buffer */ BEGIN_RING(3); @@ -487,6 +560,7 @@ static int radeon_gart_init(struct drm_device *dev) /* setup a 32MB GART */ dev_priv->gart_size = dev_priv->mm.gart_size; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; #if __OS_HAS_AGP @@ -706,6 +780,9 @@ int radeon_gem_mm_init(struct drm_device *dev) int ret; u32 pg_offset; + /* init TTM underneath */ + drm_bo_driver_init(dev); + /* size the mappable VRAM memory for now */ radeon_vram_setup(dev); @@ -747,8 +824,7 @@ void radeon_gem_mm_fini(struct drm_device *dev) radeon_gem_ib_destroy(dev); mutex_lock(&dev->struct_mutex); - - + if (dev_priv->mm.ring_read.bo) { drm_bo_kunmap(&dev_priv->mm.ring_read.kmap); drm_bo_usage_deref_locked(&dev_priv->mm.ring_read.bo); @@ -771,13 +847,13 @@ void radeon_gem_mm_fini(struct drm_device *dev) } if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) { - DRM_DEBUG("delaying takedown of TTM memory\n"); + DRM_DEBUG("delaying takedown of VRAM memory\n"); } mutex_unlock(&dev->struct_mutex); drm_bo_driver_finish(dev); - dev_priv->mm_enabled = false; + dev_priv->mm_enabled = false; } int radeon_gem_object_pin(struct drm_gem_object *obj, @@ -899,7 +975,8 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri { drm_radeon_private_t *dev_priv = dev->dev_private; /* relocate the handle */ - int domains = reloc[2]; + uint32_t read_domains = reloc[2]; + uint32_t write_domain = reloc[3]; struct drm_gem_object *obj; int flags = 0; int ret; @@ -910,19 +987,11 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri return false; obj_priv = obj->driver_private; - if (domains == RADEON_GEM_DOMAIN_VRAM) { - flags = DRM_BO_FLAG_MEM_VRAM; - } else { - flags = DRM_BO_FLAG_MEM_TT; - } - - ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0); - if (ret) - return ret; + radeon_gem_set_domain(obj, read_domains, write_domain, &flags, false); if (flags == DRM_BO_FLAG_MEM_VRAM) *offset = obj_priv->bo->offset + dev_priv->fb_location; - else + else if (flags == DRM_BO_FLAG_MEM_TT) *offset = obj_priv->bo->offset + dev_priv->gart_vm_start; /* BAD BAD BAD - LINKED LIST THE OBJS and UNREF ONCE IB is SUBMITTED */ -- cgit v1.2.3 From fe59d04a7c30692952652f77529deb22a3e0c8bb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 4 Sep 2008 11:57:00 +1000 Subject: radeon: fixup a number of avivo checks for rs690 --- linux-core/radeon_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index eceb5207..44a0f1d1 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -483,7 +483,7 @@ static uint32_t radeon_get_accessible_vram(struct drm_device *dev) dev_priv->chip_family == CHIP_RV380 || dev_priv->chip_family == CHIP_R420 || dev_priv->chip_family == CHIP_RV410 || - dev_priv->chip_family >= CHIP_RS600) { + radeon_is_avivo(dev_priv)) { uint32_t temp = RADEON_READ(RADEON_HOST_PATH_CNTL); temp |= RADEON_HDP_APER_CNTL; RADEON_WRITE(RADEON_HOST_PATH_CNTL, temp); @@ -515,7 +515,7 @@ void radeon_vram_setup(struct drm_device *dev) uint32_t vram; uint32_t accessible, bar_size; - if ((dev_priv->chip_family <= CHIP_RV515) && (dev_priv->flags & RADEON_IS_IGP)) { + if (!radeon_is_avivo(dev_priv) && (dev_priv->flags & RADEON_IS_IGP)) { uint32_t tom = RADEON_READ(RADEON_NB_TOM); vram = (((tom >> 16) - (tom & 0xffff) + 1) << 6); -- cgit v1.2.3 From 9f9f171f8e0ad817414e6218b44579171d03cec0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 5 Sep 2008 10:56:18 +1000 Subject: radeon: rs690 GART tables need to be in uncached memory. Allocate the rs480/690 tables from uncached memory. --- linux-core/radeon_gem.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 44a0f1d1..24c806a1 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -613,17 +613,18 @@ static int radeon_gart_init(struct drm_device *dev) } else if (!(dev_priv->flags & RADEON_IS_AGP)) { /* allocate PCI GART table */ dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); + dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + if (dev_priv->flags & RADEON_IS_IGPGART) + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; + else + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; + ret = drm_ati_alloc_pcigart_table(dev, &dev_priv->gart_info); if (ret) { DRM_ERROR("cannot allocate PCI GART page!\n"); return -EINVAL; } - dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; - if (dev_priv->flags & RADEON_IS_IGPGART) - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; - else - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; dev_priv->gart_info.addr = dev_priv->gart_info.table_handle->vaddr; dev_priv->gart_info.bus_addr = dev_priv->gart_info.table_handle->busaddr; } -- cgit v1.2.3 From 2a6dad31d84252d505f392f91dffd90689bb947c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:05:59 +1000 Subject: radeon: add initial suspend/resume support plus a bunch of fixes --- linux-core/radeon_gem.c | 59 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 7 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 24c806a1..98105e7c 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -43,7 +43,6 @@ int radeon_gem_init_object(struct drm_gem_object *obj) obj->driver_private = obj_priv; obj_priv->obj = obj; - return 0; } @@ -320,6 +319,8 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, struct drm_gem_object *obj; struct drm_radeon_gem_object *obj_priv; int ret; + int flags = DRM_BO_FLAG_NO_EVICT; + int mask = DRM_BO_FLAG_NO_EVICT; obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) @@ -329,15 +330,24 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); /* validate into a pin with no fence */ + if (args->pin_domain) { + mask |= DRM_BO_MASK_MEM; + if (args->pin_domain == RADEON_GEM_DOMAIN_GTT) + flags |= DRM_BO_FLAG_MEM_TT; + else if (args->pin_domain == RADEON_GEM_DOMAIN_VRAM) + flags |= DRM_BO_FLAG_MEM_VRAM; + else + return -EINVAL; + } if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { - ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, + ret = drm_bo_do_validate(obj_priv->bo, flags, mask, DRM_BO_HINT_DONT_FENCE, 0); } else ret = 0; args->offset = obj_priv->bo->offset; - DRM_DEBUG("got here %p %p\n", obj, obj_priv->bo); + DRM_DEBUG("got here %p %p %x\n", obj, obj_priv->bo, obj_priv->bo->offset); mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(obj); @@ -361,7 +371,7 @@ int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, /* validate into a pin with no fence */ - ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT, + ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, DRM_BO_HINT_DONT_FENCE, 0); mutex_lock(&dev->struct_mutex); @@ -598,7 +608,11 @@ static int radeon_gart_init(struct drm_device *dev) if (ret) return -EINVAL; - DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset); + dev_priv->mm.pcie_table_backup = kzalloc(RADEON_PCIGART_TABLE_SIZE, GFP_KERNEL); + if (!dev_priv->mm.pcie_table_backup) + return -EINVAL; + + DRM_ERROR("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset); ret = drm_bo_kmap(dev_priv->mm.pcie_table.bo, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, &dev_priv->mm.pcie_table.kmap); if (ret) @@ -690,10 +704,11 @@ int radeon_alloc_gart_objects(struct drm_device *dev) } -static void radeon_init_memory_map(struct drm_device *dev) +void radeon_init_memory_map(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; u32 mem_size, aper_size; + u32 tmp; dev_priv->mc_fb_location = radeon_read_fb_location(dev_priv); radeon_read_agp_location(dev_priv, &dev_priv->mc_agp_loc_lo, &dev_priv->mc_agp_loc_hi); @@ -841,6 +856,10 @@ void radeon_gem_mm_fini(struct drm_device *dev) } if (dev_priv->flags & RADEON_IS_PCIE) { + if (dev_priv->mm.pcie_table_backup) { + kfree(dev_priv->mm.pcie_table_backup); + dev_priv->mm.pcie_table_backup = NULL; + } if (dev_priv->mm.pcie_table.bo) { drm_bo_kunmap(&dev_priv->mm.pcie_table.kmap); drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table.bo); @@ -858,7 +877,31 @@ void radeon_gem_mm_fini(struct drm_device *dev) } int radeon_gem_object_pin(struct drm_gem_object *obj, - uint32_t alignment) + uint32_t alignment, uint32_t pin_domain) +{ + struct drm_radeon_gem_object *obj_priv; + int ret; + uint32_t flags = DRM_BO_FLAG_NO_EVICT; + uint32_t mask = DRM_BO_FLAG_NO_EVICT; + + obj_priv = obj->driver_private; + + if (pin_domain) { + mask |= DRM_BO_MASK_MEM; + if (pin_domain == RADEON_GEM_DOMAIN_GTT) + flags |= DRM_BO_FLAG_MEM_TT; + else if (pin_domain == RADEON_GEM_DOMAIN_VRAM) + flags |= DRM_BO_FLAG_MEM_VRAM; + else + return -EINVAL; + } + ret = drm_bo_do_validate(obj_priv->bo, flags, mask, + DRM_BO_HINT_DONT_FENCE, 0); + + return ret; +} + +int radeon_gem_object_unpin(struct drm_gem_object *obj) { struct drm_radeon_gem_object *obj_priv; int ret; @@ -1335,3 +1378,5 @@ void radeon_gem_update_offsets(struct drm_device *dev, struct drm_master *master dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; } + + -- cgit v1.2.3 From 8f23d4a44cdb17abff8f1ab3585e533ae0572224 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:11:43 +1000 Subject: make text reserve 256k --- linux-core/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 98105e7c..12a03588 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -804,7 +804,7 @@ int radeon_gem_mm_init(struct drm_device *dev) radeon_init_memory_map(dev); -#define VRAM_RESERVE_TEXT (64*1024) +#define VRAM_RESERVE_TEXT (256*1024) /* need to reserve 256 for text mode for now */ dev_priv->mm.vram_visible -= VRAM_RESERVE_TEXT; pg_offset = VRAM_RESERVE_TEXT >> PAGE_SHIFT; drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, pg_offset, /*dev_priv->mm.vram_offset >> PAGE_SHIFT,*/ -- cgit v1.2.3 From ed961cb428a73a35d473c27f62809ef80bde8706 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:14:32 +1000 Subject: radeon: remove unneeded debugging --- linux-core/radeon_gem.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 12a03588..382d348b 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -612,7 +612,6 @@ static int radeon_gart_init(struct drm_device *dev) if (!dev_priv->mm.pcie_table_backup) return -EINVAL; - DRM_ERROR("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table.bo, dev_priv->mm.pcie_table.bo->offset); ret = drm_bo_kmap(dev_priv->mm.pcie_table.bo, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT, &dev_priv->mm.pcie_table.kmap); if (ret) -- cgit v1.2.3 From 9b728fe4b0c154acd2291f9bec747ee67f8cce02 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:16:09 +1000 Subject: radeon: fixup reference counting properly --- linux-core/radeon_gem.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 382d348b..c0218a3f 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -264,6 +264,9 @@ int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, #endif out_unlock: mutex_unlock(&obj_priv->bo->mutex); + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); return ret; } @@ -322,14 +325,7 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, int flags = DRM_BO_FLAG_NO_EVICT; int mask = DRM_BO_FLAG_NO_EVICT; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) - return -EINVAL; - - obj_priv = obj->driver_private; - - DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); - /* validate into a pin with no fence */ + /* check for valid args */ if (args->pin_domain) { mask |= DRM_BO_MASK_MEM; if (args->pin_domain == RADEON_GEM_DOMAIN_GTT) @@ -340,6 +336,14 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, return -EINVAL; } + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + + obj_priv = obj->driver_private; + + /* validate into a pin with no fence */ + DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { ret = drm_bo_do_validate(obj_priv->bo, flags, mask, DRM_BO_HINT_DONT_FENCE, 0); @@ -1027,7 +1031,7 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri obj = drm_gem_object_lookup(dev, file_priv, reloc[1]); if (!obj) - return false; + return -EINVAL; obj_priv = obj->driver_private; radeon_gem_set_domain(obj, read_domains, write_domain, &flags, false); -- cgit v1.2.3 From 515aa0800cf2d91bdf4706463e0531c5081a2679 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:17:27 +1000 Subject: radeon: do proper memory controller init and setup --- linux-core/radeon_gem.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 2 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index c0218a3f..58162e52 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -707,6 +707,176 @@ int radeon_alloc_gart_objects(struct drm_device *dev) } +static bool avivo_get_mc_idle(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (dev_priv->chip_family >= CHIP_R600) { + /* no idea where this is on r600 yet */ + return true; + } else if (dev_priv->chip_family == CHIP_RV515) { + if (radeon_read_mc_reg(dev_priv, RV515_MC_STATUS) & RV515_MC_STATUS_IDLE) + return true; + else + return false; + } else if (dev_priv->chip_family == CHIP_RS600) { + if (radeon_read_mc_reg(dev_priv, RS600_MC_STATUS) & RS600_MC_STATUS_IDLE) + return true; + else + return false; + } else if ((dev_priv->chip_family == CHIP_RS690) || + (dev_priv->chip_family == CHIP_RS740)) { + if (radeon_read_mc_reg(dev_priv, RS690_MC_STATUS) & RS690_MC_STATUS_IDLE) + return true; + else + return false; + } else { + if (radeon_read_mc_reg(dev_priv, R520_MC_STATUS) & R520_MC_STATUS_IDLE) + return true; + else + return false; + } +} + + +static void avivo_disable_mc_clients(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t tmp; + int timeout; + + radeon_do_wait_for_idle(dev_priv); + + RADEON_WRITE(AVIVO_D1VGA_CONTROL, RADEON_READ(AVIVO_D1VGA_CONTROL) & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); + RADEON_WRITE(AVIVO_D2VGA_CONTROL, RADEON_READ(AVIVO_D2VGA_CONTROL) & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); + + tmp = RADEON_READ(AVIVO_D1CRTC_CONTROL); + RADEON_WRITE(AVIVO_D1CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN); + + tmp = RADEON_READ(AVIVO_D2CRTC_CONTROL); + RADEON_WRITE(AVIVO_D2CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN); + + tmp = RADEON_READ(AVIVO_D2CRTC_CONTROL); + + udelay(1000); + + timeout = 0; + while (!(avivo_get_mc_idle(dev))) { + if (++timeout > 100000) { + DRM_ERROR("Timeout waiting for memory controller to update settings\n"); + DRM_ERROR("Bad things may or may not happen\n"); + } + udelay(10); + } +} + +static inline u32 radeon_busy_wait(struct drm_device *dev, uint32_t reg, uint32_t bits, + unsigned int timeout) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + u32 status; + + do { + udelay(10); + status = RADEON_READ(reg); + timeout--; + } while(status != 0xffffffff && (status & bits) && (timeout > 0)); + + if (timeout == 0) + status = 0xffffffff; + + return status; +} + +/* Wait for vertical sync on primary CRTC */ +static void radeon_wait_for_vsync(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t crtc_gen_cntl; + int ret; + + crtc_gen_cntl = RADEON_READ(RADEON_CRTC_GEN_CNTL); + if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || + !(crtc_gen_cntl & RADEON_CRTC_EN)) + return; + + /* Clear the CRTC_VBLANK_SAVE bit */ + RADEON_WRITE(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); + + radeon_busy_wait(dev, RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE, 2000); + +} + +/* Wait for vertical sync on primary CRTC */ +static void radeon_wait_for_vsync2(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t crtc2_gen_cntl; + struct timeval timeout; + + crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); + if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || + !(crtc2_gen_cntl & RADEON_CRTC2_EN)) + return; + + /* Clear the CRTC_VBLANK_SAVE bit */ + RADEON_WRITE(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); + + radeon_busy_wait(dev, RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE, 2000); +} + +static void legacy_disable_mc_clients(struct drm_device *dev) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + uint32_t old_mc_status, status_idle; + uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; + uint32_t status; + + radeon_do_wait_for_idle(dev_priv); + + if (dev_priv->flags & RADEON_IS_IGP) + return; + + old_mc_status = RADEON_READ(RADEON_MC_STATUS); + + /* stop display and memory access */ + ov0_scale_cntl = RADEON_READ(RADEON_OV0_SCALE_CNTL); + RADEON_WRITE(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); + crtc_ext_cntl = RADEON_READ(RADEON_CRTC_EXT_CNTL); + RADEON_WRITE(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); + crtc_gen_cntl = RADEON_READ(RADEON_CRTC_GEN_CNTL); + + radeon_wait_for_vsync(dev); + + RADEON_WRITE(RADEON_CRTC_GEN_CNTL, + (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | + RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); + + if (!(dev_priv->flags & RADEON_SINGLE_CRTC)) { + crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); + + radeon_wait_for_vsync2(dev); + RADEON_WRITE(RADEON_CRTC2_GEN_CNTL, + (crtc2_gen_cntl & + ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | + RADEON_CRTC2_DISP_REQ_EN_B); + } + + udelay(500); + + if (radeon_is_r300(dev_priv)) + status_idle = R300_MC_IDLE; + else + status_idle = RADEON_MC_IDLE; + + status = radeon_busy_wait(dev, RADEON_MC_STATUS, status_idle, 200000); + if (status == 0xffffffff) { + DRM_ERROR("Timeout waiting for memory controller to update settings\n"); + DRM_ERROR("Bad things may or may not happen\n"); + } +} + + void radeon_init_memory_map(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -776,6 +946,14 @@ void radeon_init_memory_map(struct drm_device *dev) else dev_priv->fb_location = (dev_priv->mc_fb_location & 0xffff) << 16; + /* updating mc regs here */ + if (radeon_is_avivo(dev_priv)) + avivo_disable_mc_clients(dev); + else + legacy_disable_mc_clients(dev); + + radeon_write_fb_location(dev_priv, dev_priv->mc_fb_location); + if (radeon_is_avivo(dev_priv)) { if (dev_priv->chip_family >= CHIP_R600) RADEON_WRITE(R600_HDP_NONSURFACE_BASE, (dev_priv->mc_fb_location << 16) & 0xff0000); @@ -783,8 +961,6 @@ void radeon_init_memory_map(struct drm_device *dev) RADEON_WRITE(AVIVO_HDP_FB_LOCATION, dev_priv->mc_fb_location); } - radeon_write_fb_location(dev_priv, dev_priv->mc_fb_location); - dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; dev_priv->fb_size = ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) -- cgit v1.2.3 From 8f38c28a3924dbda5babcf035911e103f27f9a05 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:19:08 +1000 Subject: radeon: fail properly if we can't create the ring. Normally this will be due to an AGP driver needing updating --- linux-core/radeon_gem.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 58162e52..821a3e13 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -667,7 +667,10 @@ int radeon_alloc_gart_objects(struct drm_device *dev) DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT, 0, 1, 0, &dev_priv->mm.ring.bo); if (ret) { - DRM_ERROR("failed to allocate ring\n"); + if (dev_priv->flags & RADEON_IS_AGP) + DRM_ERROR("failed to allocate ring - most likely an AGP driver bug\n"); + else + DRM_ERROR("failed to allocate ring\n"); return -EINVAL; } @@ -1004,8 +1007,10 @@ int radeon_gem_mm_init(struct drm_device *dev) /* need to allocate some objects in the GART */ /* ring + ring read ptr */ ret = radeon_alloc_gart_objects(dev); - if (ret) + if (ret) { + radeon_gem_mm_fini(dev); return -EINVAL; + } dev_priv->mm_enabled = true; return 0; @@ -1508,8 +1513,10 @@ static void radeon_gem_dma_bufs_destroy(struct drm_device *dev) struct drm_radeon_private *dev_priv = dev->dev_private; drm_dma_takedown(dev); - drm_bo_kunmap(&dev_priv->mm.dma_bufs.kmap); - drm_bo_usage_deref_unlocked(&dev_priv->mm.dma_bufs.bo); + if (dev_priv->mm.dma_bufs.bo) { + drm_bo_kunmap(&dev_priv->mm.dma_bufs.kmap); + drm_bo_usage_deref_unlocked(&dev_priv->mm.dma_bufs.bo); + } } -- cgit v1.2.3 From f426f458f7e766cd47bb30736004ccfc9209f27f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 18 Sep 2008 10:20:29 +1000 Subject: [PATCH] radeon: fixup GEM domain setting - allows more userspace paths also dirty buffer on validate --- linux-core/radeon_gem.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 821a3e13..8338f8f5 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -166,8 +166,16 @@ int radeon_gem_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uin return -EINVAL; // we can't write to system RAM } else { /* okay for a read domain - prefer wherever the object is now or close enough */ - if ((read_domains == 0) || (read_domains == RADEON_GEM_DOMAIN_CPU)) + if (read_domains == 0) return -EINVAL; + + /* if its already a local memory and CPU is valid do nothing */ + if (read_domains & RADEON_GEM_DOMAIN_CPU) { + if (obj_priv->bo->mem.mem_type == DRM_BO_MEM_LOCAL) + return 0; + if (read_domains == RADEON_GEM_DOMAIN_CPU) + return -EINVAL; + } /* simple case no choice in domains */ if (read_domains == RADEON_GEM_DOMAIN_VRAM) @@ -178,12 +186,19 @@ int radeon_gem_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uin flags = DRM_BO_FLAG_MEM_VRAM; else if ((obj_priv->bo->mem.mem_type == DRM_BO_MEM_TT) && (read_domains & RADEON_GEM_DOMAIN_GTT)) flags = DRM_BO_FLAG_MEM_TT; + else if ((obj_priv->bo->mem.mem_type == DRM_BO_MEM_LOCAL) && (read_domains & RADEON_GEM_DOMAIN_GTT)) + flags = DRM_BO_FLAG_MEM_TT; else if (read_domains & RADEON_GEM_DOMAIN_VRAM) flags = DRM_BO_FLAG_MEM_VRAM; else if (read_domains & RADEON_GEM_DOMAIN_GTT) flags = DRM_BO_FLAG_MEM_TT; } + /* if this BO is pinned then we ain't moving it anywhere */ + if (obj_priv->bo->pinned_mem_type && unfenced) + return 0; + + DRM_DEBUG("validating %p from %d into %x %d %d\n", obj_priv->bo, obj_priv->bo->mem.mem_type, flags, read_domains, write_domain); ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM | DRM_BO_FLAG_CACHED, unfenced ? DRM_BO_HINT_DONT_FENCE : 0, 0); if (ret) @@ -1217,6 +1232,7 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri obj_priv = obj->driver_private; radeon_gem_set_domain(obj, read_domains, write_domain, &flags, false); + obj_priv->bo->mem.flags &= ~DRM_BO_FLAG_CLEAN; if (flags == DRM_BO_FLAG_MEM_VRAM) *offset = obj_priv->bo->offset + dev_priv->fb_location; else if (flags == DRM_BO_FLAG_MEM_TT) -- cgit v1.2.3 From 35e379ce5a0d23f4c812739f89e02703900cd91b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 24 Sep 2008 15:25:35 +1000 Subject: radeon: add r600 modesetting registers writes --- linux-core/radeon_gem.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 8338f8f5..7cdcf47d 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -979,10 +979,16 @@ void radeon_init_memory_map(struct drm_device *dev) RADEON_WRITE(AVIVO_HDP_FB_LOCATION, dev_priv->mc_fb_location); } - dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; - dev_priv->fb_size = - ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) - - dev_priv->fb_location; + if (dev_priv->chip_family >= CHIP_R600) { + dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffffff) << 24; + dev_priv->fb_size = ((radeon_read_fb_location(dev_priv) & 0xff000000u) + 0x1000000) + - dev_priv->fb_location; + } else { + dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; + dev_priv->fb_size = + ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) + - dev_priv->fb_location; + } } @@ -1009,6 +1015,11 @@ int radeon_gem_mm_init(struct drm_device *dev) 0); + if (dev_priv->chip_family > CHIP_R600) { + dev_priv->mm_enabled = true; + return 0; + } + dev_priv->mm.gart_size = (32 * 1024 * 1024); dev_priv->mm.gart_start = 0; ret = radeon_gart_init(dev); -- cgit v1.2.3 From a981a6860365065682f3ca295939e629b989a9d1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 6 Oct 2008 16:39:25 +1000 Subject: drm/radeon: fixup clean flag handling --- linux-core/radeon_gem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 7cdcf47d..8c6f836f 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1244,6 +1244,8 @@ static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_pri radeon_gem_set_domain(obj, read_domains, write_domain, &flags, false); obj_priv->bo->mem.flags &= ~DRM_BO_FLAG_CLEAN; + obj_priv->bo->mem.proposed_flags &= ~DRM_BO_FLAG_CLEAN; + if (flags == DRM_BO_FLAG_MEM_VRAM) *offset = obj_priv->bo->offset + dev_priv->fb_location; else if (flags == DRM_BO_FLAG_MEM_TT) -- cgit v1.2.3 From 4a4d7727c6c6eff4cf19d5debb91a6fcac555832 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 6 Oct 2008 16:40:20 +1000 Subject: radeon: fix pin ioctl interface to mesa can find offset for pinned buffers --- linux-core/radeon_gem.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 8c6f836f..b9c3b80d 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -347,8 +347,9 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, flags |= DRM_BO_FLAG_MEM_TT; else if (args->pin_domain == RADEON_GEM_DOMAIN_VRAM) flags |= DRM_BO_FLAG_MEM_VRAM; - else - return -EINVAL; + else /* hand back the offset we currently have if no args supplied + - this is to allow old mesa to work - its a hack */ + flags = 0; } obj = drm_gem_object_lookup(dev, file_priv, args->handle); @@ -359,11 +360,11 @@ int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, /* validate into a pin with no fence */ DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage)); - if (!(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { + if (flags && !(obj_priv->bo->type != drm_bo_type_kernel && !DRM_SUSER(DRM_CURPROC))) { ret = drm_bo_do_validate(obj_priv->bo, flags, mask, DRM_BO_HINT_DONT_FENCE, 0); } else - ret = 0; + ret = 0; args->offset = obj_priv->bo->offset; DRM_DEBUG("got here %p %p %x\n", obj, obj_priv->bo, obj_priv->bo->offset); -- cgit v1.2.3 From 4d1031a9f0e5cddb6ca403afdbd1f019c9c3df2e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 6 Oct 2008 16:40:45 +1000 Subject: radeon: fix alignment so Xv works again --- linux-core/radeon_gem.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index b9c3b80d..225f0269 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -80,10 +80,11 @@ struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, struct drm_radeon_gem_object *obj_priv; int ret; uint32_t flags; + uint32_t page_align; obj = drm_gem_object_alloc(dev, size); if (!obj) - return NULL;; + return NULL; obj_priv = obj->driver_private; flags = DRM_BO_FLAG_MAPPABLE; @@ -95,10 +96,15 @@ struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED; flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE; + + if (alignment == 0) + alignment = PAGE_SIZE; + + page_align = alignment >> PAGE_SHIFT; /* create a TTM BO */ ret = drm_buffer_object_create(dev, size, drm_bo_type_device, - flags, 0, alignment, + flags, 0, page_align, 0, &obj_priv->bo); if (ret) goto fail; @@ -188,10 +194,14 @@ int radeon_gem_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uin flags = DRM_BO_FLAG_MEM_TT; else if ((obj_priv->bo->mem.mem_type == DRM_BO_MEM_LOCAL) && (read_domains & RADEON_GEM_DOMAIN_GTT)) flags = DRM_BO_FLAG_MEM_TT; - else if (read_domains & RADEON_GEM_DOMAIN_VRAM) - flags = DRM_BO_FLAG_MEM_VRAM; - else if (read_domains & RADEON_GEM_DOMAIN_GTT) - flags = DRM_BO_FLAG_MEM_TT; + + /* no idea here just set whatever we are input */ + if (flags == 0) { + if (read_domains & RADEON_GEM_DOMAIN_VRAM) + flags |= DRM_BO_FLAG_MEM_VRAM; + if (read_domains & RADEON_GEM_DOMAIN_GTT) + flags |= DRM_BO_FLAG_MEM_TT; + } } /* if this BO is pinned then we ain't moving it anywhere */ -- cgit v1.2.3 From d958cd7bb95558aa6c49824e2ae2b302f1433d2e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 16 Oct 2008 10:51:31 +1000 Subject: radeon: use discardable flags on no backing store objects --- linux-core/radeon_gem.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 225f0269..5e2ad98b 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -74,7 +74,7 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, } struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, int alignment, - int initial_domain) + int initial_domain, bool discardable) { struct drm_gem_object *obj; struct drm_radeon_gem_object *obj_priv; @@ -97,6 +97,9 @@ struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE; + if (discardable) + flags |= DRM_BO_FLAG_DISCARDABLE; + if (alignment == 0) alignment = PAGE_SIZE; @@ -129,7 +132,7 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, /* create a gem object to contain this object in */ args->size = roundup(args->size, PAGE_SIZE); - obj = radeon_gem_object_alloc(dev, args->size, args->alignment, args->initial_domain); + obj = radeon_gem_object_alloc(dev, args->size, args->alignment, args->initial_domain, args->no_backing_store); if (!obj) return -EINVAL; -- cgit v1.2.3 From 653b16f2dd32b5fdbd5f97277edc1c6df66755a9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:31:17 +1000 Subject: radeon: fix accessible VRAM sizing --- linux-core/radeon_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 5e2ad98b..5ecd8c55 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -585,6 +585,9 @@ void radeon_vram_setup(struct drm_device *dev) if (accessible > bar_size) accessible = bar_size; + if (accessible > vram) + accessible = vram; + DRM_INFO("Detected VRAM RAM=%dK, accessible=%uK, BAR=%uK\n", vram, accessible, bar_size); -- cgit v1.2.3 From 624da91277ee33936ea3cfaf20e7f6775293deb2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:33:12 +1000 Subject: radeon: add r423 bits to modesetting --- linux-core/radeon_gem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 5ecd8c55..4b15fac3 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -525,6 +525,7 @@ static uint32_t radeon_get_accessible_vram(struct drm_device *dev) dev_priv->chip_family == CHIP_RV350 || dev_priv->chip_family == CHIP_RV380 || dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_R423 || dev_priv->chip_family == CHIP_RV410 || radeon_is_avivo(dev_priv)) { uint32_t temp = RADEON_READ(RADEON_HOST_PATH_CNTL); @@ -963,6 +964,7 @@ void radeon_init_memory_map(struct drm_device *dev) dev_priv->chip_family == CHIP_RV350 || dev_priv->chip_family == CHIP_RV380 || dev_priv->chip_family == CHIP_R420 || + dev_priv->chip_family == CHIP_R423 || dev_priv->chip_family == CHIP_RV410) aper0_base &= ~(mem_size - 1); -- cgit v1.2.3 From 8b2925468d326ab6fa31a312e845a3bc71343106 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:39:53 +1000 Subject: radeon: make new CS2 command submission interface port older interface to this --- linux-core/radeon_gem.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 4b15fac3..7899490f 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1148,11 +1148,11 @@ int radeon_gem_object_unpin(struct drm_gem_object *obj) #define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) -int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32_t *card_offset) +int radeon_gem_ib_get(struct drm_radeon_cs_parser *parser, uint32_t *card_offset) { int i, index = -1; int ret; - drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_private_t *dev_priv = parser->dev->dev_private; for (i = 0; i < RADEON_NUM_IB; i++) { if (!(dev_priv->ib_alloc_bitmap & (1 << i))){ @@ -1178,12 +1178,12 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32 } if (index == -1) { - DRM_ERROR("Major case fail to allocate IB from freelist %x\n", dev_priv->ib_alloc_bitmap); + DRM_ERROR("Major case fail to allocate IB from freelist %llx\n", dev_priv->ib_alloc_bitmap); return -EINVAL; } - if (dwords > RADEON_IB_SIZE / sizeof(uint32_t)) + if (parser->chunks[parser->ib_index].length_dw > RADEON_IB_SIZE / sizeof(uint32_t)) return -EINVAL; ret = drm_bo_do_validate(dev_priv->ib_objs[index]->bo, 0, @@ -1195,25 +1195,24 @@ int radeon_gem_ib_get(struct drm_device *dev, void **ib, uint32_t dwords, uint32 } *card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; - *ib = dev_priv->ib_objs[index]->kmap.virtual; + parser->ib = dev_priv->ib_objs[index]->kmap.virtual; dev_priv->ib_alloc_bitmap |= (1 << i); return 0; } -static void radeon_gem_ib_free(struct drm_device *dev, void *ib, uint32_t dwords) +static void radeon_gem_ib_free(struct drm_radeon_cs_parser *parser) { + struct drm_device *dev = parser->dev; drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_fence_object *fence; int ret; int i; for (i = 0; i < RADEON_NUM_IB; i++) { - - if (dev_priv->ib_objs[i]->kmap.virtual == ib) { + if (dev_priv->ib_objs[i]->kmap.virtual == parser->ib) { /* emit a fence object */ ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); if (ret) { - drm_putback_buffer_objects(dev); } /* dereference the fence object */ @@ -1243,19 +1242,19 @@ static int radeon_gem_ib_destroy(struct drm_device *dev) return 0; } -static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_priv, - uint32_t *reloc, uint32_t *offset) +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]; struct drm_gem_object *obj; int flags = 0; - int ret; struct drm_radeon_gem_object *obj_priv; - obj = drm_gem_object_lookup(dev, file_priv, reloc[1]); + obj = drm_gem_object_lookup(dev, parser->file_priv, reloc[1]); if (!obj) return -EINVAL; -- cgit v1.2.3 From 6000fa686294019e93f815433a1a9b44db511a69 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:40:52 +1000 Subject: radeon: CS2 make it all work with new relocs style --- linux-core/radeon_gem.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 7899490f..851a95d3 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -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); -- cgit v1.2.3 From f5e6dbef797cff18953e4f3271e1c74a0b24b715 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:41:30 +1000 Subject: radeon: fix some warnings --- linux-core/radeon_gem.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 851a95d3..6c62620a 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -126,7 +126,6 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_radeon_gem_object *obj_priv; struct drm_gem_object *obj; int ret = 0; - uint32_t flags; int handle; /* create a gem object to contain this object in */ @@ -157,8 +156,6 @@ fail: int radeon_gem_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain, uint32_t *flags_p, bool unfenced) { - struct drm_device *dev = obj->dev; - drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_radeon_gem_object *obj_priv; uint32_t flags = 0; int ret; @@ -616,7 +613,7 @@ static int radeon_gart_init(struct drm_device *dev) base = dev->agp->base; if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { - DRM_INFO("Can't use agp base @0x%08xlx, won't fit\n", + DRM_INFO("Can't use agp base @0x%08lx, won't fit\n", dev->agp->base); base = 0; } @@ -732,7 +729,7 @@ int radeon_alloc_gart_objects(struct drm_device *dev) return -EINVAL; } - DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n", + DRM_DEBUG("Ring ptr %p mapped at %ld %p, read ptr %p maped at %ld %p\n", dev_priv->mm.ring.bo, dev_priv->mm.ring.bo->offset, dev_priv->mm.ring.kmap.virtual, dev_priv->mm.ring_read.bo, dev_priv->mm.ring_read.bo->offset, dev_priv->mm.ring_read.kmap.virtual); @@ -829,7 +826,6 @@ static void radeon_wait_for_vsync(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; uint32_t crtc_gen_cntl; - int ret; crtc_gen_cntl = RADEON_READ(RADEON_CRTC_GEN_CNTL); if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || @@ -848,7 +844,6 @@ static void radeon_wait_for_vsync2(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; uint32_t crtc2_gen_cntl; - struct timeval timeout; crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || @@ -917,7 +912,6 @@ void radeon_init_memory_map(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; u32 mem_size, aper_size; - u32 tmp; dev_priv->mc_fb_location = radeon_read_fb_location(dev_priv); radeon_read_agp_location(dev_priv, &dev_priv->mc_agp_loc_lo, &dev_priv->mc_agp_loc_hi); @@ -1581,7 +1575,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) DRM_DEBUG("\n"); radeon_gem_addbufs(dev); - DRM_DEBUG("%x %d\n", dev_priv->mm.dma_bufs.bo->map_list.hash.key, size); + DRM_DEBUG("%lx %d\n", dev_priv->mm.dma_bufs.bo->map_list.hash.key, size); dev->agp_buffer_token = dev_priv->mm.dma_bufs.bo->map_list.hash.key << PAGE_SHIFT; dev_priv->mm.fake_agp_map.handle = dev_priv->mm.dma_bufs.kmap.virtual; dev_priv->mm.fake_agp_map.size = size; -- cgit v1.2.3 From 4ccec67a239517458bace47bf08f6770393abb37 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:42:01 +1000 Subject: radeon: remove unused gem indirect ioctl --- linux-core/radeon_gem.c | 75 ------------------------------------------------- 1 file changed, 75 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 6c62620a..ce33979e 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -424,81 +424,6 @@ int radeon_gem_execbuffer(struct drm_device *dev, void *data, } -int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_radeon_gem_indirect *args = data; - struct drm_radeon_private *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_radeon_gem_object *obj_priv; - uint32_t start, end; - int ret; - RING_LOCALS; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) - return -EINVAL; - - obj_priv = obj->driver_private; - - DRM_DEBUG("got here %p %d\n", obj, args->used); - //RING_SPACE_TEST_WITH_RETURN(dev_priv); - //VB_AGE_TEST_WITH_RETURN(dev_priv); - - ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT, - 0 , 0); - if (ret) - return ret; - - /* Wait for the 3D stream to idle before the indirect buffer - * containing 2D acceleration commands is processed. - */ - BEGIN_RING(2); - - RADEON_WAIT_UNTIL_3D_IDLE(); - - ADVANCE_RING(); - - start = 0; - end = args->used; - - if (start != end) { - int offset = (dev_priv->gart_vm_start + - + obj_priv->bo->offset + start); - int dwords = (end - start + 3) / sizeof(u32); - - /* Fire off the indirect buffer */ - BEGIN_RING(3); - - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(offset); - OUT_RING(dwords); - - ADVANCE_RING(); - } - - COMMIT_RING(); - - /* we need to fence the buffer */ - ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &obj_priv->fence); - if (ret) { - - drm_putback_buffer_objects(dev); - ret = 0; - goto fail; - } - - /* dereference he fence object */ - drm_fence_usage_deref_unlocked(&obj_priv->fence); - - mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - ret = 0; - fail: - return ret; -} - /* * Depending on card genertation, chipset bugs, etc... the amount of vram * accessible to the CPU can vary. This function is our best shot at figuring -- cgit v1.2.3 From 31f8d4218c0f6455751d8bbc788172912359b0df Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:44:03 +1000 Subject: radeon: add wait rendering API --- linux-core/radeon_gem.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index ce33979e..f5d6b94a 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -416,14 +416,33 @@ int radeon_gem_busy(struct drm_device *dev, void *data, return 0; } -int radeon_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int radeon_gem_wait_rendering(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - return -ENOSYS; + struct drm_radeon_gem_wait_rendering *args = data; + struct drm_gem_object *obj; + struct drm_radeon_gem_object *obj_priv; + int ret; + + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EINVAL; + obj_priv = obj->driver_private; + mutex_lock(&obj_priv->bo->mutex); + ret = drm_bo_wait(obj_priv->bo, 0, 1, 1, 0); + mutex_unlock(&obj_priv->bo->mutex); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return ret; } + + /* * Depending on card genertation, chipset bugs, etc... the amount of vram * accessible to the CPU can vary. This function is our best shot at figuring -- cgit v1.2.3 From 31b8a640db9b55638bf9967f0d78ec665fa8839f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:46:54 +1000 Subject: radeon: overhaul ring interactions emit in 16-dword blocks, emit irqs at same time as everything else --- linux-core/radeon_gem.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index f5d6b94a..a785041e 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1086,7 +1086,7 @@ int radeon_gem_object_unpin(struct drm_gem_object *obj) #define RADEON_NUM_IB (RADEON_IB_MEMORY / RADEON_IB_SIZE) -int radeon_gem_ib_get(struct drm_radeon_cs_parser *parser, uint32_t *card_offset) +int radeon_gem_ib_get(struct drm_radeon_cs_parser *parser) { int i, index = -1; int ret; @@ -1132,8 +1132,8 @@ int radeon_gem_ib_get(struct drm_radeon_cs_parser *parser, uint32_t *card_offset return -EINVAL; } - *card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; parser->ib = dev_priv->ib_objs[index]->kmap.virtual; + parser->card_offset = dev_priv->gart_vm_start + dev_priv->ib_objs[index]->bo->offset; dev_priv->ib_alloc_bitmap |= (1 << i); return 0; } @@ -1150,6 +1150,7 @@ static void radeon_gem_ib_free(struct drm_radeon_cs_parser *parser) if (dev_priv->ib_objs[i]->kmap.virtual == parser->ib) { /* emit a fence object */ ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence); + dev_priv->irq_emitted = 0; if (ret) { drm_putback_buffer_objects(dev); } -- cgit v1.2.3 From 49551f87fcd21e10a4485b3e00af47f0b9f94a0f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:49:41 +1000 Subject: radeon: set dma bufs bo type to a kernel type --- linux-core/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index a785041e..f39e8b47 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -1502,7 +1502,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) if (ret < 0) return ret; - ret = drm_buffer_object_create(dev, size, drm_bo_type_device, + ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE, 0, 0, 0, &dev_priv->mm.dma_bufs.bo); -- cgit v1.2.3 From 0e1df6216e7ce3a69d4311e4685613e57129285f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 3 Nov 2008 09:52:25 +1000 Subject: radeon: add mtrr support for VRAM aperture. --- linux-core/radeon_gem.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index f39e8b47..2e20de3c 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -947,6 +947,10 @@ void radeon_init_memory_map(struct drm_device *dev) - dev_priv->fb_location; } + /* add an MTRR for the VRAM */ + dev_priv->aper_size = aper_size; + dev_priv->vram_mtrr = mtrr_add(dev_priv->fb_aper_offset, dev_priv->aper_size, MTRR_TYPE_WRCOMB, 1); + } /* init memory manager - start with all of VRAM and a 32MB GART aperture for now */ @@ -1037,6 +1041,8 @@ void radeon_gem_mm_fini(struct drm_device *dev) DRM_DEBUG("delaying takedown of VRAM memory\n"); } + if (dev_priv->vram_mtrr) + mtrr_del(dev_priv->vram_mtrr, dev_priv->fb_aper_offset, dev_priv->aper_size); mutex_unlock(&dev->struct_mutex); drm_bo_driver_finish(dev); -- cgit v1.2.3 From 31b0c4cd20d0eb843268a6307b7c32dbc07e42a0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 10 Nov 2008 15:13:08 +1000 Subject: radeon: fixup vram visible calculation to take a/c pinned objects for now --- linux-core/radeon_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 2e20de3c..85185232 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -586,6 +586,9 @@ static int radeon_gart_init(struct drm_device *dev) if (ret) return -EINVAL; + /* subtract from VRAM value reporting to userspace */ + dev_priv->mm.vram_visible -= RADEON_PCIGART_TABLE_SIZE; + dev_priv->mm.pcie_table_backup = kzalloc(RADEON_PCIGART_TABLE_SIZE, GFP_KERNEL); if (!dev_priv->mm.pcie_table_backup) return -EINVAL; -- cgit v1.2.3 From 241a9b64141b2dd09449e581017b5ca0c0cc2357 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 10 Nov 2008 15:30:21 +1000 Subject: drm/radeon: add uncached allocator to drm ttm code. --- linux-core/radeon_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index 85185232..f338e64c 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -966,6 +966,9 @@ int radeon_gem_mm_init(struct drm_device *dev) /* init TTM underneath */ drm_bo_driver_init(dev); + /* use the uncached allocator */ + dev->bm.allocator_type = _DRM_BM_ALLOCATOR_UNCACHED; + /* size the mappable VRAM memory for now */ radeon_vram_setup(dev); -- cgit v1.2.3 From 15464f5181538d01e8fc016211daa1a824b89531 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 10 Nov 2008 15:38:32 +1000 Subject: radeon: add gart useable size to report to userspace --- linux-core/radeon_gem.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux-core/radeon_gem.c') diff --git a/linux-core/radeon_gem.c b/linux-core/radeon_gem.c index f338e64c..2ed9bfc1 100644 --- a/linux-core/radeon_gem.c +++ b/linux-core/radeon_gem.c @@ -68,7 +68,7 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, args->vram_visible = dev_priv->mm.vram_visible; args->gart_start = dev_priv->mm.gart_start; - args->gart_size = dev_priv->mm.gart_size; + args->gart_size = dev_priv->mm.gart_useable; return 0; } @@ -680,6 +680,8 @@ int radeon_alloc_gart_objects(struct drm_device *dev) dev_priv->mm.ring.bo, dev_priv->mm.ring.bo->offset, dev_priv->mm.ring.kmap.virtual, dev_priv->mm.ring_read.bo, dev_priv->mm.ring_read.bo->offset, dev_priv->mm.ring_read.kmap.virtual); + dev_priv->mm.gart_useable -= RADEON_DEFAULT_RING_SIZE + PAGE_SIZE; + /* init the indirect buffers */ radeon_gem_ib_init(dev); radeon_gem_dma_bufs_init(dev); @@ -989,6 +991,7 @@ int radeon_gem_mm_init(struct drm_device *dev) dev_priv->mm.gart_size = (32 * 1024 * 1024); dev_priv->mm.gart_start = 0; + dev_priv->mm.gart_useable = dev_priv->mm.gart_size; ret = radeon_gart_init(dev); if (ret) return -EINVAL; @@ -1293,6 +1296,7 @@ static int radeon_gem_ib_init(struct drm_device *dev) goto free_all; } + dev_priv->mm.gart_useable -= RADEON_IB_SIZE * RADEON_NUM_IB; dev_priv->ib_alloc_bitmap = 0; dev_priv->cs.ib_get = radeon_gem_ib_get; @@ -1529,6 +1533,7 @@ static int radeon_gem_dma_bufs_init(struct drm_device *dev) DRM_ERROR("Failed to mmap DMA buffers\n"); return -ENOMEM; } + dev_priv->mm.gart_useable -= size; DRM_DEBUG("\n"); radeon_gem_addbufs(dev); -- cgit v1.2.3 From a7457915f5775137436f3b16a640eb8bd6424ca6 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 12 Nov 2008 15:56:40 +0100 Subject: radeon+libdrm-radeon: change relocation informations Relocation now consist of the following informations (in this order) : handle buffer object handle identifier start_offset start offset of first data of the buffer object used by the cs end_offset end offset of last data of the buffer object used by the cs read_domain read domain (either VRAM, or GTT as GPU is invalid for CS) write_domain write domain (either VRAM, or GTT as GPU is invalid for CS) flags flags used for further optimization (like discard previous buffer content or forget buffer content after cs which can help in avoiding moving content in or out) --- linux-core/radeon_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/radeon_gem.c') 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; } -- cgit v1.2.3