]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ARC: IOC: panic if kernel was started with previously enabled IOC
authorEugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Thu, 4 Oct 2018 13:12:12 +0000 (16:12 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Dec 2019 07:51:12 +0000 (08:51 +0100)
[ Upstream commit 3624379d90ad2b65f9dbb30d7f7ce5498d2fe322 ]

If IOC was already enabled (due to bootloader) it technically needs to
be reconfigured with aperture base,size corresponding to Linux memory map
which will certainly be different than uboot's. But disabling and
reenabling IOC when DMA might be potentially active is tricky business.
To avoid random memory issues later, just panic here and ask user to
upgrade bootloader to one which doesn't enable IOC

This was actually seen as issue on some of the HSDK board with a version
of uboot which enabled IOC. There were random issues later with starting
of X or peripherals etc.

Also while I'm at it, replace hardcoded bits in ARC_REG_IO_COH_PARTIAL
and ARC_REG_IO_COH_ENABLE registers by definitions.

Inspired by: https://lkml.org/lkml/2018/1/19/557
Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/arc/include/asm/cache.h
arch/arc/mm/cache.c

index db681cf4959c879803b17b71b9da8ebb54264e4a..2ad77fb43639cd89fe2a00033790d565a2ff1935 100644 (file)
@@ -124,7 +124,9 @@ extern unsigned long perip_base, perip_end;
 
 /* IO coherency related Auxiliary registers */
 #define ARC_REG_IO_COH_ENABLE  0x500
+#define ARC_IO_COH_ENABLE_BIT  BIT(0)
 #define ARC_REG_IO_COH_PARTIAL 0x501
+#define ARC_IO_COH_PARTIAL_BIT BIT(0)
 #define ARC_REG_IO_COH_AP0_BASE        0x508
 #define ARC_REG_IO_COH_AP0_SIZE        0x509
 
index f2701c13a66b209571ff89b71ac6c93cabb9835d..cf9619d4efb4f86d68cb2417558fe3327c55c408 100644 (file)
@@ -1144,6 +1144,20 @@ noinline void __init arc_ioc_setup(void)
 {
        unsigned int ioc_base, mem_sz;
 
+       /*
+        * If IOC was already enabled (due to bootloader) it technically needs to
+        * be reconfigured with aperture base,size corresponding to Linux memory map
+        * which will certainly be different than uboot's. But disabling and
+        * reenabling IOC when DMA might be potentially active is tricky business.
+        * To avoid random memory issues later, just panic here and ask user to
+        * upgrade bootloader to one which doesn't enable IOC
+        */
+       if (read_aux_reg(ARC_REG_IO_COH_ENABLE) & ARC_IO_COH_ENABLE_BIT)
+               panic("IOC already enabled, please upgrade bootloader!\n");
+
+       if (!ioc_enable)
+               return;
+
        /*
         * As for today we don't support both IOC and ZONE_HIGHMEM enabled
         * simultaneously. This happens because as of today IOC aperture covers
@@ -1187,8 +1201,8 @@ noinline void __init arc_ioc_setup(void)
                panic("IOC Aperture start must be aligned to the size of the aperture");
 
        write_aux_reg(ARC_REG_IO_COH_AP0_BASE, ioc_base >> 12);
-       write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
-       write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
+       write_aux_reg(ARC_REG_IO_COH_PARTIAL, ARC_IO_COH_PARTIAL_BIT);
+       write_aux_reg(ARC_REG_IO_COH_ENABLE, ARC_IO_COH_ENABLE_BIT);
 
        /* Re-enable L1 dcache */
        __dc_enable();
@@ -1265,7 +1279,7 @@ void __init arc_cache_init_master(void)
        if (is_isa_arcv2() && l2_line_sz && !slc_enable)
                arc_slc_disable();
 
-       if (is_isa_arcv2() && ioc_enable)
+       if (is_isa_arcv2() && ioc_exists)
                arc_ioc_setup();
 
        if (is_isa_arcv2() && l2_line_sz && slc_enable) {