aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2013-05-15 00:09:49 -0400
committerMarek Szyprowski <m.szyprowski@samsung.com>2013-06-28 09:14:28 -0400
commit63c181922f25371b7d24ef63d4e15887ff23a088 (patch)
tree7a33e5ac0d608e0af6de72f4462b1f30c38a337a
parent9e4b259d4fbf8a9c822117e734356e94b7f30927 (diff)
ARM: DMA-mapping: mark all !DMA_TO_DEVICE pages in unmapping as clean
It is common for one sg to include many pages, so mark all these pages as clean to avoid unnecessary flushing on them in set_pte_at() or update_mmu_cache(). The patch might improve loading performance of applciation code a bit. On the below test code to read file(~1GByte size) from usb mass storage disk to buffer created with mmap(PROT_READ | PROT_EXEC) on Pandaboard, average ~1% improvement can be observed with the patch on 10 times test. unsigned int sum = 0; static unsigned long tv_diff(struct timeval *tv1, struct timeval *tv2) { return (tv2->tv_sec - tv1->tv_sec) * 1000000 + (tv2->tv_usec - tv1->tv_usec); } int main(int argc, char *argv[]) { char *mbuffer; int fd; int i; unsigned long page_size, size; struct stat stat; struct timeval t1, t2; page_size = getpagesize(); fd = open(argv[1], O_RDONLY); assert(fd >= 0); fstat(fd, &stat); size = stat.st_size; printf("%s: file %s, file size %lu, page size %lu\n", argv[0], read_filename, size, page_size); gettimeofday(&t1, NULL); mbuffer = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); for (i = 0 ; i < size ; i += page_size) sum += mbuffer[i]; munmap(mbuffer, page_size); gettimeofday(&t2, NULL); printf("\tread mmaped time: %luus\n", tv_diff(&t1, &t2)); close(fd); } Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
-rw-r--r--arch/arm/mm/dma-mapping.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 26a5833c9f29..97926b1277b2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -880,10 +880,24 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
880 dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); 880 dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
881 881
882 /* 882 /*
883 * Mark the D-cache clean for this page to avoid extra flushing. 883 * Mark the D-cache clean for these pages to avoid extra flushing.
884 */ 884 */
885 if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE) 885 if (dir != DMA_TO_DEVICE && size >= PAGE_SIZE) {
886 set_bit(PG_dcache_clean, &page->flags); 886 unsigned long pfn;
887 size_t left = size;
888
889 pfn = page_to_pfn(page) + off / PAGE_SIZE;
890 off %= PAGE_SIZE;
891 if (off) {
892 pfn++;
893 left -= PAGE_SIZE - off;
894 }
895 while (left >= PAGE_SIZE) {
896 page = pfn_to_page(pfn++);
897 set_bit(PG_dcache_clean, &page->flags);
898 left -= PAGE_SIZE;
899 }
900 }
887} 901}
888 902
889/** 903/**