aboutsummaryrefslogtreecommitdiff
path: root/linux-core/drm_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/drm_gem.c')
-rw-r--r--linux-core/drm_gem.c386
1 files changed, 9 insertions, 377 deletions
diff --git a/linux-core/drm_gem.c b/linux-core/drm_gem.c
index a8ecaf76..76d7aa94 100644
--- a/linux-core/drm_gem.c
+++ b/linux-core/drm_gem.c
@@ -74,6 +74,11 @@ drm_gem_init(struct drm_device *dev)
spin_lock_init(&dev->object_name_lock);
idr_init(&dev->object_name_idr);
atomic_set(&dev->object_count, 0);
+ atomic_set(&dev->object_memory, 0);
+ atomic_set(&dev->pin_count, 0);
+ atomic_set(&dev->pin_memory, 0);
+ atomic_set(&dev->gtt_count, 0);
+ atomic_set(&dev->gtt_memory, 0);
return 0;
}
@@ -99,15 +104,6 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
kref_init(&obj->refcount);
kref_init(&obj->handlecount);
obj->size = size;
-
- /*
- * We've just allocated pages from the kernel,
- * so they've just been written by the CPU with
- * zeros. They'll need to be clflushed before we
- * use them with the GPU.
- */
- obj->write_domain = DRM_GEM_DOMAIN_CPU;
- obj->read_domains = DRM_GEM_DOMAIN_CPU;
if (dev->driver->gem_init_object != NULL &&
dev->driver->gem_init_object(obj) != 0) {
fput(obj->filp);
@@ -115,55 +111,17 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
return NULL;
}
atomic_inc(&dev->object_count);
+ atomic_add(obj->size, &dev->object_memory);
return obj;
}
EXPORT_SYMBOL(drm_gem_object_alloc);
/**
- * Removes the mapping from handle to filp for this object.
- */
-static int
-drm_gem_handle_delete(struct drm_file *filp, int handle)
-{
- struct drm_device *dev;
- struct drm_gem_object *obj;
-
- /* This is gross. The idr system doesn't let us try a delete and
- * return an error code. It just spews if you fail at deleting.
- * So, we have to grab a lock around finding the object and then
- * doing the delete on it and dropping the refcount, or the user
- * could race us to double-decrement the refcount and cause a
- * use-after-free later. Given the frequency of our handle lookups,
- * we may want to use ida for number allocation and a hash table
- * for the pointers, anyway.
- */
- spin_lock(&filp->table_lock);
-
- /* Check if we currently have a reference on the object */
- obj = idr_find(&filp->object_idr, handle);
- if (obj == NULL) {
- spin_unlock(&filp->table_lock);
- return -EINVAL;
- }
- dev = obj->dev;
-
- /* Release reference and decrement refcount. */
- idr_remove(&filp->object_idr, handle);
- spin_unlock(&filp->table_lock);
-
- mutex_lock(&dev->struct_mutex);
- drm_gem_object_handle_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/**
* Create a handle for this object. This adds a handle reference
* to the object, which includes a regular reference count. Callers
* will likely want to dereference the object afterwards.
*/
-static int
+int
drm_gem_handle_create(struct drm_file *file_priv,
struct drm_gem_object *obj,
int *handlep)
@@ -191,6 +149,7 @@ again:
drm_gem_object_handle_reference(obj);
return 0;
}
+EXPORT_SYMBOL(drm_gem_handle_create);
/** Returns a reference to the object named by the handle. */
struct drm_gem_object *
@@ -217,334 +176,6 @@ drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
EXPORT_SYMBOL(drm_gem_object_lookup);
/**
- * Creates a new mm object and returns a handle to it.
- */
-int
-drm_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_create *args = data;
- struct drm_gem_object *obj;
- int handle, ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- args->size = roundup(args->size, PAGE_SIZE);
-
- /* Allocate the new object */
- obj = drm_gem_object_alloc(dev, args->size);
- if (obj == NULL)
- return -ENOMEM;
-
- 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)
- return ret;
-
- args->handle = handle;
-
- return 0;
-}
-
-/**
- * Releases the handle to an mm object.
- */
-int
-drm_gem_close_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_close *args = data;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- ret = drm_gem_handle_delete(file_priv, args->handle);
-
- return ret;
-}
-
-/**
- * Reads data from the object referenced by handle.
- *
- * On error, the contents of *data are undefined.
- */
-int
-drm_gem_pread_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_pread *args = data;
- struct drm_gem_object *obj;
- ssize_t read;
- loff_t offset;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (obj == NULL)
- return -EINVAL;
-
- mutex_lock(&dev->struct_mutex);
- if (dev->driver->gem_set_domain) {
- ret = dev->driver->gem_set_domain(obj, file_priv,
- DRM_GEM_DOMAIN_CPU,
- 0);
- if (ret) {
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
- }
- offset = args->offset;
-
- read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr,
- args->size, &offset);
- if (read != args->size) {
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- if (read < 0)
- return read;
- else
- return -EINVAL;
- }
-
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/**
- * Maps the contents of an object, returning the address it is mapped
- * into.
- *
- * While the mapping holds a reference on the contents of the object, it doesn't
- * imply a ref on the object itself.
- */
-int
-drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_mmap *args = data;
- struct drm_gem_object *obj;
- loff_t offset;
- unsigned long addr;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (obj == NULL)
- return -EINVAL;
-
- offset = args->offset;
-
- down_write(&current->mm->mmap_sem);
- addr = do_mmap(obj->filp, 0, args->size,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- args->offset);
- up_write(&current->mm->mmap_sem);
- 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;
-}
-
-/**
- * Writes data to the object referenced by handle.
- *
- * On error, the contents of the buffer that were to be modified are undefined.
- */
-int
-drm_gem_pwrite_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_pwrite *args = data;
- struct drm_gem_object *obj;
- ssize_t written;
- loff_t offset;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (obj == NULL)
- return -EINVAL;
-
- mutex_lock(&dev->struct_mutex);
- if (dev->driver->gem_set_domain) {
- ret = dev->driver->gem_set_domain(obj, file_priv,
- DRM_GEM_DOMAIN_CPU,
- DRM_GEM_DOMAIN_CPU);
- if (ret) {
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
- }
- offset = args->offset;
-
- written = vfs_write(obj->filp,
- (char __user *)(uintptr_t) args->data_ptr,
- args->size, &offset);
-
- if (written != args->size) {
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- if (written < 0)
- return written;
- else
- return -EINVAL;
- }
-
- if (dev->driver->gem_flush_pwrite)
- dev->driver->gem_flush_pwrite(obj,
- args->offset,
- args->size);
-
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-/**
- * Create a global name for an object, returning the name.
- *
- * Note that the name does not hold a reference; when the object
- * is freed, the name goes away.
- */
-int
-drm_gem_flink_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_flink *args = data;
- struct drm_gem_object *obj;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (obj == NULL)
- return -EINVAL;
-
-again:
- if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
- return -ENOMEM;
-
- spin_lock(&dev->object_name_lock);
- if (obj->name) {
- spin_unlock(&dev->object_name_lock);
- return -EEXIST;
- }
- ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
- &obj->name);
- spin_unlock(&dev->object_name_lock);
- if (ret == -EAGAIN)
- goto again;
-
- if (ret != 0) {
- mutex_lock(&dev->struct_mutex);
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
-
- /*
- * Leave the reference from the lookup around as the
- * name table now holds one
- */
- args->name = (uint64_t) obj->name;
-
- return 0;
-}
-
-/**
- * Open an object using the global name, returning a handle and the size.
- *
- * This handle (of course) holds a reference to the object, so the object
- * will not go away until the handle is deleted.
- */
-int
-drm_gem_open_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_open *args = data;
- struct drm_gem_object *obj;
- int ret;
- int handle;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- spin_lock(&dev->object_name_lock);
- obj = idr_find(&dev->object_name_idr, (int) args->name);
- if (obj)
- drm_gem_object_reference(obj);
- spin_unlock(&dev->object_name_lock);
- if (!obj)
- return -ENOENT;
-
- ret = drm_gem_handle_create(file_priv, obj, &handle);
- mutex_lock(&dev->struct_mutex);
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- if (ret)
- return ret;
-
- args->handle = handle;
- args->size = obj->size;
-
- return 0;
-}
-
-/**
- * Called when user space prepares to use an object
- */
-int
-drm_gem_set_domain_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_gem_set_domain *args = data;
- struct drm_gem_object *obj;
- int ret;
-
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (obj == NULL)
- return -EINVAL;
-
- mutex_lock(&dev->struct_mutex);
- if (dev->driver->gem_set_domain) {
- ret = dev->driver->gem_set_domain(obj, file_priv,
- args->read_domains,
- args->write_domain);
- } else {
- obj->read_domains = args->read_domains;
- obj->write_domain = args->write_domain;
- ret = 0;
- }
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
-}
-
-/**
* Called at device open time, sets up the structure for handling refcounting
* of mm objects.
*/
@@ -603,6 +234,7 @@ drm_gem_object_free(struct kref *kref)
fput(obj->filp);
atomic_dec(&dev->object_count);
+ atomic_sub(obj->size, &dev->object_memory);
kfree(obj);
}
EXPORT_SYMBOL(drm_gem_object_free);