[RFC/PATCH] map drivers. DCACHE option for physmap and mphysmap drivers

Korolev, Alexey alexey.korolev at intel.com
Thu Jan 26 12:24:29 EST 2006


Hi All,
 
Some mapping drivers of linux-mtd has feature of cached mapping. This
can improve read performance on FLASH significantly . 
I think adding the option of data cache mapping would also be helpful
for physmap and mphysmap drivers.
 
Here is a perf. data I measured on Mainstone with enabled and disabled
DCACHE mapping option:
 
DCAHCE is off:
time dd if=/dev/mtd2 of=/dev/null bs=4k count=4k
4096+0 records in
4096+0 records out
real    0m 7.21s
user    0m 0.00s
sys     0m 7.21s
 
DCACHE is on:
time dd if=/dev/mtd2 of=/dev/null bs=4k count=4k
4096+0 records in
4096+0 records out
real    0m 0.69s
user    0m 0.01s
sys     0m 0.69s
 
 
Please find diff file below. 
 
========================================================================
=====
diff -uNr a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
--- a/drivers/mtd/maps/Kconfig 2005-12-22 15:06:38.000000000 +0300
+++ b/drivers/mtd/maps/Kconfig 2005-12-22 15:05:24.000000000 +0300
@@ -60,6 +60,12 @@
    Ignore this option if you use run-time physmap configuration
    (i.e., run-time calling physmap_configure()).
 
+config MTD_PHYSMAP_DCACHE
+ bool "Enable dcache for flash mapping"
+ depends on MTD_PHYSMAP
+ help
+   This option enables CPU data cache for flash mapping
+   This improves flash read speed significantly. 
 config MTD_MULTI_PHYSMAP
  tristate "multiple CFI Flash devices in physical memory map"
  depends on MTD_CFI
@@ -86,6 +92,12 @@
  depends on MTD_MULTI_PHYSMAP
  default "2"
 
+config MTD_MULTI_PHYSMAP_1_DCACHE
+ bool "Enable dcache for 1st flash mapping"
+ depends on MTD_MULTI_PHYSMAP
+ help
+   This option enables CPU data cache for 1st flash mapping
+   This improves flash read speed significantly.
 config MTD_MULTI_PHYSMAP_2_NAME
  string "2nd mapping name"
  depends on MTD_MULTI_PHYSMAP
@@ -106,6 +118,12 @@
  depends on MTD_MULTI_PHYSMAP
  default "2"
 
+config MTD_MULTI_PHYSMAP_2_DCACHE
+ bool "Enable dcache for 2nd flash mapping"
+ depends on MTD_MULTI_PHYSMAP
+ help
+   This option enables CPU data cache for 2nd flash mapping
+   This improves flash read speed significantly.
 config MTD_MULTI_PHYSMAP_3_NAME
  string "3rd mapping name"
  depends on MTD_MULTI_PHYSMAP
@@ -126,6 +144,12 @@
  depends on MTD_MULTI_PHYSMAP
  default "2"
 
+config MTD_MULTI_PHYSMAP_3_DCACHE
+ bool "Enable dcache for 3rd flash mapping"
+ depends on MTD_MULTI_PHYSMAP
+ help
+   This option enables CPU data cache for 3rd flash mapping
+   This improves flash read speed significantly.
 config MTD_MULTI_PHYSMAP_4_NAME
  string "4th mapping name"
  depends on MTD_MULTI_PHYSMAP
@@ -146,6 +170,12 @@
  depends on MTD_MULTI_PHYSMAP
  default "2"
 
+config MTD_MULTI_PHYSMAP_4_DCACHE
+ bool "Enable dcache for 4th flash mapping"
+ depends on MTD_MULTI_PHYSMAP
+ help
+   This option enables CPU data cache for 4th flash mapping
+   This improves flash read speed significantly.
 config MTD_SUN_UFLASH
  tristate "Sun Microsystems userflash support"
  depends on (SPARC32 || SPARC64) && MTD_CFI
