rk: ion: support last snapshot like last log
authorCMY <cmy@rock-chips.com>
Fri, 18 Apr 2014 10:18:29 +0000 (18:18 +0800)
committerCMY <cmy@rock-chips.com>
Fri, 18 Apr 2014 10:20:30 +0000 (18:20 +0800)
arch/arm/configs/rockchip_defconfig
drivers/staging/android/ion/Kconfig
drivers/staging/android/ion/ion.c
drivers/staging/android/ion/rockchip/Makefile
drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c [new file with mode: 0755]

index 2c67100fc12e7c731d2b0589aa42d07dd706056d..ae742757af69bcd46ef963cdf1ae38128f7fcd2b 100755 (executable)
@@ -501,6 +501,8 @@ CONFIG_SW_SYNC=y
 CONFIG_SW_SYNC_USER=y
 CONFIG_ION=y
 CONFIG_ION_ROCKCHIP=y
+CONFIG_ION_ROCKCHIP_SNAPSHOT=y
+CONFIG_ION_SNAPSHOT_BUF_SHIFT=18
 CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_IIO=y
 CONFIG_ROCKCHIP_ADC=y
index a8a23602e662cd828af6523baad70107f079ca2c..554ad411342e90ae3bddceea3ce5d457ac5a8f26 100644 (file)
@@ -38,3 +38,21 @@ config ION_ROCKCHIP
     depends on ARCH_ROCKCHIP && ION
     help
       Choose this option if you wish to use ion on an Rockchip.
+
+if ION_ROCKCHIP
+
+config ION_ROCKCHIP_SNAPSHOT
+    bool "Snapshot for rockchip ion"
+    depends on ION_ROCKCHIP
+    help
+         Provide ion snapshot for debug
+
+config ION_SNAPSHOT_BUF_SHIFT
+   int "ION snapshot buffer size (18 => 256KB, 19 => 512KB)"
+   depends on ION_ROCKCHIP_SNAPSHOT
+   range 12 21
+   default 18
+   help
+     Select ION snapshot buffer size as a power of 2
+
+endif
index 72d8b337696b62d67239762605148584de291033..0b7c5d785f27cd988b4db3ed6dc3760cc917a0d0 100755 (executable)
@@ -117,6 +117,8 @@ struct ion_handle {
 };
 
 static void ion_iommu_force_unmap(struct ion_buffer *buffer);
+extern char *rockchip_ion_snapshot_get(unsigned *size);
+extern int rockchip_ion_snapshot_debugfs(struct dentry* root);
 
 bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer)
 {
@@ -1969,6 +1971,10 @@ struct ion_device *ion_device_create(long (*custom_ioctl)
        if (!idev->clients_debug_root)
                pr_err("ion: failed to create debugfs clients directory.\n");
 
+#ifdef CONFIG_ION_ROCKCHIP_SNAPSHOT
+       rockchip_ion_snapshot_debugfs(idev->debug_root);
+#endif
+
 debugfs_done:
 
        idev->custom_ioctl = custom_ioctl;
@@ -2023,7 +2029,7 @@ void __init ion_reserve(struct ion_platform_data *data)
        }
 }
 
-#define ION_SNAPSHOT_BUFFER_LEN                1<<18
+#ifdef CONFIG_ION_ROCKCHIP_SNAPSHOT
 int ion_snapshot_save(struct ion_device *idev)
 {
        static struct seq_file seqf;
@@ -2031,18 +2037,14 @@ int ion_snapshot_save(struct ion_device *idev)
        struct rb_node *n;
 
        if (!seqf.buf) {
-               seqf.size = ION_SNAPSHOT_BUFFER_LEN;
-               seqf.buf = kmalloc(seqf.size, GFP_KERNEL);
+               seqf.buf = rockchip_ion_snapshot_get(&seqf.size);
                if (!seqf.buf)
                        return -ENOMEM;
-               printk("%s: create snapshot 0x%x@0x%lx\n", __func__, seqf.size,
-                       __pa(seqf.buf));
-       } else {
-               printk("%s: save snapshot 0x%x@0x%lx\n", __func__, seqf.size,
-                       __pa(seqf.buf));
-               memset(seqf.buf, 0, seqf.size);
-               seqf.count = 0;
        }
+       memset(seqf.buf, 0, seqf.size);
+       seqf.count = 0;
+       pr_info("%s: save snapshot 0x%x@0x%lx\n", __func__, seqf.size,
+               __pa(seqf.buf));
 
        down_read(&idev->lock);
 
@@ -2078,3 +2080,9 @@ int ion_snapshot_save(struct ion_device *idev)
 
        return 0;
 }
+#else
+int ion_snapshot_save(struct ion_device *idev)
+{
+       return 0;
+}
+#endif
index 5451bfd6551cec13013c2f8b87a1f50862709a2f..1871de8ce23ac822b545ce005f2bf79137ec997c 100644 (file)
@@ -1 +1,2 @@
 obj-y += rockchip_ion.o
