mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-14 09:30:40 +09:00
rk: ion: support last snapshot like last log
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
obj-y += rockchip_ion.o
|
||||
obj-$(CONFIG_ION_ROCKCHIP_SNAPSHOT) += rockchip_ion_snapshot.o
|
||||
|
||||
143
drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c
Executable file
143
drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c
Executable file
@@ -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);
|
||||
Reference in New Issue
Block a user