ion: dmabuf improve debugfs

Improvements made to ION to add an additional debugfs file
to display allocation/reference information for all ION buffers.

rb tree was deleted becaused of unused, add it back to track
ion buffer alloc.

Migrated from (CR):
https://gerrit.mot.com/#/c/1535657/
https://gerrit.mot.com/#/c/1535658/

Change-Id: I1e42d3dac61d4fc856ba8d749cfd2123e40529d9
Signed-off-by: liuwang2 <liuwang2@lenovo.com>
Reviewed-on: https://gerrit.mot.com/1811670
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Zhilong Wang <wangzl30@motorola.com>
Reviewed-by: Ji Zhao <zhaoji1@lenovo.com>
Reviewed-by: Bolei Shang <shangbl1@lenovo.com>
Reviewed-by: Zilong Zhang <zhangzl7@lenovo.com>
Reviewed-by: Dawei Wang <wangdw10@motorola.com>
Reviewed-by: Zhenxin Xi <xizx@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
liuwang2 2020-11-26 11:09:23 +08:00 • committed by Xiaojun Ji
commit 5b298f511c
8 changed files with 147 additions and 1 deletions

View file

@ -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);

View file

@ -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:

View file

@ -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);

View file

@ -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,

View file

@ -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 */

View file

@ -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 *);
};
/**

View file

@ -20,8 +20,11 @@
#include <linux/types.h>
#include <uapi/linux/ion.h>
#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;
};
/**

View file

@ -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.