diff -uNr a/drivers/mtd/maps/mphysmap.c b/drivers/mtd/maps/mphysmap.c
--- a/drivers/mtd/maps/mphysmap.c 2005-12-22 15:06:38.000000000 +0300
+++ b/drivers/mtd/maps/mphysmap.c 2005-12-22 15:05:24.000000000 +0300
@@ -9,9 +9,40 @@
 #include <linux/module.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
+#if defined(CONFIG_MTD_MULTI_PHYSMAP_1_DCACHE) || \
+    defined(CONFIG_MTD_MULTI_PHYSMAP_2_DCACHE) || \
+    defined(CONFIG_MTD_MULTI_PHYSMAP_3_DCACHE) || \
+    defined(CONFIG_MTD_MULTI_PHYSMAP_4_DCACHE)
+#define CONFIG_MTD_MULTI_PHYSMAP_DCACHE
+#endif    
 #ifdef CONFIG_MTD_PARTITIONS
 #include <linux/mtd/partitions.h>
 #endif
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_DCACHE
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+#endif
+
+
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_DCACHE
+static void mphysmap_inval_cache(struct map_info *map, unsigned long
from, ssize_t len)
+{unsigned long end;
+   /* flush_cache_all() works, but seriously degrades performance */
+   /* flush_cache_all(); */
+   /**/
+   /* round to full pages */
+   end=(from+len);
+   end=(end / PAGE_SIZE + 1) * PAGE_SIZE;
+   from=(from / PAGE_SIZE) * PAGE_SIZE;
+   len=end-from;
+#ifdef CONFIG_ARM        
+   consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+#else
+   /* Non ARM architectures has not been tested */
+   dma_cache_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+#endif
+}
+#endif
 
 static struct map_info mphysmap_static_maps[] = {
 #if CONFIG_MTD_MULTI_PHYSMAP_1_WIDTH
@@ -20,6 +57,9 @@
   .phys  = CONFIG_MTD_MULTI_PHYSMAP_1_START,
   .size  = CONFIG_MTD_MULTI_PHYSMAP_1_LEN,
   .bankwidth = CONFIG_MTD_MULTI_PHYSMAP_1_WIDTH,
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_1_DCACHE
+  .inval_cache = mphysmap_inval_cache,
+#endif
  },
 #endif
 #if CONFIG_MTD_MULTI_PHYSMAP_2_WIDTH
@@ -28,6 +68,9 @@
   .phys  = CONFIG_MTD_MULTI_PHYSMAP_2_START,
   .size  = CONFIG_MTD_MULTI_PHYSMAP_2_LEN,
   .bankwidth = CONFIG_MTD_MULTI_PHYSMAP_2_WIDTH,
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_2_DCACHE
+  .inval_cache = mphysmap_inval_cache,
+#endif
  },
 #endif
 #if CONFIG_MTD_MULTI_PHYSMAP_3_WIDTH
@@ -36,6 +79,9 @@
   .phys  = CONFIG_MTD_MULTI_PHYSMAP_3_START,
   .size  = CONFIG_MTD_MULTI_PHYSMAP_3_LEN,
   .bankwidth = CONFIG_MTD_MULTI_PHYSMAP_3_WIDTH,
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_3_DCACHE
+  .inval_cache = mphysmap_inval_cache,
+#endif
  },
 #endif
 #if CONFIG_MTD_MULTI_PHYSMAP_4_WIDTH
@@ -44,6 +90,9 @@
   .phys  = CONFIG_MTD_MULTI_PHYSMAP_4_START,
   .size  = CONFIG_MTD_MULTI_PHYSMAP_4_LEN,
   .bankwidth = CONFIG_MTD_MULTI_PHYSMAP_4_WIDTH,
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_4_DCACHE
+  .inval_cache = mphysmap_inval_cache,
+#endif
  },
 #endif
 };
@@ -68,10 +117,20 @@
 #endif
        NULL};
 #endif
- map->virt = ioremap(map->phys, map->size);
+ map->virt = ioremap_nocache(map->phys, map->size);
  if (!map->virt)
   return -EIO;
