diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index d60b7ced21cb..1630f66dc6d4 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -434,6 +434,10 @@ static long dma_buf_ioctl(struct file *file, return ret; + case DMA_BUF_IOCTL_IMPORT_BUF_ADD_BY_MOTO: + dmabuf->ops->import_buf_add_by_moto(dmabuf); + return 0; + case DMA_BUF_SET_NAME_A: case DMA_BUF_SET_NAME_B: return dma_buf_set_name(dmabuf, (const char __user *)arg); diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 61d2a8cbf894..d86e54f1f912 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -481,6 +481,54 @@ static int ion_init_sysfs(void) return 0; } +static int ion_debug_allbufs_show(struct seq_file *s, void *unused) +{ + struct ion_device *dev = s->private; + struct rb_node *n; + int i; + unsigned long total_len = 0; + + seq_printf(s, "%16.s %16.s %12.s %12.s %20.s %s\n", "heap", + "buffer", "size", "ref cnt", "allocator", "references"); + + down_read(&dev->lock); + mutex_lock(&dev->buffer_lock); + for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { + struct ion_buffer *buf = rb_entry(n, struct ion_buffer, node); + int buf_refcount = buf->ref_cnt; + total_len += buf->size; + seq_printf(s, "%16.s %16pK %12.x %12.d %20.d %s", + buf->heap->name, buf, (int)buf->size, + buf_refcount, buf->pid, ""); + + for(i = 0; i < buf->ref_cnt && i < MAX_CLIENTS_NUM; i++) + seq_printf(s, "%u, ", buf->client_pids[i]); + + seq_puts(s, "\n"); + } + + if (s->file && s->file->f_path.dentry + && !strcmp(s->file->f_path.dentry->d_iname, "check_all_bufs_total")) + seq_printf(s, "%16.s %s is: %lld(%lld KB)\n", + "heap", "total size", total_len, total_len/1024); + + mutex_unlock(&dev->buffer_lock); + up_read(&dev->lock); + return 0; +} + +static int ion_debug_allbufs_open(struct inode *inode, struct file *file) +{ + return single_open(file, ion_debug_allbufs_show, inode->i_private); +} + +static const struct file_operations debug_allbufs_fops = { + .open = ion_debug_allbufs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int ion_device_create(void) { struct ion_device *idev; @@ -506,10 +554,18 @@ static int ion_device_create(void) goto err_sysfs; } + idev->buffers = RB_ROOT; + mutex_init(&idev->buffer_lock); idev->debug_root = debugfs_create_dir("ion", NULL); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); internal_dev = idev; + + debugfs_create_file("check_all_bufs", 0664, idev->debug_root, idev, + &debug_allbufs_fops); + debugfs_create_file("check_all_bufs_total", 0664, idev->debug_root, idev, + &debug_allbufs_fops); + return 0; err_sysfs: diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c index eb0e4d285a57..e63944935b6b 100644 --- a/drivers/staging/android/ion/ion_buffer.c +++ b/drivers/staging/android/ion/ion_buffer.c @@ -31,6 +31,31 @@ static void track_buffer_destroyed(struct ion_buffer *buffer) trace_ion_stat(buffer->sg_table, -buffer->size, total); } +/* this function should only be called while dev->buffer_lock is held */ +static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) +{ + struct rb_node **p = &dev->buffers.rb_node; + struct rb_node *parent = NULL; + struct ion_buffer *entry; + + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_buffer, node); + + if (buffer < entry) { + p = &(*p)->rb_left; + } else if (buffer > entry) { + p = &(*p)->rb_right; + } else { + pr_err("%s: buffer already found.", __func__); + BUG(); + } + } + + rb_link_node(&buffer->node, parent, p); + rb_insert_color(&buffer->node, &dev->buffers); +} + /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -84,6 +109,14 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); track_buffer_created(buffer); + + mutex_lock(&dev->buffer_lock); + ion_buffer_add(dev, buffer); + mutex_unlock(&dev->buffer_lock); + + buffer->pid = task_pid_nr(current->group_leader); + buffer->client_pids[buffer->ref_cnt++] = buffer->pid; + return buffer; err1: @@ -240,6 +273,10 @@ int ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) return -EINVAL; } + mutex_lock(&dev->buffer_lock); + rb_erase(&buffer->node, &dev->buffers); + mutex_unlock(&dev->buffer_lock); + heap = buffer->heap; track_buffer_destroyed(buffer); diff --git a/drivers/staging/android/ion/ion_dma_buf.c b/drivers/staging/android/ion/ion_dma_buf.c index b7295fee31c7..dd9189228113 100644 --- a/drivers/staging/android/ion/ion_dma_buf.c +++ b/drivers/staging/android/ion/ion_dma_buf.c @@ -259,6 +259,28 @@ static void *ion_dma_buf_map(struct dma_buf *dmabuf, unsigned long offset) return ion_buffer_kmap_get(buffer) + offset * PAGE_SIZE; } +static int ion_dma_buf_import_buf_add_by_moto(struct dma_buf *dmabuf) +{ + struct ion_buffer *buffer = dmabuf->priv; + int i; + int found_pid = 0; + pid_t task_pid = task_pid_nr(current->group_leader); + + mutex_lock(&buffer->lock); + for (i = 0; i < buffer->ref_cnt && i < MAX_CLIENTS_NUM; i++) { + if (buffer->client_pids[i] == task_pid) { + found_pid = 1; + break; + } + } + if (!found_pid && buffer->ref_cnt < MAX_CLIENTS_NUM) + buffer->client_pids[buffer->ref_cnt++] = task_pid; + + mutex_unlock(&buffer->lock); + + return 0; +} + static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { struct ion_buffer *buffer = dmabuf->priv; @@ -278,6 +300,8 @@ static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) mutex_unlock(&buffer->lock); } + ion_dma_buf_import_buf_add_by_moto(dmabuf); + if (ret) pr_err("%s: failure mapping buffer to userspace\n", __func__); @@ -353,6 +377,7 @@ static const struct dma_buf_ops dma_buf_ops = { .vmap = ion_dma_buf_vmap, .vunmap = ion_dma_buf_vunmap, .get_flags = ion_dma_buf_get_flags, + .import_buf_add_by_moto = ion_dma_buf_import_buf_add_by_moto, }; struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h index db4e90683f4c..0ff6d5ccfa55 100644 --- a/drivers/staging/android/ion/ion_private.h +++ b/drivers/staging/android/ion/ion_private.h @@ -20,6 +20,8 @@ /** * struct ion_device - the metadata of the ion device node + * @buffers: an rb tree of all the existing buffers + * @buffer_lock: lock protecting the tree of buffers * @dev: the actual misc device * @lock: rwsem protecting the tree of heaps, heap_bitmap and * clients @@ -32,6 +34,8 @@ struct ion_device { struct plist_head heaps; struct dentry *debug_root; int heap_cnt; + struct rb_root buffers; + struct mutex buffer_lock; }; /* ion_buffer manipulators */ diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index accce2b534e7..db780978805a 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -348,6 +348,16 @@ struct dma_buf_ops { * will be populated with the buffer's flags. */ int (*get_flags)(struct dma_buf *dmabuf, unsigned long *flags); + + /** + * @import_buf_add_by_moto: + * + * This is called by gr_ion_alloc added by Motorola + * + * Returns: + * always return 0 + */ + int (*import_buf_add_by_moto)(struct dma_buf *); }; /** diff --git a/include/linux/ion.h b/include/linux/ion.h index 80c6fdeb4822..ce9c9692d22f 100644 --- a/include/linux/ion.h +++ b/include/linux/ion.h @@ -20,8 +20,11 @@ #include #include +#define MAX_CLIENTS_NUM 16 + /** * struct ion_buffer - metadata for a particular buffer + * @node: node in the ion_device buffers tree * @list: element in list of deferred freeable buffers * @heap: back pointer to the heap the buffer came from * @flags: buffer specific flags @@ -36,7 +39,10 @@ * @attachments: list of devices attached to this buffer */ struct ion_buffer { - struct list_head list; + union { + struct rb_node node; + struct list_head list; + }; struct ion_heap *heap; unsigned long flags; unsigned long private_flags; @@ -47,6 +53,9 @@ struct ion_buffer { void *vaddr; struct sg_table *sg_table; struct list_head attachments; + pid_t pid; + pid_t client_pids[MAX_CLIENTS_NUM]; + int ref_cnt; }; /** diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h index f76d11725c6c..83e118dd84f3 100644 --- a/include/uapi/linux/dma-buf.h +++ b/include/uapi/linux/dma-buf.h @@ -39,6 +39,7 @@ struct dma_buf_sync { #define DMA_BUF_BASE 'b' #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) +#define DMA_BUF_IOCTL_IMPORT_BUF_ADD_BY_MOTO _IO(DMA_BUF_BASE, 0xCC) /* 32/64bitness of this uapi was botched in android, there's no difference * between them in actual uapi, they're just different numbers.