diff mbox

[14/16] ARM: TC2: ensure powerdown-time data is flushed from cache

Message ID 1357777251-13541-15-git-send-email-nicolas.pitre@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Nicolas Pitre Jan. 10, 2013, 12:20 a.m. UTC
From: Dave Martin <dave.martin@linaro.org>

Non-local variables used by the CCI management function called after
disabling the cache must be flushed out to main memory in advance,
otherwise incoherency of those values may occur if they are sitting
in the cache of some other CPU when cci_disable() executes.

This patch adds the appropriate flushing to the CCI driver to ensure
that the relevant data is available in RAM ahead of time.

Because this creates a dependency on arch-specific cacheflushing
functions, this patch also makes ARM_CCI depend on ARM.

Signed-off-by: Dave Martin <dave.martin@linaro.org>
Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 drivers/misc/Kconfig   |  1 +
 drivers/misc/arm-cci.c | 21 +++++++++++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)

Comments

tip-bot for Dave Martin Jan. 10, 2013, 6:50 p.m. UTC | #1
On Wed, Jan 09, 2013 at 07:20:49PM -0500, Nicolas Pitre wrote:
> From: Dave Martin <dave.martin@linaro.org>

To avoid confusion, the prefix in the subject line should be "CCI", not
"TC2".  Any platform which calls disable_cci() after turning caches off
and/or disabling the SMP bit may fall foul of this otherwise ... i.e.,
any platform which has CCI.

Let me know if you want me to send you a modified patch.

Cheers
---Daave

> Non-local variables used by the CCI management function called after
> disabling the cache must be flushed out to main memory in advance,
> otherwise incoherency of those values may occur if they are sitting
> in the cache of some other CPU when cci_disable() executes.
> 
> This patch adds the appropriate flushing to the CCI driver to ensure
> that the relevant data is available in RAM ahead of time.
> 
> Because this creates a dependency on arch-specific cacheflushing
> functions, this patch also makes ARM_CCI depend on ARM.
> 
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
> ---
>  drivers/misc/Kconfig   |  1 +
>  drivers/misc/arm-cci.c | 21 +++++++++++++++++++--
>  2 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 30d5be1ad2..b24630696c 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -501,6 +501,7 @@ config USB_SWITCH_FSA9480
>  
>  config ARM_CCI
>         bool "ARM CCI driver support"
> +	depends on ARM
>  
>  source "drivers/misc/c2port/Kconfig"
>  source "drivers/misc/eeprom/Kconfig"
> diff --git a/drivers/misc/arm-cci.c b/drivers/misc/arm-cci.c
> index f329c43099..739e1c96d3 100644
> --- a/drivers/misc/arm-cci.c
> +++ b/drivers/misc/arm-cci.c
> @@ -21,8 +21,16 @@
>  #include <linux/slab.h>
>  #include <linux/arm-cci.h>
>  
> -#define CCI400_EAG_OFFSET       0x4000
> -#define CCI400_KF_OFFSET        0x5000
> +#include <asm/cacheflush.h>
> +#include <asm/memory.h>
> +#include <asm/outercache.h>
> +
> +#include <asm/irq_regs.h>
> +#include <asm/pmu.h>
> +
> +#define CCI400_PMCR                   0x0100
> +#define CCI400_EAG_OFFSET             0x4000
> +#define CCI400_KF_OFFSET              0x5000
>  
>  #define DRIVER_NAME	"CCI"
>  struct cci_drvdata {
> @@ -73,6 +81,15 @@ static int __devinit cci_driver_probe(struct platform_device *pdev)
>  		goto ioremap_err;
>  	}
>  
> +	/*
> +	 * Multi-cluster systems may need this data when non-coherent, during
> +	 * cluster power-up/power-down. Make sure it reaches main memory:
> +	 */
> +	__cpuc_flush_dcache_area(info, sizeof *info);
> +	__cpuc_flush_dcache_area(&info, sizeof info);
> +	outer_clean_range(virt_to_phys(info), virt_to_phys(info + 1));
> +	outer_clean_range(virt_to_phys(&info), virt_to_phys(&info + 1));
> +
>  	platform_set_drvdata(pdev, info);
>  
>  	pr_info("CCI loaded at %p\n", info->baseaddr);
> -- 
> 1.8.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Nicolas Pitre Jan. 10, 2013, 7:13 p.m. UTC | #2
On Thu, 10 Jan 2013, Dave Martin wrote:

> On Wed, Jan 09, 2013 at 07:20:49PM -0500, Nicolas Pitre wrote:
> > From: Dave Martin <dave.martin@linaro.org>
> 
> To avoid confusion, the prefix in the subject line should be "CCI", not
> "TC2".

Absolutely.  This is my mistake as I removed the TC2 changes from your 
original patch to only keep the CCI ones, but forgot to update the patch 
title.


Nicolas
tip-bot for Dave Martin Jan. 11, 2013, 11:38 a.m. UTC | #3
On Thu, Jan 10, 2013 at 02:13:09PM -0500, Nicolas Pitre wrote:
> On Thu, 10 Jan 2013, Dave Martin wrote:
> 
> > On Wed, Jan 09, 2013 at 07:20:49PM -0500, Nicolas Pitre wrote:
> > > From: Dave Martin <dave.martin@linaro.org>
> > 
> > To avoid confusion, the prefix in the subject line should be "CCI", not
> > "TC2".
> 
> Absolutely.  This is my mistake as I removed the TC2 changes from your 
> original patch to only keep the CCI ones, but forgot to update the patch 
> title.

Oh right.  I was quite happy to believe it was my mistake :)

It makes sense to have two separate patches anyway, though.

Cheers
---Dave
diff mbox

Patch

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 30d5be1ad2..b24630696c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -501,6 +501,7 @@  config USB_SWITCH_FSA9480
 
 config ARM_CCI
        bool "ARM CCI driver support"
+	depends on ARM
 
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
diff --git a/drivers/misc/arm-cci.c b/drivers/misc/arm-cci.c
index f329c43099..739e1c96d3 100644
--- a/drivers/misc/arm-cci.c
+++ b/drivers/misc/arm-cci.c
@@ -21,8 +21,16 @@ 
 #include <linux/slab.h>
 #include <linux/arm-cci.h>
 
-#define CCI400_EAG_OFFSET       0x4000
-#define CCI400_KF_OFFSET        0x5000
+#include <asm/cacheflush.h>
+#include <asm/memory.h>
+#include <asm/outercache.h>
+
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
+
+#define CCI400_PMCR                   0x0100
+#define CCI400_EAG_OFFSET             0x4000
+#define CCI400_KF_OFFSET              0x5000
 
 #define DRIVER_NAME	"CCI"
 struct cci_drvdata {
@@ -73,6 +81,15 @@  static int __devinit cci_driver_probe(struct platform_device *pdev)
 		goto ioremap_err;
 	}
 
+	/*
+	 * Multi-cluster systems may need this data when non-coherent, during
+	 * cluster power-up/power-down. Make sure it reaches main memory:
+	 */
+	__cpuc_flush_dcache_area(info, sizeof *info);
+	__cpuc_flush_dcache_area(&info, sizeof info);
+	outer_clean_range(virt_to_phys(info), virt_to_phys(info + 1));
+	outer_clean_range(virt_to_phys(&info), virt_to_phys(&info + 1));
+
 	platform_set_drvdata(pdev, info);
 
 	pr_info("CCI loaded at %p\n", info->baseaddr);