[PATCH] MIPS: Add option to disable software I/O coherency.

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] MIPS: Add option to disable software I/O coherency.

Steven J. Hill-3
From: "Steven J. Hill" <[hidden email]>

Some MIPS controllers have hardware I/O coherency. This patch
detects those and turns off software coherency. A new kernel
command line option also allows the user to manually turn
software coherency on or off.

Signed-off-by: Steven J. Hill <[hidden email]>
---
 arch/mips/include/asm/mach-generic/dma-coherence.h |    4 +-
 arch/mips/mm/c-r4k.c                               |   21 +---
 arch/mips/mm/dma-default.c                         |    8 +-
 arch/mips/mti-malta/malta-setup.c                  |  102 ++++++++++++++++++++
 4 files changed, 116 insertions(+), 19 deletions(-)

diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 9c95177..9f1cd31 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -63,7 +63,9 @@ static inline int plat_device_is_coherent(struct device *dev)
  return 1;
 #endif
 #ifdef CONFIG_DMA_NONCOHERENT
- return 0;
+ extern int coherentio;
+
+ return coherentio;
 #endif
 }
 
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index c0f27c8..7f13f24 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1383,20 +1383,6 @@ static void __cpuinit coherency_setup(void)
  }
 }
 
-#if defined(CONFIG_DMA_NONCOHERENT)
-
-static int __cpuinitdata coherentio;
-
-static int __init setcoherentio(char *str)
-{
- coherentio = 1;
-
- return 1;
-}
-
-__setup("coherentio", setcoherentio);
-#endif
-
 static void __cpuinit r4k_cache_error_setup(void)
 {
  extern char __weak except_vec2_generic;
@@ -1419,6 +1405,7 @@ void __cpuinit r4k_cache_init(void)
 {
  extern void build_clear_page(void);
  extern void build_copy_page(void);
+ extern int coherentio;
  struct cpuinfo_mips *c = &current_cpu_data;
 
  probe_pcache();
@@ -1478,9 +1465,11 @@ void __cpuinit r4k_cache_init(void)
 
  build_clear_page();
  build_copy_page();
-#if !defined(CONFIG_MIPS_CMP)
+
+ /* We want to run CMP kernels on core(s) with and without coherent caches */
+ /* Therefore can't use CONFIG_MIPS_CMP to decide to flush cache */
  local_r4k___flush_cache_all(NULL);
-#endif
+
  coherency_setup();
  board_cache_error_setup = r4k_cache_error_setup;
 }
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 3fab204..058c2ca 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -100,6 +100,7 @@ EXPORT_SYMBOL(dma_alloc_noncoherent);
 static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
  dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
 {
+ extern int hw_coherentio;
  void *ret;
 
  if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
@@ -115,7 +116,8 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
 
  if (!plat_device_is_coherent(dev)) {
  dma_cache_wback_inv((unsigned long) ret, size);
- ret = UNCAC_ADDR(ret);
+ if (!hw_coherentio)
+ ret = UNCAC_ADDR(ret);
  }
  }
 
@@ -134,6 +136,7 @@ EXPORT_SYMBOL(dma_free_noncoherent);
 static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
  dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
+ extern int hw_coherentio;
  unsigned long addr = (unsigned long) vaddr;
  int order = get_order(size);
 
@@ -143,7 +146,8 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
  plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
 
  if (!plat_device_is_coherent(dev))
- addr = CAC_ADDR(addr);
+ if (!hw_coherentio)
+ addr = CAC_ADDR(addr);
 
  free_pages(addr, get_order(size));
 }
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index ed68073..0bac429 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -31,6 +31,7 @@
 #include <asm/mips-boards/maltaint.h>
 #include <asm/dma.h>
 #include <asm/traps.h>
+#include <asm/gcmpregs.h>
 #ifdef CONFIG_VT
 #include <linux/console.h>
 #endif
@@ -104,6 +105,105 @@ static void __init fd_activate(void)
 }
 #endif
 
