Jesse Barnes wrote:
> Ok, here's an updated patch (note: only compile tested!) which I think
> addresses all of the comments I received. I switched over to using
> dev_mapping for unmapping and tried to cleanup the mm mmap & private fields a
> bit.
>
> How does it look?
>
> Thanks,
> Jesse
>
> ------------------------------------------------------------------------
>
> diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
> index bde64b8..9916366 100644
> --- a/drivers/gpu/drm/drm_bufs.c
> +++ b/drivers/gpu/drm/drm_bufs.c
> @@ -262,6 +262,9 @@ static int drm_addmap_core(struct drm_device * dev,
> unsigned int offset,
> DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n",
> map->offset, map->size);
>
> break;
> + case _DRM_GEM:
> + DRM_ERROR("tried to rmmap GEM object\n");
> + break;
> }
> case _DRM_SCATTER_GATHER:
> if (!dev->sg) {
> @@ -419,6 +422,9 @@ int drm_rmmap_locked(struct drm_device *dev,
> drm_local_map_t *map)
> dmah.size = map->size;
> __drm_pci_free(dev, &dmah);
> break;
> + case _DRM_GEM:
> + DRM_ERROR("tried to rmmap GEM object\n");
> + break;
> }
> drm_free(map, sizeof(*map), DRM_MEM_MAPS);
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index f934414..cb8cb16 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -234,6 +234,7 @@ int drm_lastclose(struct drm_device * dev)
> dev->lock.file_priv = NULL;
> wake_up_interruptible(&dev->lock.lock_queue);
> }
> + dev->dev_mapping = NULL;
> mutex_unlock(&dev->struct_mutex);
>
> DRM_DEBUG("lastclose completed\n");
> @@ -288,6 +289,8 @@ EXPORT_SYMBOL(drm_init);
> */
> static void drm_cleanup(struct drm_device * dev)
> {
> + struct drm_driver *driver = dev->driver;
> +
> DRM_DEBUG("\n");
>
> if (!dev) {
> @@ -317,6 +320,9 @@ static void drm_cleanup(struct drm_device * dev)
> drm_ht_remove(&dev->map_hash);
> drm_ctxbitmap_cleanup(dev);
>
> + if (driver->driver_features & DRIVER_GEM)
> + drm_gem_destroy(dev);
> +
> drm_put_minor(&dev->primary);
> if (drm_put_dev(dev))
> DRM_ERROR("Cannot unload module\n");
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index c0a309a..398d60b 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -147,11 +147,20 @@ int drm_open(struct inode *inode, struct file *filp)
> spin_lock(&dev->count_lock);
> if (!dev->open_count++) {
> spin_unlock(&dev->count_lock);
> - return drm_setup(dev);
> + retcode = drm_setup(dev);
> + goto out;
> }
> spin_unlock(&dev->count_lock);
> }
>
> +out:
> + mutex_lock(&dev->struct_mutex);
> + BUG_ON((dev->dev_mapping != NULL) &&
> + (dev->dev_mapping != inode->i_mapping));
> + if (dev->dev_mapping == NULL)
> + dev->dev_mapping = inode->i_mapping;
> + mutex_unlock(&dev->struct_mutex);
> +
> return retcode;
> }
> EXPORT_SYMBOL(drm_open);
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index ccd1afd..cfd2ca6 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -64,6 +64,13 @@
> * up at a later date, and as our interface with shmfs for memory allocation.
> */
>
> +/*
> + * We make up offsets for buffer objects so we can recognize them at
> + * mmap time.
> + */
> +#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
> +#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
> +
> /**
> * Initialize the GEM device fields
> */
> @@ -71,6 +78,8 @@
> int
> drm_gem_init(struct drm_device *dev)
> {
> + struct drm_gem_mm *mm;
> +
> spin_lock_init(&dev->object_name_lock);
> idr_init(&dev->object_name_idr);
> atomic_set(&dev->object_count, 0);
> @@ -79,9 +88,41 @@ drm_gem_init(struct drm_device *dev)
> atomic_set(&dev->pin_memory, 0);
> atomic_set(&dev->gtt_count, 0);
> atomic_set(&dev->gtt_memory, 0);
> +
> + mm = drm_calloc(1, sizeof(struct drm_gem_mm), DRM_MEM_MM);
> + if (!mm) {
> + DRM_ERROR("out of memory\n");
> + return -ENOMEM;
> + }
> +
> + dev->mm_private = mm;
> +
> + if (drm_ht_create(&mm->offset_hash, 19)) {
> + drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
> + return -ENOMEM;
> + }
> +
> + if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
> + DRM_FILE_PAGE_OFFSET_SIZE)) {
> + drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
> + drm_ht_remove(&mm->offset_hash);
> + return -ENOMEM;
> + }
> +
> return 0;
> }
>
> +void
> +drm_gem_destroy(struct drm_device *dev)
> +{
> + struct drm_gem_mm *mm = dev->mm_private;
> +
> + drm_mm_takedown(&mm->offset_manager);
> + drm_ht_remove(&mm->offset_hash);
> + drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
> + dev->mm_private = NULL;
> +}
> +
> /**
> * Allocate a GEM object of the specified size with shmfs backing store
> */
> @@ -419,3 +460,63 @@ drm_gem_object_handle_free(struct kref *kref)
> }
> EXPORT_SYMBOL(drm_gem_object_handle_free);
>
> +int
> +drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
> +{
> + struct drm_file *priv = filp->private_data;
> + struct drm_device *dev = priv->minor->dev;
> + struct drm_gem_mm *mm = dev->mm_private;
> + struct drm_map *map = NULL;
> + struct drm_gem_object *obj = map->handle;
> + struct drm_hash_item *hash;
> + int ret = 0;
> +
> + mutex_lock(&dev->struct_mutex);
> +
> + DRM_ERROR("looking for object at 0x%08lx\n", vma->vm_pgoff);
> + if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
> + DRM_ERROR("Could not find map\n");
> + ret = -EINVAL;
> + goto out_unlock;
> + }
> +
> + map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
> + if (!map ||
> + ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
> + ret = -EPERM;
> + goto out_unlock;
> + }
> +
> + /* Check for valid size. */
> + if (map->size < vma->vm_end - vma->vm_start) {
> + ret = -EINVAL;
> + goto out_unlock;
> + }
> +
> + if (map->type != _DRM_GEM) {
> + ret = drm_mmap_locked(filp, vma);
> + goto out_unlock;
> + }
> +
> +
> + if (!obj->dev->driver->gem_vm_ops) {
> + ret = -EINVAL;
> + goto out_unlock;
> + }
> +
> + vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
> + vma->vm_ops = obj->dev->driver->gem_vm_ops;
> + vma->vm_private_data = map->handle;
> + vma->vm_file = obj->filp;
> + /* FIXME: use WC or UC- so we can pick up MTRR settings */
> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> +
> + vma->vm_file = filp; /* Needed for drm_vm_open() */
> + drm_vm_open_locked(vma);
> +
> +out_unlock:
> + mutex_unlock(&dev->struct_mutex);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(drm_gem_mmap);
> diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
> index 3316067..af539f7 100644
> --- a/drivers/gpu/drm/drm_hashtab.c
> +++ b/drivers/gpu/drm/drm_hashtab.c
> @@ -127,6 +127,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct
> drm_hash_item *item)
> }
> return 0;
> }
> +EXPORT_SYMBOL(drm_ht_insert_item);
>
> /*
> * Just insert an item and return any "bits" bit key that hasn't been
> @@ -188,6 +189,7 @@ int drm_ht_remove_item(struct drm_open_hash *ht, struct
> drm_hash_item *item)
> ht->fill--;
> return 0;
> }
> +EXPORT_SYMBOL(drm_ht_remove_item);
>
> void drm_ht_remove(struct drm_open_hash *ht)
> {
> diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
> index c234c6f..3ffae02 100644
> --- a/drivers/gpu/drm/drm_vm.c
> +++ b/drivers/gpu/drm/drm_vm.c
> @@ -267,6 +267,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
> dmah.size = map->size;
> __drm_pci_free(dev, &dmah);
> break;
> + case _DRM_GEM:
> + DRM_ERROR("tried to rmmap GEM object\n");
> + break;
> }
> drm_free(map, sizeof(*map), DRM_MEM_MAPS);
> }
> @@ -399,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
> * Create a new drm_vma_entry structure as the \p vma private data entry and
> * add it to drm_device::vmalist.
> */
> -static void drm_vm_open_locked(struct vm_area_struct *vma)
> +void drm_vm_open_locked(struct vm_area_struct *vma)
> {
> struct drm_file *priv = vma->vm_file->private_data;
> struct drm_device *dev = priv->minor->dev;
> @@ -540,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
> * according to the mapping type and remaps the pages. Finally sets the file
> * pointer and calls vm_open().
> */
> -static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
> +int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
> {
> struct drm_file *priv = filp->private_data;
> struct drm_device *dev = priv->minor->dev;
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 93ca81b..0568c0e 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -954,6 +954,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
> DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
> DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
> DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
> + DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0),
> DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
> DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
> DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index e7c05d8..d58c709 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -539,6 +539,10 @@ static int i915_resume(struct drm_device *dev)
> return 0;
> }
>
> +static struct vm_operations_struct i915_gem_vm_ops = {
> + .fault = i915_gem_fault,
> +};
> +
> static struct drm_driver driver = {
> /* don't use mtrr's here, the Xserver or user space app should
> * deal with them for intel hardware.
> @@ -569,13 +573,14 @@ static struct drm_driver driver = {
> .proc_cleanup = i915_gem_proc_cleanup,
> .gem_init_object = i915_gem_init_object,
> .gem_free_object = i915_gem_free_object,
> + .gem_vm_ops = &i915_gem_vm_ops,
> .ioctls = i915_ioctls,
> .fops = {
> .owner = THIS_MODULE,
> .open = drm_open,
> .release = drm_release,
> .ioctl = drm_ioctl,
> - .mmap = drm_mmap,
> + .mmap = drm_gem_mmap,
> .poll = drm_poll,
> .fasync = drm_fasync,
> #ifdef CONFIG_COMPAT
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 5e64b21..7135566 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -350,6 +350,8 @@ struct drm_i915_gem_object {
> * This is the same as gtt_space->start
> */
> uint32_t gtt_offset;
> + uint32_t gtt_alignment;
> + uint64_t mmap_offset;
>
> /** Boolean whether this object has a valid gtt offset. */
> int gtt_bound;
> @@ -466,6 +468,8 @@ int i915_gem_pwrite_ioctl(struct drm_device *dev, void
> *data,
> struct drm_file *file_priv);
> int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
> struct drm_file *file_priv);
> +int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *file_priv);
> int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
> struct drm_file *file_priv);
> int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
> @@ -500,6 +504,12 @@ uint32_t i915_get_gem_seqno(struct drm_device *dev);
> void i915_gem_retire_requests(struct drm_device *dev);
> void i915_gem_retire_work_handler(struct work_struct *work);
> void i915_gem_clflush_object(struct drm_gem_object *obj);
> +void i915_gem_vm_open(struct vm_area_struct *vma);
> +void i915_gem_vm_close(struct vm_area_struct *vma);
> +int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
> +int i915_gem_vm_mkwrite(struct vm_area_struct *vma, struct page *page);
> +int i915_gem_vm_access(struct vm_area_struct *vma, unsigned long addr,
> + void *buf, int len, int write);
>
> /* i915_gem_tiling.c */
> void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 29d9d21..0581f41 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -30,6 +30,7 @@
> #include "i915_drm.h"
> #include "i915_drv.h"
> #include <linux/swap.h>
> +#include <linux/pci.h>
>
> static int
> i915_gem_object_set_domain(struct drm_gem_object *obj,
> @@ -49,6 +50,8 @@ i915_gem_set_domain(struct drm_gem_object *obj,
> static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
> static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
> static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
> +static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
> + unsigned alignment);
>
> int
> i915_gem_init_ioctl(struct drm_device *dev, void *data,
> @@ -467,6 +470,75 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
> return 0;
> }
>
> +int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> +{
> + struct drm_gem_object *obj = vma->vm_private_data;
> + struct drm_device *dev = obj->dev;
> + struct drm_i915_gem_object *obj_priv = obj->driver_private;
> + unsigned long pfn;
> + int ret = 0;
> +
> + DRM_ERROR("faulting in object %d offset 0x%08lx\n", obj->name,
> + vmf->pgoff);
> +
> + /* Now bind it into the GTT */
> + if (i915_gem_object_bind_to_gtt(obj, obj_priv->gtt_alignment))
> + return VM_FAULT_SIGBUS;
> +
> + pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
> + vmf->pgoff;
> + /* Finally, remap it using the new GTT offset */
> + ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
> +
> + switch (ret) {
> + case -ENOMEM:
> + case -EAGAIN:
> + return VM_FAULT_OOM;
> + case -EFAULT:
> + case -EBUSY:
> + DRM_ERROR("can't insert pfn?? fault or busy...\n");
> + return VM_FAULT_SIGBUS;
> + default:
> + return VM_FAULT_NOPAGE;
> + }
> +}
> +
> +/**
> + * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
> + * @dev: DRM device
> + * @data: GTT mapping ioctl data
> + * @file_priv: GEM object info
> + *
> + * Allocate a fake mmap offset for the given object and add it
> + * to the DRM map hash. This allows drm_mmap() to find it so that
> + * the vm_ops can be overridden with GEM fault & access handlers.
> + */
> +int
> +i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *file_priv)
> +{
> + struct drm_i915_gem_mmap_gtt *args = data;
> + struct drm_gem_object *obj;
> + struct drm_i915_gem_object *obj_priv;
> +
> + if (!(dev->driver->driver_features & DRIVER_GEM))
> + return -ENODEV;
> +
> + obj = drm_gem_object_lookup(dev, file_priv, args->handle);
> + if (obj == NULL)
> + return -EBADF;
> +
> + obj_priv = obj->driver_private;
> + obj_priv->gtt_alignment = args->alignment;
> + args->addr_ptr = obj_priv->mmap_offset;
> +
> + mutex_lock(&dev->struct_mutex);
> + drm_gem_object_unreference(obj);
> + mutex_unlock(&dev->struct_mutex);
> +
> + return 0;
> +}
> +
> static void
> i915_gem_object_free_page_list(struct drm_gem_object *obj)
> {
> @@ -940,6 +1012,13 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
>
> BUG_ON(obj_priv->active);
>
> + /* blow away mappings if mapped through GTT */
> + if (dev->dev_mapping) {
> + loff_t offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT;
> +
> + unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1);
> + }
> +
> i915_gem_object_free_page_list(obj);
>
> if (obj_priv->gtt_space) {
> @@ -2120,7 +2199,12 @@ i915_gem_throttle_ioctl(struct drm_device *dev, void
> *data,
>
> int i915_gem_init_object(struct drm_gem_object *obj)
> {
> + struct drm_device *dev = obj->dev;
> + struct drm_gem_mm *mm = dev->mm_private;
> struct drm_i915_gem_object *obj_priv;
> + struct drm_map_list *list;
> + struct drm_map *map;
> + int ret = 0;
>
> obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
> if (obj_priv == NULL)
> @@ -2138,11 +2222,62 @@ int i915_gem_init_object(struct drm_gem_object *obj)
> obj->driver_private = obj_priv;
> obj_priv->obj = obj;
> INIT_LIST_HEAD(&obj_priv->list);
> +
> + /* Set the object up for mmap'ing */
> + list = &obj->map_list;
> + list->map = drm_calloc(1, sizeof(struct drm_map_list),
> + DRM_MEM_DRIVER);
> + if (!list->map)
> + return -ENOMEM;
> +
> + map = list->map;
> + map->type = _DRM_GEM;
> + map->size = obj->size;
> + map->handle = obj;
> +
> + /* Get a DRM GEM mmap offset allocated... */
> + list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
> + obj->size / PAGE_SIZE, 0,
> 0);
> + if (!list->file_offset_node) {
> + DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
> + ret = -ENOMEM;
> + goto out_free_list;
> + }
> +
> + list->file_offset_node = drm_mm_get_block(list->file_offset_node,
> + obj->size / PAGE_SIZE, 0);
> + if (!list->file_offset_node) {
> + ret = -ENOMEM;
> + goto out_free_list;
> + }
> +
> + list->hash.key = list->file_offset_node->start;
> + if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) {
> + DRM_ERROR("failed to add to map hash\n");
> + goto out_free_mm;
> + return -ENOMEM;
> + }
> +
> + /* By now we should be all set, any drm_mmap request on the offset
> + * below will get to our mmap & fault handler */
> + obj_priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT;
> +
> return 0;
> +
> +out_free_mm:
> + drm_mm_put_block(list->file_offset_node);
> +out_free_list:
> + drm_free(list->map, sizeof(struct drm_map_list), DRM_MEM_DRIVER);
> +
> + return ret;
> }
>
> void i915_gem_free_object(struct drm_gem_object *obj)
> {
> + struct drm_device *dev = obj->dev;
> + struct drm_gem_mm *mm = dev->mm_private;
> + struct drm_map_list *list;
> + struct drm_map *map;
> struct drm_i915_gem_object *obj_priv = obj->driver_private;
>
> while (obj_priv->pin_count > 0)
> @@ -2150,6 +2285,20 @@ void i915_gem_free_object(struct drm_gem_object *obj)
>
> i915_gem_object_unbind(obj);
>
> + list = &obj->map_list;
> + drm_ht_remove_item(&mm->offset_hash, &list->hash);
> +
> + if (list->file_offset_node) {
> + drm_mm_put_block(list->file_offset_node);
> + list->file_offset_node = NULL;
> + }
> +
> + map = list->map;
> + if (map) {
> + drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
> + list->map = NULL;
> + }
> +
> drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
> drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
> }
> @@ -2265,7 +2414,15 @@ i915_gem_idle(struct drm_device *dev)
> * waited for a sequence higher than any pending execbuffer
> */
> BUG_ON(!list_empty(&dev_priv->mm.active_list));
> - BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
> + if (!list_empty(&dev_priv->mm.flushing_list)) {
> + struct drm_i915_gem_object *obj_priv;
> + DRM_ERROR("flushing list not empty, still has:\n");
> + list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
> + list) {
> + DRM_ERROR(" %p: %08x\n", obj_priv,
> + obj_priv->last_rendering_seqno);
> + }
> + }
>
> /* Request should now be empty as we've also waited
> * for the last request in the list
> @@ -2278,7 +2435,6 @@ i915_gem_idle(struct drm_device *dev)
> return ret;
>
> BUG_ON(!list_empty(&dev_priv->mm.active_list));
> - BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
> BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
> BUG_ON(!list_empty(&dev_priv->mm.request_list));
> return 0;
> @@ -2369,7 +2525,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
> dev_priv->ring.map.flags = 0;
> dev_priv->ring.map.mtrr = 0;
>
> - drm_core_ioremap(&dev_priv->ring.map, dev);
> + DRM_ERROR("remapping ring, offset 0x%08lx size %ld\n",
> + dev_priv->ring.map.offset, obj->size);
> + drm_core_ioremap_wc(&dev_priv->ring.map, dev);
> if (dev_priv->ring.map.handle == NULL) {
> DRM_ERROR("Failed to map ringbuffer.\n");
> memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
> diff --git a/include/drm/drm.h b/include/drm/drm.h
> index dc347ef..8b3c126 100644
> --- a/include/drm/drm.h
> +++ b/include/drm/drm.h
> @@ -190,6 +190,7 @@ enum drm_map_type {
> _DRM_AGP = 3, /**< AGP/GART */
> _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
> _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
> + _DRM_GEM = 6, /**< GEM object */
> };
>
> /**
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index eb2a05f..115e3eb 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -523,6 +523,7 @@ struct drm_map_list {
> struct drm_hash_item hash;
> struct drm_map *map; /**< mapping */
> uint64_t user_token;
> + struct drm_mm_node *file_offset_node; /**< fake offset */
> };
>
> typedef struct drm_map drm_local_map_t;
> @@ -563,6 +564,14 @@ struct drm_ati_pcigart_info {
> };
>
> /**
> + * GEM specific mm private for tracking GEM objects
> + */
> +struct drm_gem_mm {
> + struct drm_mm offset_manager; /**< Offset mgmt for buffer objects */
> + struct drm_open_hash offset_hash; /**< User token hash table for maps */
> +};
> +
> +/**
> * This structure defines the drm_mm memory object, which will be used by the
> * DRM for its buffer objects.
> */
> @@ -579,6 +588,9 @@ struct drm_gem_object {
> /** File representing the shmem storage */
> struct file *filp;
>
> + /* Mapping info for this object */
> + struct drm_map_list map_list;
> +
> /**
> * Size of the object, in bytes. Immutable over the object's
> * lifetime.
> @@ -681,6 +693,9 @@ struct drm_driver {
> int (*gem_init_object) (struct drm_gem_object *obj);
> void (*gem_free_object) (struct drm_gem_object *obj);
>
> + /* Driver private ops for this object */
> + struct vm_operations_struct *gem_vm_ops;
> +
> int major;
> int minor;
> int patchlevel;
> @@ -825,6 +840,8 @@ struct drm_device {
> #endif
> struct drm_sg_mem *sg; /**< Scatter gather memory */
> void *dev_private; /**< device private data */
> + void *mm_private;
> + struct address_space *dev_mapping;
> struct drm_sigdata sigdata; /**< For block_all_signals */
> sigset_t sigmask;
>
> @@ -936,6 +953,8 @@ extern int drm_release(struct inode *inode, struct file
> *filp);
>
> /* Mapping support (drm_vm.h) */
> extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
> +extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
> +extern void drm_vm_open_locked(struct vm_area_struct *vma);
> extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
> extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
> extern unsigned int drm_poll(struct file *filp, struct poll_table_struct
> *wait);
> @@ -1182,10 +1201,12 @@ extern int drm_mm_add_space_to_tail(struct drm_mm
> *mm, unsigned long size);
>
> /* Graphics Execution Manager library functions (drm_gem.c) */
> int drm_gem_init(struct drm_device *dev);
> +void drm_gem_destroy(struct drm_device *dev);
> void drm_gem_object_free(struct kref *kref);
> struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
> size_t size);
> void drm_gem_object_handle_free(struct kref *kref);
> +int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
>
> static inline void
> drm_gem_object_reference(struct drm_gem_object *obj)
> diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
> index eb4b350..fed1d7c 100644
> --- a/include/drm/i915_drm.h
> +++ b/include/drm/i915_drm.h
> @@ -159,6 +159,7 @@ typedef struct _drm_i915_sarea {
> #define DRM_I915_GEM_SW_FINISH 0x20
> #define DRM_I915_GEM_SET_TILING 0x21
> #define DRM_I915_GEM_GET_TILING 0x22
> +#define DRM_I915_GEM_MMAP_GTT 0x23
>
> #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE +
> DRM_I915_INIT, drm_i915_init_t)
> #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE +
> DRM_I915_FLUSH)
> @@ -186,6 +187,7 @@ typedef struct _drm_i915_sarea {
> #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE +
> DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
> #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE +
> DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
> #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE +
> DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
> +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE +
> DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
> #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE +
> DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
> #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE +
> DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
> #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE +
> DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
> @@ -380,6 +382,24 @@ struct drm_i915_gem_mmap {
> uint64_t addr_ptr;
> };
>
> +struct drm_i915_gem_mmap_gtt {
> + /** Handle for the object being mapped. */
> + uint32_t handle;
> + uint32_t pad;
> + /** Offset in the object to map. */
> + uint64_t offset;
> + /**
> + * Length of data to map.
> + *
> + * The value will be page-aligned.
> + */
> + uint64_t size;
> + /** Returned pointer the data was mapped at */
> + uint64_t addr_ptr; /* void *, but pointers are not 32/64
> compatible */
> + uint32_t flags;
> + uint32_t alignment;
> +};
> +
> struct drm_i915_gem_set_domain {
> /** Handle for the object */
> uint32_t handle;
>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
--
_______________________________________________
Dri-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel