From 9282a30e69520dc1fa21cd3c390e8eb4626635bc Mon Sep 17 00:00:00 2001
From: benjamin gaignard <benjamin.gaignard@linaro.org>
Date: Mon, 21 Nov 2011 15:11:50 +0100
Subject: [PATCH 1/2] add debug info to CMA
  use debugfs to dump CMA bitmap status

Signed-off-by: benjamin gaignard <benjamin.gaignard@linaro.org>

Conflicts:

	drivers/base/dma-contiguous.c
---
 drivers/base/dma-contiguous.c |   77 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 06ceab8..98c0a84 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -31,11 +31,18 @@
 #include <linux/swap.h>
 #include <linux/mm_types.h>
 #include <linux/dma-contiguous.h>
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#endif
+#include "dma-contiguous-trace.h"
 
 #ifndef SZ_1M
 #define SZ_1M (1 << 20)
 #endif
 
+static DEFINE_MUTEX(cma_mutex);
+
 struct cma {
 	unsigned long	base_pfn;
 	unsigned long	count;
@@ -68,6 +75,72 @@ struct cma *dma_contiguous_default_area;
  */
 static unsigned long size_bytes = CMA_SIZE_MBYTES * SZ_1M;
 static unsigned long size_percent = CMA_SIZE_PERCENTAGE;
+
+/* debugfs related functions */
+#ifdef CONFIG_DEBUG_FS
+/* when using debugfs_create_file private data field is set on inode
+ * copy data pointer to file private data */
+static int cma_debugfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t cma_debugfs_read(struct file *file, char __user *user_buf,
+			 size_t size, loff_t *ppos)
+{
+	struct cma *cma = file->private_data;
+	char *buf;
+	unsigned int len = 0, count = 0;
+	/* bitmap_scnprintf() produces one hex-digit per 4 bits of the
+	 * bitmap and one comma per every 8 hex-digits meaning par every
+	 * 32 bits, add 64 bytes for the additional characters
+	 */
+	unsigned int buffer_size = (cma->count/4) + (cma->count/32) + 64;
+	int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long);
+
+	buf = kmalloc(buffer_size, GFP_KERNEL);
+	if (!buf)
+		return 0;
+
+	len +=
+	    snprintf(buf + len, buffer_size - len,
+		     "CMA base 0x%08lx, count %lx\n", cma->base_pfn,
+		     cma->count);
+	len += snprintf(buf + len, buffer_size - len, "CMA bitmap : ");
+
+	mutex_lock(&cma_mutex);
+	len +=
+	    bitmap_scnprintf(buf + len, buffer_size - len, cma->bitmap,
+			     bitmap_size);
+	mutex_unlock(&cma_mutex);
+
+	len += snprintf(buf + len, buffer_size - len, "\n");
+
+	if (len > buffer_size)
+		len = buffer_size;
+
+	count = simple_read_from_buffer(user_buf, size, ppos, buf, len);
+	kfree(buf);
+
+	return count;
+}
+
+static const struct file_operations cma_debugfs_fops = {
+	.open = cma_debugfs_open,
+	.read = cma_debugfs_read,
+	.llseek = default_llseek,
+	.owner = THIS_MODULE,
+};
+
+static void cma_debugfs_create_file(struct cma *cma)
+{
+	debugfs_create_file("cma", S_IRUSR, NULL, cma, &cma_debugfs_fops);
+}
+#else
+static inline void cma_debugfs_create_file(struct cma *cma) { }
+#endif
+
 static long size_cmdline = -1;
 
 static int __init early_cma(char *p)
@@ -138,8 +211,6 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
 	dma_declare_contiguous(NULL, selected_size, 0, limit);
 };
 
-static DEFINE_MUTEX(cma_mutex);
-
 static int cma_activate_area(unsigned long base_pfn, unsigned long count)
 {
 	unsigned long pfn = base_pfn;
@@ -186,6 +257,8 @@ static struct cma *cma_create_area(unsigned long base_pfn,
 	if (ret)
 		goto error;
 
+	cma_debugfs_create_file(cma);
+
 	pr_debug("%s: returned %p\n", __func__, (void *)cma);
 	return cma;
 
-- 
1.7.0.4