+obj-$(CONFIG_ION_ROCKCHIP_SNAPSHOT) += rockchip_ion_snapshot.o
diff --git a/drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c b/drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c
new file mode 100755 (executable)
index 0000000..00a1d6c
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c
+ *
+ *  Copyright (C) 2011-2014 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "ion_snapshot: " fmt
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+
+#define LOG_BUF_LEN    (1 << CONFIG_ION_SNAPSHOT_BUF_SHIFT)
+#define LOG_BUF_PAGE_ORDER     (CONFIG_ION_SNAPSHOT_BUF_SHIFT - PAGE_SHIFT)
+// snapshot for last
+static char last_ion_buf[LOG_BUF_LEN];
+// snapshot for current
+static char* ion_snapshot_buf;
+
+static ssize_t last_ion_read(struct file *file, char __user *buf,
+                                   size_t len, loff_t *offset)
+{
+       loff_t pos = *offset;
+       ssize_t count;
+
+       if (pos >= LOG_BUF_LEN || last_ion_buf[0]==0)
+               return 0;
+
+       count = min(len, (size_t)(LOG_BUF_LEN - pos));
+       if (copy_to_user(buf, &last_ion_buf[pos], count))
+               return -EFAULT;
+
+       *offset += count;
+       return count;
+}
+
+static const struct file_operations last_ion_fops = {
+       .owner = THIS_MODULE,
+       .read = last_ion_read,
+};
+
+static ssize_t ion_snapshot_read(struct file *file, char __user *buf,
+                                   size_t len, loff_t *offset)
+{
+       loff_t pos = *offset;
+       ssize_t count;
+
+       if (pos >= LOG_BUF_LEN || ion_snapshot_buf[0]==0)
+               return 0;
+
+       count = min(len, (size_t)(LOG_BUF_LEN - pos));
+       if (copy_to_user(buf, &ion_snapshot_buf[pos], count))
+               return -EFAULT;
+
+       *offset += count;
+       return count;
+}
+
+static const struct file_operations ion_snapshot_fops = {
+       .owner = THIS_MODULE,
+       .read = ion_snapshot_read,
+};
+
+char *rockchip_ion_snapshot_get(unsigned *size)
+{
+       *size = LOG_BUF_LEN;
+       return ion_snapshot_buf;
+}
+
+int rockchip_ion_snapshot_debugfs(struct dentry* root)
+{
+       struct dentry* last_ion_dentry;
+       struct dentry* ion_snapshot_dentry;
+
+       last_ion_dentry = debugfs_create_file("last_ion", S_IRUSR,
+                                               root,
+                                               NULL, &last_ion_fops);
+       if (!last_ion_dentry) {
+               char buf[256], *path;
+               path = dentry_path(root, buf, 256);
+               pr_err("Failed to create client debugfs at %s/%s\n",
+                       path, "last_ion");
+       }
+
+       ion_snapshot_dentry = debugfs_create_file("ion_snapshot", S_IRUSR,
+                                               root,
+                                               NULL, &ion_snapshot_fops);
+       if (!ion_snapshot_dentry) {
+               char buf[256], *path;
+               path = dentry_path(root, buf, 256);
+               pr_err("Failed to create client debugfs at %s/%s\n",
+                       path, "ion_snapshot");
+       }
+
+       return 0;
+}
+
+static void * __init last_ion_vmap(phys_addr_t start, unsigned int page_count)
+{
+       struct page *pages[page_count + 1];
+       unsigned int i;
+
+       for (i = 0; i < page_count; i++) {
+               phys_addr_t addr = start + i * PAGE_SIZE;
+               pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
+       }
+       pages[page_count] = pfn_to_page(start >> PAGE_SHIFT);
+       return vmap(pages, page_count + 1, VM_MAP, pgprot_noncached(PAGE_KERNEL));
+}
+
+static int __init rockchip_ion_snapshot_init(void)
+{
+       char *log_buf;
+
+       log_buf = (char *)__get_free_pages(GFP_KERNEL, LOG_BUF_PAGE_ORDER);
+       if (!log_buf) {
+               pr_err("failed to __get_free_pages(%d)\n", LOG_BUF_PAGE_ORDER);
+               return 0;
+       }
+
+       ion_snapshot_buf = last_ion_vmap(virt_to_phys(log_buf), 1 << LOG_BUF_PAGE_ORDER);
+       if (!ion_snapshot_buf) {
+               pr_err("failed to map %d pages at 0x%08x\n", 1 << LOG_BUF_PAGE_ORDER, virt_to_phys(log_buf));
+               return 0;
+       }
+
+       pr_info("0x%08x map to 0x%p and copy to 0x%p (version 0.1)\n", 
+                       virt_to_phys(log_buf), ion_snapshot_buf, last_ion_buf);
+
+       memcpy(last_ion_buf, ion_snapshot_buf, LOG_BUF_LEN);
+       memset(ion_snapshot_buf, 0, LOG_BUF_LEN);
+
+       return 0;
+}
+
+postcore_initcall(rockchip_ion_snapshot_init);