gpu: ion: Update print format in Ion.
[linux-2.6.git] / drivers / gpu / ion / ion.c
index 1a63ebf..28b8bb4 100644 (file)
@@ -14,6 +14,8 @@
  *
  */
 
+#define pr_fmt(fmt)    "%s():%d: " fmt, __func__, __LINE__
+
 #include <linux/device.h>
 #include <linux/file.h>
 #include <linux/fs.h>
 #include "ion_priv.h"
 #define DEBUG
 
-/**
- * struct ion_device - the metadata of the ion device node
- * @dev:               the actual misc device
- * @buffers:   an rb tree of all the existing buffers
- * @lock:              lock protecting the buffers & heaps trees
- * @heaps:             list of all the heaps in the system
- * @user_clients:      list of all the clients created from userspace
- */
-struct ion_device {
-       struct miscdevice dev;
-       struct rb_root buffers;
-       struct mutex lock;
-       struct rb_root heaps;
-       long (*custom_ioctl) (struct ion_client *client, unsigned int cmd,
-                             unsigned long arg);
-       struct rb_root user_clients;
-       struct rb_root kernel_clients;
-       struct dentry *debug_root;
-};
-
-/**
- * struct ion_client - a process/hw block local address space
- * @ref:               for reference counting the client
- * @node:              node in the tree of all clients
- * @dev:               backpointer to ion device
- * @handles:           an rb tree of all the handles in this client
- * @lock:              lock protecting the tree of handles
- * @heap_mask:         mask of all supported heaps
- * @name:              used for debugging
- * @task:              used for debugging
- *
- * A client represents a list of buffers this client may access.
- * The mutex stored here is used to protect both handles tree
- * as well as the handles themselves, and should be held while modifying either.
- */
-struct ion_client {
-       struct kref ref;
-       struct rb_node node;
-       struct ion_device *dev;
-       struct rb_root handles;
-       struct mutex lock;
-       unsigned int heap_mask;
-       const char *name;
-       struct task_struct *task;
-       pid_t pid;
-       struct dentry *debug_root;
-};
-
-/**
- * ion_handle - a client local reference to a buffer
- * @ref:               reference count
- * @client:            back pointer to the client the buffer resides in
- * @buffer:            pointer to the buffer
- * @node:              node in the client's handle rbtree
- * @kmap_cnt:          count of times this client has mapped to kernel
- * @dmap_cnt:          count of times this client has mapped for dma
- * @usermap_cnt:       count of times this client has mapped for userspace
- *
- * Modifications to node, map_cnt or mapping should be protected by the
- * lock in the client.  Other fields are never changed after initialization.
- */
-struct ion_handle {
-       struct kref ref;
-       struct ion_client *client;
-       struct ion_buffer *buffer;
-       struct rb_node node;
-       unsigned int kmap_cnt;
-       unsigned int dmap_cnt;
-       unsigned int usermap_cnt;
-};
-
 /* this function should only be called while dev->lock is held */
 static void ion_buffer_add(struct ion_device *dev,
                           struct ion_buffer *buffer)
@@ -121,7 +52,7 @@ static void ion_buffer_add(struct ion_device *dev,
                } else if (buffer > entry) {
                        p = &(*p)->rb_right;
                } else {
-                       pr_err("%s: buffer already found.", __func__);
+                       pr_err("buffer already found.");
                        BUG();
                }
        }
@@ -131,7 +62,7 @@ static void ion_buffer_add(struct ion_device *dev,
 }
 
 /* this function should only be called while dev->lock is held */
-struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
+static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
                                     struct ion_device *dev,
                                     unsigned long len,
                                     unsigned long align,
@@ -171,7 +102,7 @@ static void ion_buffer_destroy(struct kref *kref)
        kfree(buffer);
 }
 
-static void ion_buffer_get(struct ion_buffer *buffer)
+void ion_buffer_get(struct ion_buffer *buffer)
 {
        kref_get(&buffer->ref);
 }
@@ -190,6 +121,7 @@ struct ion_handle *ion_handle_create(struct ion_client *client,
        if (!handle)
                return ERR_PTR(-ENOMEM);
        kref_init(&handle->ref);
+       rb_init_node(&handle->node);
        handle->client = client;
        ion_buffer_get(buffer);
        handle->buffer = buffer;
@@ -205,7 +137,8 @@ static void ion_handle_destroy(struct kref *kref)
         */
        ion_buffer_put(handle->buffer);
        mutex_lock(&handle->client->lock);
-       rb_erase(&handle->node, &handle->client->handles);
+       if (!RB_EMPTY_NODE(&handle->node))
+               rb_erase(&handle->node, &handle->client->handles);
        mutex_unlock(&handle->client->lock);
        kfree(handle);
 }
@@ -215,12 +148,12 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle)
        return handle->buffer;
 }
 