-
+        map->cached=NULL;        
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_DCACHE
+        if (map->inval_cache)
+        {
+#ifdef CONFIG_ARM        
+           map->cached = ioremap_cached(map->phys, map->size);
+#else
+           map->cached = __ioremap(map->phys, map->size,
L_PTE_CACHEABLE);
+#endif
+        };   
+#endif
  simple_map_init(map);
  mtd = NULL;
  type = rom_probe_types;
@@ -81,6 +140,10 @@
 
  if (!mtd) {
   iounmap(map->virt);
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_DCACHE
+  if (map->cached)
+      iounmap(map->cached);
+#endif
   return -ENXIO;
  }
 
@@ -134,6 +197,12 @@
  map->map_priv_1 = 0;
  map->map_priv_2 = 0;
  map->virt = NULL;
+#ifdef CONFIG_MTD_MULTI_PHYSMAP_DCACHE
+ if (map->cached) {
+     iounmap(map->cached);
+     map->cached = NULL;
+ }
+#endif
 }
 
 
diff -uNr a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
--- a/drivers/mtd/maps/physmap.c 2005-12-22 15:06:38.000000000 +0300
+++ b/drivers/mtd/maps/physmap.c 2005-12-22 15:05:24.000000000 +0300
@@ -19,15 +19,41 @@
 #include <linux/mtd/map.h>
 #include <linux/config.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
+#ifdef CONFIG_MTD_PHYSMAP_DCACHE
+#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+#endif
 
 static struct mtd_info *mymtd;
 
+#ifdef CONFIG_MTD_PHYSMAP_DCACHE
+static void physmap_inval_cache(struct map_info *map, unsigned long
from, ssize_t len)
+{unsigned long end;
+   /* flush_cache_all() works, but seriously degrades performance */
+   /* flush_cache_all(); */
+   /**/
+   /* round to full pages */
+   end=(from+len);
+   end=(end / PAGE_SIZE + 1) * PAGE_SIZE;
+   from=(from / PAGE_SIZE) * PAGE_SIZE;
+   len=end-from;
+#ifdef CONFIG_ARM        
+   consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+#else
+   /* Non ARM architectures are not tested */
+   dma_cache_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
+#endif
+}
+#endif
+
 struct map_info physmap_map = {
  .name = "phys_mapped_flash",
  .phys = CONFIG_MTD_PHYSMAP_START,
  .size = CONFIG_MTD_PHYSMAP_LEN,
  .bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH,
+#ifdef CONFIG_MTD_PHYSMAP_DCACHE
+ .inval_cache = physmap_inval_cache,
+#endif
 };
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -52,13 +78,22 @@
  const char **type;
 
         printk(KERN_NOTICE "physmap flash device: %lx at %lx\n",
physmap_map.size, physmap_map.phys);
- physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
+ physmap_map.virt = ioremap_nocache(physmap_map.phys,
physmap_map.size);
 
  if (!physmap_map.virt) {
   printk("Failed to ioremap\n");
   return -EIO;
  }
-
+#ifdef CONFIG_MTD_PHYSMAP_DCACHE
+#ifdef CONFIG_ARM
+ physmap_map.cached = ioremap_cached(physmap_map.phys,
physmap_map.size);
+#else        
+ physmap_map.cached = __ioremap(physmap_map.phys, physmap_map.size,
L_PTE_CACHEABLE);
+#endif        
+ if (!physmap_map.cached) {
+  printk("Failed to ioremap cached\n");
+ }
+#endif
  simple_map_init(&physmap_map);
 
  mymtd = NULL;
@@ -94,6 +129,10 @@
  }
 
  iounmap(physmap_map.virt);
+#ifdef CONFIG_MTD_PHYSMAP_DCACHE
+ if (physmap_map.cached)
+  iounmap(physmap_map.cached);
+#endif
  return -ENXIO;
 }
 
@@ -115,6 +154,12 @@
 
  iounmap(physmap_map.virt);
  physmap_map.virt = NULL;
+#ifdef CONFIG_MTD_PHYSMAP_DCACHE
+ if (physmap_map.cached) {
+  iounmap(physmap_map.cached);
+  physmap_map.cached = NULL;
+ }
+#endif
 }
 
 module_init(init_physmap);
=========================================================
 
Thanks,
Alexey




More information about the linux-mtd mailing list