From: CMY Date: Fri, 18 Apr 2014 10:18:29 +0000 (+0800) Subject: rk: ion: support last snapshot like last log X-Git-Tag: firefly_0821_release~5501 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b58fa64555c18913bba364b8faebff722ff5e95e;p=firefly-linux-kernel-4.4.55.git rk: ion: support last snapshot like last log --- diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 2c67100fc12e..ae742757af69 100755 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -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 diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index a8a23602e662..554ad411342e 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -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 diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 72d8b337696b..0b7c5d785f27 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -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 diff --git a/drivers/staging/android/ion/rockchip/Makefile b/drivers/staging/android/ion/rockchip/Makefile index 5451bfd6551c..1871de8ce23a 100644 --- a/drivers/staging/android/ion/rockchip/Makefile +++ b/drivers/staging/android/ion/rockchip/Makefile @@ -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 index 000000000000..00a1d6ccfea6 --- /dev/null +++ b/drivers/staging/android/ion/rockchip/rockchip_ion_snapshot.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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);