+int coherentio = -1; /* no DMA cache coherency (may be set by user) */
+int hw_coherentio; /* init to 0 => no HW DMA cache coherency (reflects real HW) */
+static int __init setcoherentio(char *str)
+{
+ if (coherentio < 0)
+ pr_info("Command line checking done before"
+ " plat_setup_iocoherency!!\n");
+ if (coherentio == 0)
+ pr_info("Command line enabling coherentio"
+ " (this will break...)!!\n");
+
+ coherentio = 1;
+ pr_info("Hardware DMA cache coherency (command line)\n");
+ return 1;
+}
+__setup("coherentio", setcoherentio);
+
+static int __init setnocoherentio(char *str)
+{
+ if (coherentio < 0)
+ pr_info("Command line checking done before"
+ " plat_setup_iocoherency!!\n");
+ if (coherentio == 1)
+ pr_info("Command line disabling coherentio\n");
+
+ coherentio = 0;
+ pr_info("Software DMA cache coherency (command line)\n");
+ return 1;
+}
+__setup("nocoherentio", setnocoherentio);
+
+static int __init
+plat_enable_iocoherency(void)
+{
+ int supported = 0;
+ if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
+ if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
+ BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
+ pr_info("Enabled Bonito CPU coherency\n");
+ supported = 1;
+ }
+ if (strstr(fw_getcmdline(), "iobcuncached")) {
+ BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
+ BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+ ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+  BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+ pr_info("Disabled Bonito IOBC coherency\n");
+ } else {
+ BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
+ BONITO_PCIMEMBASECFG |=
+ (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+ pr_info("Enabled Bonito IOBC coherency\n");
+ }
+ } else if (gcmp_niocu() != 0) {
+ /* Nothing special needs to be done to enable coherency */
+ pr_info("CMP IOCU detected\n");
+ if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) {
+ pr_crit("IOCU OPERATION DISABLED BY SWITCH"
+ " - DEFAULTING TO SW IO COHERENCY\n");
+ return 0;
+ }
+ supported = 1;
+ }
+ hw_coherentio = supported;
+ return supported;
+}
+
+static void __init
+plat_setup_iocoherency(void)
+{
+#ifdef CONFIG_DMA_NONCOHERENT
+ /*
+ * Kernel has been configured with software coherency
+ * but we might choose to turn it off
+ */
+ if (plat_enable_iocoherency()) {
+ if (coherentio == 0)
+ pr_info("Hardware DMA cache coherency supported"
+ " but disabled from command line\n");
+ else {
+ coherentio = 1;
+ printk(KERN_INFO "Hardware DMA cache coherency\n");
+ }
+ } else {
+ if (coherentio == 1)
+ pr_info("Hardware DMA cache coherency not supported"
+ " but enabled from command line\n");
+ else {
+ coherentio = 0;
+ pr_info("Software DMA cache coherency\n");
+ }
+ }
+#else
+ if (!plat_enable_iocoherency())
+ panic("Hardware DMA cache coherency not supported");
+#endif
+}
+
 #ifdef CONFIG_BLK_DEV_IDE
 static void __init pci_clock_check(void)
 {
@@ -205,6 +305,8 @@ void __init plat_mem_setup(void)
  if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO)
  bonito_quirks_setup();
 
+ plat_setup_iocoherency();
+
 #ifdef CONFIG_BLK_DEV_IDE
  pci_clock_check();
 #endif
--
1.7.9.5


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] MIPS: Add option to disable software I/O coherency.

Shane McDonald-3
On Thu, Dec 6, 2012 at 11:23 PM, Steven J. Hill <[hidden email]> wrote:
> From: "Steven J. Hill" <[hidden email]>
>
> Some MIPS controllers have hardware I/O coherency. This patch
> detects those and turns off software coherency. A new kernel
> command line option also allows the user to manually turn
> software coherency on or off.
>
> Signed-off-by: Steven J. Hill <[hidden email]>

This patch conflicts with commit b5b64f2ba4 "MIPS: Move processing of
coherency kernel parameters earlier" in the linux-next tree.

Shane McDonald