video: tegra: nvmap: implement full L2 clean/flush
Kirill Artamonov [Tue, 12 Jun 2012 16:00:58 +0000 (19:00 +0300)]
When allocation is bigger than L2 size it is more optimal to
flush or writeback whole L2 instead of doing maintenance
for each allocated page.

bug 983964

Signed-off-by: Kirill Artamonov <kartamonov@nvidia.com>
Change-Id: Ieaa70875b92920567ad7cd75eca6eac8197f46de
Reviewed-on: http://git-master/r/108511
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

drivers/video/tegra/Kconfig
drivers/video/tegra/nvmap/nvmap_common.h
drivers/video/tegra/nvmap/nvmap_dev.c
drivers/video/tegra/nvmap/nvmap_ioctl.c

index 650c418..68cf542 100644 (file)
@@ -119,7 +119,7 @@ config NVMAP_PAGE_POOL_SIZE
        default 0x0
 
 config NVMAP_CACHE_MAINT_BY_SET_WAYS
-       bool "Enalbe cache maintenance by set/ways"
+       bool "Enable cache maintenance by set/ways"
        depends on TEGRA_NVMAP
        help
         Say Y here to reduce cache maintenance overhead by MVA.
@@ -127,6 +127,14 @@ config NVMAP_CACHE_MAINT_BY_SET_WAYS
         where inner cache includes only L1. For the systems, where inner cache
         includes L1 and L2, keep this option disabled.
 
+config NVMAP_OUTER_CACHE_MAINT_BY_SET_WAYS
+       bool "Enable outer cache maintenance by set/ways"
+       depends on TEGRA_NVMAP
+       help
+         Say Y here if you want to optimize cache maintenance for ranges
+         bigger than size of outer cache. This option has no effect on
+         system without outer cache.
+
 config NVMAP_VPR
        bool "Enable VPR Heap."
        depends on TEGRA_NVMAP
index 6da0107..2a1e2b4 100644 (file)
@@ -23,7 +23,8 @@
 extern void v7_flush_kern_cache_all(void *);
 extern void v7_clean_kern_cache_all(void *);
 
-#define FLUSH_CLEAN_BY_SET_WAY_THRESHOLD (8 * PAGE_SIZE)
+#define FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER (8 * PAGE_SIZE)
+#define FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_OUTER (1024 * 1024)
 
 static inline void inner_flush_cache_all(void)
 {
index 02ccaee..0c12348 100644 (file)
@@ -290,7 +290,7 @@ int nvmap_flush_heap_block(struct nvmap_client *client,
        if (prot == NVMAP_HANDLE_UNCACHEABLE || prot == NVMAP_HANDLE_WRITE_COMBINE)
                goto out;
 
-       if (len >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD) {
+       if (len >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER) {
                inner_flush_cache_all();
                if (prot != NVMAP_HANDLE_INNER_CACHEABLE)
                        outer_flush_range(block->base, block->base + len);
index e3adc0a..da974b2 100644 (file)
@@ -550,14 +550,32 @@ static void heap_page_cache_maint(struct nvmap_client *client,
        }
 }
 
+static bool fast_cache_maint_outer(unsigned long start,
+               unsigned long end, unsigned int op)
+{
+       bool result = false;
+#if defined(CONFIG_NVMAP_OUTER_CACHE_MAINT_BY_SET_WAYS)
+       if (end - start >= FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_OUTER) {
+               if (op == NVMAP_CACHE_OP_WB_INV) {
+                       outer_flush_all();
+                       result = true;
+               }
+               if (op == NVMAP_CACHE_OP_WB) {
+                       outer_clean_all();
+                       result = true;
+               }
+       }
+#endif
+       return result;
+}
+
 static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
        unsigned long start, unsigned long end, unsigned int op)
 {
        int ret = false;
-
 #if defined(CONFIG_NVMAP_CACHE_MAINT_BY_SET_WAYS)
        if ((op == NVMAP_CACHE_OP_INV) ||
-               ((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD))
+               ((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD_INNER))
                goto out;
 
        if (op == NVMAP_CACHE_OP_WB_INV)
@@ -565,13 +583,19 @@ static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h
        else if (op == NVMAP_CACHE_OP_WB)
                inner_clean_cache_all();
 
-       if (h->heap_pgalloc && (h->flags != NVMAP_HANDLE_INNER_CACHEABLE)) {
-               heap_page_cache_maint(client, h, start, end, op,
-                               false, true, NULL, 0, 0);
-       } else if (h->flags != NVMAP_HANDLE_INNER_CACHEABLE) {
-               start += h->carveout->base;
-               end += h->carveout->base;
-               outer_cache_maint(op, start, end - start);
+       /* outer maintenance */
+       if (h->flags != NVMAP_HANDLE_INNER_CACHEABLE ) {
+               if(!fast_cache_maint_outer(start, end, op))
+               {
+                       if (h->heap_pgalloc) {
+                               heap_page_cache_maint(client, h, start,
+                                       end, op, false, true, NULL, 0, 0);
+                       } else  {
+                               start += h->carveout->base;
+                               end += h->carveout->base;
+                               outer_cache_maint(op, start, end - start);
+                       }
+               }
        }
        ret = true;
 out: