xref: /OK3568_Linux_fs/kernel/drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *  drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c
3  *
4  *  Copyright (C) 2011-2014 ROCKCHIP, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #define pr_fmt(fmt) "ion_snapshot: " fmt
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/mm.h>
15 #include <linux/module.h>
16 #include <linux/vmalloc.h>
17 #include <linux/uaccess.h>
18 #include <linux/debugfs.h>
19 
20 #define LOG_BUF_LEN	(1 << CONFIG_ION_SNAPSHOT_BUF_SHIFT)
21 #define LOG_BUF_PAGE_ORDER	(CONFIG_ION_SNAPSHOT_BUF_SHIFT - PAGE_SHIFT)
22 // snapshot for last
23 static char last_ion_buf[LOG_BUF_LEN];
24 // snapshot for current
25 static char* ion_snapshot_buf;
26 
last_ion_read(struct file * file,char __user * buf,size_t len,loff_t * offset)27 static ssize_t last_ion_read(struct file *file, char __user *buf,
28 				    size_t len, loff_t *offset)
29 {
30 	loff_t pos = *offset;
31 	ssize_t count;
32 
33 	if (pos >= LOG_BUF_LEN || last_ion_buf[0]==0)
34 		return 0;
35 
36 	count = min(len, (size_t)(LOG_BUF_LEN - pos));
37 	if (copy_to_user(buf, &last_ion_buf[pos], count))
38 		return -EFAULT;
39 
40 	*offset += count;
41 	return count;
42 }
43 
44 static const struct file_operations last_ion_fops = {
45 	.owner = THIS_MODULE,
46 	.read = last_ion_read,
47 };
48 
ion_snapshot_read(struct file * file,char __user * buf,size_t len,loff_t * offset)49 static ssize_t ion_snapshot_read(struct file *file, char __user *buf,
50 				    size_t len, loff_t *offset)
51 {
52 	loff_t pos = *offset;
53 	ssize_t count;
54 
55 	if (pos >= LOG_BUF_LEN || ion_snapshot_buf[0]==0)
56 		return 0;
57 
58 	count = min(len, (size_t)(LOG_BUF_LEN - pos));
59 	if (copy_to_user(buf, &ion_snapshot_buf[pos], count))
60 		return -EFAULT;
61 
62 	*offset += count;
63 	return count;
64 }
65 
66 static const struct file_operations ion_snapshot_fops = {
67 	.owner = THIS_MODULE,
68 	.read = ion_snapshot_read,
69 };
70 
rockchip_ion_snapshot_get(size_t * size)71 char *rockchip_ion_snapshot_get(size_t *size)
72 {
73 	*size = LOG_BUF_LEN;
74 	return ion_snapshot_buf;
75 }
76 
rockchip_ion_snapshot_debugfs(struct dentry * root)77 int rockchip_ion_snapshot_debugfs(struct dentry* root)
78 {
79 	struct dentry* last_ion_dentry;
80 	struct dentry* ion_snapshot_dentry;
81 
82 	last_ion_dentry = debugfs_create_file("last_ion", 0664,
83 						root,
84 						NULL, &last_ion_fops);
85 	if (!last_ion_dentry) {
86 		char buf[256], *path;
87 		path = dentry_path(root, buf, 256);
88 		pr_err("Failed to create client debugfs at %s/%s\n",
89 			path, "last_ion");
90 	}
91 
92 	ion_snapshot_dentry = debugfs_create_file("ion_snapshot", 0664,
93 						root,
94 						NULL, &ion_snapshot_fops);
95 	if (!ion_snapshot_dentry) {
96 		char buf[256], *path;
97 		path = dentry_path(root, buf, 256);
98 		pr_err("Failed to create client debugfs at %s/%s\n",
99 			path, "ion_snapshot");
100 	}
101 
102 	return 0;
103 }
104 
last_ion_vmap(phys_addr_t start,unsigned int page_count)105 static void * __init last_ion_vmap(phys_addr_t start, unsigned int page_count)
106 {
107 	struct page *pages[page_count + 1];
108 	unsigned int i;
109 
110 	for (i = 0; i < page_count; i++) {
111 		phys_addr_t addr = start + i * PAGE_SIZE;
112 		pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
113 	}
114 	pages[page_count] = pfn_to_page(start >> PAGE_SHIFT);
115 	return vmap(pages, page_count + 1, VM_MAP, pgprot_writecombine(PAGE_KERNEL));
116 }
117 
rockchip_ion_snapshot_init(void)118 static int __init rockchip_ion_snapshot_init(void)
119 {
120 	char *log_buf;
121 
122 	log_buf = (char *)__get_free_pages(GFP_KERNEL, LOG_BUF_PAGE_ORDER);
123 	if (!log_buf) {
124 		pr_err("failed to __get_free_pages(%d)\n", LOG_BUF_PAGE_ORDER);
125 		return 0;
126 	}
127 
128 	ion_snapshot_buf = last_ion_vmap(virt_to_phys(log_buf), 1 << LOG_BUF_PAGE_ORDER);
129 	if (!ion_snapshot_buf) {
130 		pr_err("failed to map %d pages at 0x%lx\n", 1 << LOG_BUF_PAGE_ORDER,
131 			(unsigned long)virt_to_phys(log_buf));
132 		return 0;
133 	}
134 
135 	pr_info("0x%lx map to 0x%p and copy to 0x%p (version 0.1)\n",
136 			(unsigned long)virt_to_phys(log_buf), ion_snapshot_buf,
137 			last_ion_buf);
138 
139 	memcpy(last_ion_buf, ion_snapshot_buf, LOG_BUF_LEN);
140 	memset(ion_snapshot_buf, 0, LOG_BUF_LEN);
141 
142 	return 0;
143 }
144 
145 postcore_initcall(rockchip_ion_snapshot_init);
146