-static void ion_handle_get(struct ion_handle *handle)
+void ion_handle_get(struct ion_handle *handle)
 {
        kref_get(&handle->ref);
 }
 
-static int ion_handle_put(struct ion_handle *handle)
+int ion_handle_put(struct ion_handle *handle)
 {
        return kref_put(&handle->ref, ion_handle_destroy);
 }
@@ -253,10 +186,12 @@ bool ion_handle_validate(struct ion_client *client, struct ion_handle *handle)
                else
                        return true;
        }
+       WARN(1, "invalid handle passed h=0x%x,comm=%d\n", handle,
+               current->group_leader->comm);
        return false;
 }
 
-static void ion_handle_add(struct ion_client *client, struct ion_handle *handle)
+void ion_handle_add(struct ion_client *client, struct ion_handle *handle)
 {
        struct rb_node **p = &client->handles.rb_node;
        struct rb_node *parent = NULL;
@@ -333,13 +268,22 @@ end:
 
 void ion_free(struct ion_client *client, struct ion_handle *handle)
 {
+       bool valid_handle;
+
+       BUG_ON(client != handle->client);
+
+       mutex_lock(&client->lock);
+       valid_handle = ion_handle_validate(client, handle);
+       mutex_unlock(&client->lock);
+
+       if (!valid_handle) {
+               WARN(1, "%s: invalid handle passed to free.\n", __func__);
+               return;
+       }
        ion_handle_put(handle);
 }
 
-static void ion_client_get(struct ion_client *client);
-static int ion_client_put(struct ion_client *client);
-
-bool _ion_map(int *buffer_cnt, int *handle_cnt)
+static bool _ion_map(int *buffer_cnt, int *handle_cnt)
 {
        bool map;
 
@@ -355,7 +299,7 @@ bool _ion_map(int *buffer_cnt, int *handle_cnt)
        return map;
 }
 
-bool _ion_unmap(int *buffer_cnt, int *handle_cnt)
+static bool _ion_unmap(int *buffer_cnt, int *handle_cnt)
 {
        BUG_ON(*handle_cnt == 0);
        (*handle_cnt)--;
@@ -383,8 +327,7 @@ int ion_phys(struct ion_client *client, struct ion_handle *handle,
        buffer = handle->buffer;
 
        if (!buffer->heap->ops->phys) {
-               pr_err("%s: ion_phys is not implemented by this heap.\n",
-                      __func__);
+               pr_err("ion_phys is not implemented by this heap.\n");
                mutex_unlock(&client->lock);
                return -ENODEV;
        }
@@ -400,8 +343,7 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
 
        mutex_lock(&client->lock);
        if (!ion_handle_validate(client, handle)) {
-               pr_err("%s: invalid handle passed to map_kernel.\n",
-                      __func__);
+               WARN(1, "invalid handle passed to map_kernel.\n");
                mutex_unlock(&client->lock);
                return ERR_PTR(-EINVAL);
        }
@@ -410,8 +352,7 @@ void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
        mutex_lock(&buffer->lock);
 
        if (!handle->buffer->heap->ops->map_kernel) {
-               pr_err("%s: map_kernel is not implemented by this heap.\n",
-                      __func__);
+               pr_err("map_kernel is not implemented by this heap.\n");
                mutex_unlock(&buffer->lock);
                mutex_unlock(&client->lock);
                return ERR_PTR(-ENODEV);
@@ -438,8 +379,7 @@ struct scatterlist *ion_map_dma(struct ion_client *client,
 
        mutex_lock(&client->lock);
        if (!ion_handle_validate(client, handle)) {
-               pr_err("%s: invalid handle passed to map_dma.\n",
-                      __func__);
+               WARN(1, "invalid handle passed to map_dma.\n");
                mutex_unlock(&client->lock);
                return ERR_PTR(-EINVAL);
        }
@@ -447,8 +387,7 @@ struct scatterlist *ion_map_dma(struct ion_client *client,
        mutex_lock(&buffer->lock);
 
        if (!handle->buffer->heap->ops->map_dma) {
-               pr_err("%s: map_kernel is not implemented by this heap.\n",
-                      __func__);
+               pr_err("map_kernel is not implemented by this heap.\n");
                mutex_unlock(&buffer->lock);
                mutex_unlock(&client->lock);
                return ERR_PTR(-ENODEV);
@@ -500,7 +439,17 @@ void ion_unmap_dma(struct ion_client *client, struct ion_handle *handle)
 struct ion_buffer *ion_share(struct ion_client *client,
                                 struct ion_handle *handle)
 {
-       /* don't not take an extra refernce here, the burden is on the caller
+       bool valid_handle;
+
+       mutex_lock(&client->lock);
+       valid_handle = ion_handle_validate(client, handle);
+       mutex_unlock(&client->lock);
+       if (!valid_handle) {
+               WARN(1, "%s: invalid handle passed to share.\n", __func__);
+               return ERR_PTR(-EINVAL);
+       }
+
+       /* do not take an extra reference here, the burden is on the caller
         * to make sure the buffer doesn't go away while it's passing it
         * to another client -- ion_free should not be called on this handle
         * until the buffer has been imported into the other client
@@ -521,8 +470,10 @@ struct ion_handle *ion_import(struct ion_client *client,
                goto end;
        }
        handle = ion_handle_create(client, buffer);
-       if (IS_ERR_OR_NULL(handle))
+       if (IS_ERR_OR_NULL(handle)) {
+               pr_err("error during handle create\n");
                goto end;
+       }
        ion_handle_add(client, handle);
 end:
        mutex_unlock(&client->lock);
@@ -537,12 +488,11 @@ struct ion_handle *ion_import_fd(struct ion_client *client, int fd)
        struct ion_handle *handle;
 
        if (!file) {
-               pr_err("%s: imported fd not found in file table.\n", __func__);
+               pr_err("imported fd not found in file table.\n");
                return ERR_PTR(-EINVAL);
        }
        if (file->f_op != &ion_share_fops) {
-               pr_err("%s: imported file is not a shared ion file.\n",
-                      __func__);
+               pr_err("imported file is not a shared ion file.\n");
                handle = ERR_PTR(-EINVAL);
                goto end;
        }
@@ -705,12 +655,13 @@ struct ion_client *ion_client_create(struct ion_device *dev,
        return client;
 }
 
-void ion_client_destroy(struct ion_client *client)
+static void _ion_client_destroy(struct kref *kref)
 {
+       struct ion_client *client = container_of(kref, struct ion_client, ref);
        struct ion_device *dev = client->dev;
        struct rb_node *n;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
+       pr_debug("\n");
        while ((n = rb_first(&client->handles))) {
                struct ion_handle *handle = rb_entry(n, struct ion_handle,
                                                     node);
@@ -729,27 +680,26 @@ void ion_client_destroy(struct ion_client *client)
        kfree(client);
 }
 
-static void _ion_client_destroy(struct kref *kref)
+void ion_client_get(struct ion_client *client)
 {
-       struct ion_client *client = container_of(kref, struct ion_client, ref);
-       ion_client_destroy(client);
+       kref_get(&client->ref);
 }
 
-static void ion_client_get(struct ion_client *client)
+int ion_client_put(struct ion_client *client)
 {
-       kref_get(&client->ref);
+       return kref_put(&client->ref, _ion_client_destroy);
 }
 
-static int ion_client_put(struct ion_client *client)
+void ion_client_destroy(struct ion_client *client)
 {
-       return kref_put(&client->ref, _ion_client_destroy);
+       ion_client_put(client);
 }
 
 static int ion_share_release(struct inode *inode, struct file* file)
 {
        struct ion_buffer *buffer = file->private_data;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
+       pr_debug("\n");
        /* drop the reference to the buffer -- this prevents the
           buffer from going away because the client holding it exited
           while it was being passed */
@@ -764,7 +714,7 @@ static void ion_vma_open(struct vm_area_struct *vma)
        struct ion_handle *handle = vma->vm_private_data;
        struct ion_client *client;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
+       pr_debug("\n");
        /* check that the client still exists and take a reference so
           it can't go away until this vma is closed */
        client = ion_client_lookup(buffer->dev, current->group_leader);
@@ -772,8 +722,9 @@ static void ion_vma_open(struct vm_area_struct *vma)
                vma->vm_private_data = NULL;
                return;
        }
-       pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
-                __func__, __LINE__,
+       ion_buffer_get(buffer);
+       ion_handle_get(handle);
+       pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
                 atomic_read(&client->ref.refcount),
                 atomic_read(&handle->ref.refcount),
                 atomic_read(&buffer->ref.refcount));
@@ -785,20 +736,19 @@ static void ion_vma_close(struct vm_area_struct *vma)
        struct ion_buffer *buffer = vma->vm_file->private_data;
        struct ion_client *client;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
+       pr_debug("\n");
        /* this indicates the client is gone, nothing to do here */
        if (!handle)
                return;
        client = handle->client;
-       pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
-                __func__, __LINE__,
+       pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
                 atomic_read(&client->ref.refcount),
                 atomic_read(&handle->ref.refcount),
                 atomic_read(&buffer->ref.refcount));
        ion_handle_put(handle);
        ion_client_put(client);
-       pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
-                __func__, __LINE__,
+       ion_buffer_put(buffer);
+       pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
                 atomic_read(&client->ref.refcount),
                 atomic_read(&handle->ref.refcount),
                 atomic_read(&buffer->ref.refcount));
@@ -817,21 +767,21 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
        struct ion_handle *handle;
        int ret;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
+       pr_debug("\n");
        /* make sure the client still exists, it's possible for the client to
           have gone away but the map/share fd still to be around, take
           a reference to it so it can't go away while this mapping exists */
        client = ion_client_lookup(buffer->dev, current->group_leader);
        if (IS_ERR_OR_NULL(client)) {
-               pr_err("%s: trying to mmap an ion handle in a process with no "
-                      "ion client\n", __func__);
+               WARN(1, "trying to mmap an ion handle in a process with no "
+                      "ion client\n");
                return -EINVAL;
        }
 
        if ((size > buffer->size) || (size + (vma->vm_pgoff << PAGE_SHIFT) >
                                     buffer->size)) {
-               pr_err("%s: trying to map larger area than handle has available"
-                      "\n", __func__);
+               WARN(1, "trying to map larger area than handle has available"
+                      "\n");
                ret = -EINVAL;
                goto err;
        }
@@ -842,10 +792,11 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
                ret = -EINVAL;
                goto err;
        }
+       ion_buffer_get(buffer);
 
        if (!handle->buffer->heap->ops->map_user) {
-               pr_err("%s: this heap does not define a method for mapping "
-                      "to userspace\n", __func__);
+               pr_err("this heap does not define a method for mapping "
+                      "to userspace\n");
                ret = -EINVAL;
                goto err1;
        }
@@ -855,8 +806,7 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
        ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
        mutex_unlock(&buffer->lock);
        if (ret) {
-               pr_err("%s: failure mapping buffer to userspace\n",
-                      __func__);
+               pr_err("failure mapping buffer to userspace\n");
                goto err1;
        }
 
@@ -864,8 +814,7 @@ static int ion_share_mmap(struct file *file, struct vm_area_struct *vma)
        /* move the handle into the vm_private_data so we can access it from
           vma_open/close */
        vma->vm_private_data = handle;
-       pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
-                __func__, __LINE__,
+       pr_debug("client_cnt %d handle_cnt %d alloc_cnt %d\n",
                 atomic_read(&client->ref.refcount),
                 atomic_read(&handle->ref.refcount),
                 atomic_read(&buffer->ref.refcount));
@@ -875,7 +824,7 @@ err1:
        /* drop the reference to the handle */
        ion_handle_put(handle);
 err:
-       /* drop the refernce to the client */
+       /* drop the reference to the client */
        ion_client_put(client);
        return ret;
 }
@@ -951,8 +900,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        return -EFAULT;
                mutex_lock(&client->lock);
                if (!ion_handle_validate(client, data.handle)) {
-                       pr_err("%s: invalid handle passed to share ioctl.\n",
-                              __func__);
+                       WARN(1, "invalid handle passed to share ioctl.\n");
                        mutex_unlock(&client->lock);
                        return -EINVAL;
                }
@@ -999,7 +947,7 @@ static int ion_release(struct inode *inode, struct file *file)
 {
        struct ion_client *client = file->private_data;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
+       pr_debug("\n");
        ion_client_put(client);
        return 0;
 }
@@ -1010,14 +958,10 @@ static int ion_open(struct inode *inode, struct file *file)
        struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
        struct ion_client *client;
 
-       pr_debug("%s: %d\n", __func__, __LINE__);
-       client = ion_client_lookup(dev, current->group_leader);
-       if (IS_ERR_OR_NULL(client)) {
-               /* XXX: consider replacing "user" with cmdline */
-               client = ion_client_create(dev, -1, "user");
-               if (IS_ERR_OR_NULL(client))
-                       return PTR_ERR(client);
-       }
+       pr_debug("\n");
+       client = ion_client_create(dev, -1, "user");
+       if (IS_ERR_OR_NULL(client))
+               return PTR_ERR(client);
        file->private_data = client;
 
        return 0;
@@ -1109,8 +1053,8 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
                } else if (heap->id > entry->id ) {
                        p = &(*p)->rb_right;
                } else {
-                       pr_err("%s: can not insert multiple heaps with "
-                               "id %d\n", __func__, heap->id);
+                       pr_err("can not insert multiple heaps with "
+                               "id %d\n", heap->id);
                        goto end;
                }
        }
@@ -1164,3 +1108,19 @@ void ion_device_destroy(struct ion_device *dev)
        /* XXX need to free the heaps and clients ? */
        kfree(dev);
 }
+
+struct ion_client *ion_client_get_file(int fd)
+{
+       struct ion_client *client = ERR_PTR(-EFAULT);
+       struct file *f = fget(fd);
+       if (!f)
+               return ERR_PTR(-EINVAL);
+
+       if (f->f_op == &ion_fops) {
+               client = f->private_data;
+               ion_client_get(client);
+       }
+
+       fput(f);
+       return client;
+}