aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 10:44:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 10:44:37 -0400
commitb0ca4d0123608cfec73fc689c74295da89fc934e (patch)
tree4d79f2b9c3277501637e0dcd6c541416091e4308
parentd70b1e06eb331afe1576ac23bb9523708026ba1f (diff)
parentb89e35636bc75b72d15a1af6d49798802aff77d5 (diff)
Merge tag 'tag-for-linus-3.10' of git://git.linaro.org/people/sumitsemwal/linux-dma-buf
Pull dma-buf updates from Sumit Semwal: "Added debugfs support to dma-buf" * tag 'tag-for-linus-3.10' of git://git.linaro.org/people/sumitsemwal/linux-dma-buf: dma-buf: Add debugfs support dma-buf: replace dma_buf_export() with dma_buf_export_named()
-rw-r--r--Documentation/dma-buf-sharing.txt13
-rw-r--r--drivers/base/dma-buf.c169
-rw-r--r--include/linux/dma-buf.h16
3 files changed, 189 insertions, 9 deletions
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt
index 4966b1be42ac..0b23261561d2 100644
--- a/Documentation/dma-buf-sharing.txt
+++ b/Documentation/dma-buf-sharing.txt
@@ -52,14 +52,23 @@ The dma_buf buffer sharing API usage contains the following steps:
52 associated with this buffer. 52 associated with this buffer.
53 53
54 Interface: 54 Interface:
55 struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops, 55 struct dma_buf *dma_buf_export_named(void *priv, struct dma_buf_ops *ops,
56 size_t size, int flags) 56 size_t size, int flags,
57 const char *exp_name)
57 58
58 If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a 59 If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a
59 pointer to the same. It also associates an anonymous file with this buffer, 60 pointer to the same. It also associates an anonymous file with this buffer,
60 so it can be exported. On failure to allocate the dma_buf object, it returns 61 so it can be exported. On failure to allocate the dma_buf object, it returns
61 NULL. 62 NULL.
62 63
64 'exp_name' is the name of exporter - to facilitate information while
65 debugging.
66
67 Exporting modules which do not wish to provide any specific name may use the
68 helper define 'dma_buf_export()', with the same arguments as above, but
69 without the last argument; a __FILE__ pre-processor directive will be
70 inserted in place of 'exp_name' instead.
71
632. Userspace gets a handle to pass around to potential buffer-users 722. Userspace gets a handle to pass around to potential buffer-users
64 73
65 Userspace entity requests for a file-descriptor (fd) which is a handle to the 74 Userspace entity requests for a file-descriptor (fd) which is a handle to the
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index 2a7cb0df176b..08fe897c0b4c 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -27,9 +27,18 @@
27#include <linux/dma-buf.h> 27#include <linux/dma-buf.h>
28#include <linux/anon_inodes.h> 28#include <linux/anon_inodes.h>
29#include <linux/export.h> 29#include <linux/export.h>
30#include <linux/debugfs.h>
31#include <linux/seq_file.h>
30 32
31static inline int is_dma_buf_file(struct file *); 33static inline int is_dma_buf_file(struct file *);
32 34
35struct dma_buf_list {
36 struct list_head head;
37 struct mutex lock;
38};
39
40static struct dma_buf_list db_list;
41
33static int dma_buf_release(struct inode *inode, struct file *file) 42static int dma_buf_release(struct inode *inode, struct file *file)
34{ 43{
35 struct dma_buf *dmabuf; 44 struct dma_buf *dmabuf;
@@ -42,6 +51,11 @@ static int dma_buf_release(struct inode *inode, struct file *file)
42 BUG_ON(dmabuf->vmapping_counter); 51 BUG_ON(dmabuf->vmapping_counter);
43 52
44 dmabuf->ops->release(dmabuf); 53 dmabuf->ops->release(dmabuf);
54
55 mutex_lock(&db_list.lock);
56 list_del(&dmabuf->list_node);
57 mutex_unlock(&db_list.lock);
58
45 kfree(dmabuf); 59 kfree(dmabuf);
46 return 0; 60 return 0;
47} 61}
@@ -77,22 +91,24 @@ static inline int is_dma_buf_file(struct file *file)
77} 91}
78 92
79/** 93/**
80 * dma_buf_export - Creates a new dma_buf, and associates an anon file 94 * dma_buf_export_named - Creates a new dma_buf, and associates an anon file
81 * with this buffer, so it can be exported. 95 * with this buffer, so it can be exported.
82 * Also connect the allocator specific data and ops to the buffer. 96 * Also connect the allocator specific data and ops to the buffer.
97 * Additionally, provide a name string for exporter; useful in debugging.
83 * 98 *
84 * @priv: [in] Attach private data of allocator to this buffer 99 * @priv: [in] Attach private data of allocator to this buffer
85 * @ops: [in] Attach allocator-defined dma buf ops to the new buffer. 100 * @ops: [in] Attach allocator-defined dma buf ops to the new buffer.
86 * @size: [in] Size of the buffer 101 * @size: [in] Size of the buffer
87 * @flags: [in] mode flags for the file. 102 * @flags: [in] mode flags for the file.
103 * @exp_name: [in] name of the exporting module - useful for debugging.
88 * 104 *
89 * Returns, on success, a newly created dma_buf object, which wraps the 105 * Returns, on success, a newly created dma_buf object, which wraps the
90 * supplied private data and operations for dma_buf_ops. On either missing 106 * supplied private data and operations for dma_buf_ops. On either missing
91 * ops, or error in allocating struct dma_buf, will return negative error. 107 * ops, or error in allocating struct dma_buf, will return negative error.
92 * 108 *
93 */ 109 */
94struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops, 110struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
95 size_t size, int flags) 111 size_t size, int flags, const char *exp_name)
96{ 112{
97 struct dma_buf *dmabuf; 113 struct dma_buf *dmabuf;
98 struct file *file; 114 struct file *file;
@@ -114,6 +130,7 @@ struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
114 dmabuf->priv = priv; 130 dmabuf->priv = priv;
115 dmabuf->ops = ops; 131 dmabuf->ops = ops;
116 dmabuf->size = size; 132 dmabuf->size = size;
133 dmabuf->exp_name = exp_name;
117 134
118 file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags); 135 file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
119 136
@@ -122,9 +139,13 @@ struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
122 mutex_init(&dmabuf->lock); 139 mutex_init(&dmabuf->lock);
123 INIT_LIST_HEAD(&dmabuf->attachments); 140 INIT_LIST_HEAD(&dmabuf->attachments);
124 141
142 mutex_lock(&db_list.lock);
143 list_add(&dmabuf->list_node, &db_list.head);
144 mutex_unlock(&db_list.lock);
145
125 return dmabuf; 146 return dmabuf;
126} 147}
127EXPORT_SYMBOL_GPL(dma_buf_export); 148EXPORT_SYMBOL_GPL(dma_buf_export_named);
128 149
129 150
130/** 151/**
@@ -548,3 +569,143 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
548 mutex_unlock(&dmabuf->lock); 569 mutex_unlock(&dmabuf->lock);
549} 570}
550EXPORT_SYMBOL_GPL(dma_buf_vunmap); 571EXPORT_SYMBOL_GPL(dma_buf_vunmap);
572
573#ifdef CONFIG_DEBUG_FS
574static int dma_buf_describe(struct seq_file *s)
575{
576 int ret;
577 struct dma_buf *buf_obj;
578 struct dma_buf_attachment *attach_obj;
579 int count = 0, attach_count;
580 size_t size = 0;
581
582 ret = mutex_lock_interruptible(&db_list.lock);
583
584 if (ret)
585 return ret;
586
587 seq_printf(s, "\nDma-buf Objects:\n");
588 seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n");
589
590 list_for_each_entry(buf_obj, &db_list.head, list_node) {
591 ret = mutex_lock_interruptible(&buf_obj->lock);
592
593 if (ret) {
594 seq_printf(s,
595 "\tERROR locking buffer object: skipping\n");
596 continue;
597 }
598
599 seq_printf(s, "\t");
600
601 seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n",
602 buf_obj->exp_name, buf_obj->size,
603 buf_obj->file->f_flags, buf_obj->file->f_mode,
604 (long)(buf_obj->file->f_count.counter));
605
606 seq_printf(s, "\t\tAttached Devices:\n");
607 attach_count = 0;
608
609 list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
610 seq_printf(s, "\t\t");
611
612 seq_printf(s, "%s\n", attach_obj->dev->init_name);
613 attach_count++;
614 }
615
616 seq_printf(s, "\n\t\tTotal %d devices attached\n",
617 attach_count);
618
619 count++;
620 size += buf_obj->size;
621 mutex_unlock(&buf_obj->lock);
622 }
623
624 seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
625
626 mutex_unlock(&db_list.lock);
627 return 0;
628}
629
630static int dma_buf_show(struct seq_file *s, void *unused)
631{
632 void (*func)(struct seq_file *) = s->private;
633 func(s);
634 return 0;
635}
636
637static int dma_buf_debug_open(struct inode *inode, struct file *file)
638{
639 return single_open(file, dma_buf_show, inode->i_private);
640}
641
642static const struct file_operations dma_buf_debug_fops = {
643 .open = dma_buf_debug_open,
644 .read = seq_read,
645 .llseek = seq_lseek,
646 .release = single_release,
647};
648
649static struct dentry *dma_buf_debugfs_dir;
650
651static int dma_buf_init_debugfs(void)
652{
653 int err = 0;
654 dma_buf_debugfs_dir = debugfs_create_dir("dma_buf", NULL);
655 if (IS_ERR(dma_buf_debugfs_dir)) {
656 err = PTR_ERR(dma_buf_debugfs_dir);
657 dma_buf_debugfs_dir = NULL;
658 return err;
659 }
660
661 err = dma_buf_debugfs_create_file("bufinfo", dma_buf_describe);
662
663 if (err)
664 pr_debug("dma_buf: debugfs: failed to create node bufinfo\n");
665
666 return err;
667}
668
669static void dma_buf_uninit_debugfs(void)
670{
671 if (dma_buf_debugfs_dir)
672 debugfs_remove_recursive(dma_buf_debugfs_dir);
673}
674
675int dma_buf_debugfs_create_file(const char *name,
676 int (*write)(struct seq_file *))
677{
678 struct dentry *d;
679
680 d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir,
681 write, &dma_buf_debug_fops);
682
683 if (IS_ERR(d))
684 return PTR_ERR(d);
685
686 return 0;
687}
688#else
689static inline int dma_buf_init_debugfs(void)
690{
691 return 0;
692}
693static inline void dma_buf_uninit_debugfs(void)
694{
695}
696#endif
697
698static int __init dma_buf_init(void)
699{
700 mutex_init(&db_list.lock);
701 INIT_LIST_HEAD(&db_list.head);
702 dma_buf_init_debugfs();
703 return 0;
704}
705subsys_initcall(dma_buf_init);
706
707static void __exit dma_buf_deinit(void)
708{
709 dma_buf_uninit_debugfs();
710}
711__exitcall(dma_buf_deinit);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 9978b614a1aa..dfac5ed31120 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -112,6 +112,8 @@ struct dma_buf_ops {
112 * @file: file pointer used for sharing buffers across, and for refcounting. 112 * @file: file pointer used for sharing buffers across, and for refcounting.
113 * @attachments: list of dma_buf_attachment that denotes all devices attached. 113 * @attachments: list of dma_buf_attachment that denotes all devices attached.
114 * @ops: dma_buf_ops associated with this buffer object. 114 * @ops: dma_buf_ops associated with this buffer object.
115 * @exp_name: name of the exporter; useful for debugging.
116 * @list_node: node for dma_buf accounting and debugging.
115 * @priv: exporter specific private data for this buffer object. 117 * @priv: exporter specific private data for this buffer object.
116 */ 118 */
117struct dma_buf { 119struct dma_buf {
@@ -123,6 +125,8 @@ struct dma_buf {
123 struct mutex lock; 125 struct mutex lock;
124 unsigned vmapping_counter; 126 unsigned vmapping_counter;
125 void *vmap_ptr; 127 void *vmap_ptr;
128 const char *exp_name;
129 struct list_head list_node;
126 void *priv; 130 void *priv;
127}; 131};
128 132
@@ -162,8 +166,13 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
162 struct device *dev); 166 struct device *dev);
163void dma_buf_detach(struct dma_buf *dmabuf, 167void dma_buf_detach(struct dma_buf *dmabuf,
164 struct dma_buf_attachment *dmabuf_attach); 168 struct dma_buf_attachment *dmabuf_attach);
165struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops, 169
166 size_t size, int flags); 170struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
171 size_t size, int flags, const char *);
172
173#define dma_buf_export(priv, ops, size, flags) \
174 dma_buf_export_named(priv, ops, size, flags, __FILE__)
175
167int dma_buf_fd(struct dma_buf *dmabuf, int flags); 176int dma_buf_fd(struct dma_buf *dmabuf, int flags);
168struct dma_buf *dma_buf_get(int fd); 177struct dma_buf *dma_buf_get(int fd);
169void dma_buf_put(struct dma_buf *dmabuf); 178void dma_buf_put(struct dma_buf *dmabuf);
@@ -185,5 +194,6 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
185 unsigned long); 194 unsigned long);
186void *dma_buf_vmap(struct dma_buf *); 195void *dma_buf_vmap(struct dma_buf *);
187void dma_buf_vunmap(struct dma_buf *, void *vaddr); 196void dma_buf_vunmap(struct dma_buf *, void *vaddr);
188 197int dma_buf_debugfs_create_file(const char *name,
198 int (*write)(struct seq_file *));
189#endif /* __DMA_BUF_H__ */ 199#endif /* __DMA_BUF_H__ */