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

Reply via email to