]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Jul 2016 20:03:49 +0000 (13:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Jul 2016 20:03:49 +0000 (13:03 -0700)
Pull ARM updates from Russell King:
 "Included in this update are:

   - Patches from Gregory Clement to fix the coherent DMA cases in our
     dma-mapping code.

   - A number of CPU errata updates and fixes.

   - ARM cpuidle improvements from Jisheng Zhang.

   - Fix from Kees for the location of _etext.

   - Cleanups from Masahiro Yamada to avoid duplicated messages during
     the kernel build, and remove CONFIG_ARCH_HAS_BARRIERS.

   - Remove a udelay loop limitation, allowing for faster CPUs to
     calibrate the delay correctly.

   - Cleanup some left-overs from the SW PAN implementation.

   - Ensure that a modified address limit is not visible to exception
     handlers"

* 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm: (21 commits)
  ARM: 8586/1: cpuidle: make arm_cpuidle_suspend() a bit more efficient
  ARM: 8585/1: cpuidle: fix !cpuidle_ops[cpu].init case during init
  ARM: 8561/4: dma-mapping: Fix the coherent case when iommu is used
  ARM: 8561/3: dma-mapping: Don't use outer_flush_range when the L2C is coherent
  ARM: 8560/1: errata: Workaround errata A12 825619 / A17 852421
  ARM: 8559/1: errata: Workaround erratum A12 821420
  ARM: 8558/1: errata: Workaround errata A12 818325/852422 A17 852423
  ARM: save and reset the address limit when entering an exception
  ARM: 8577/1: Fix Cortex-A15 798181 errata initialization
  ARM: 8584/1: floppy: avoid gcc-6 warning
  ARM: 8583/1: mm: fix location of _etext
  ARM: 8582/1: remove unused CONFIG_ARCH_HAS_BARRIERS
  ARM: 8306/1: loop_udelay: remove bogomips value limitation
  ARM: 8581/1: add missing <asm/prom.h> to arch/arm/kernel/devtree.c
  ARM: 8576/1: avoid duplicating "Kernel: arch/arm/boot/*Image is ready"
  ARM: 8556/1: on a generic DT system: do not touch l2x0
  ARM: uaccess: remove put_user() code duplication
  ARM: 8580/1: Remove orphaned __addr_ok() definition
  ARM: get rid of horrible *(unsigned int *)(regs + 1)
  ARM: introduce svc_pt_regs structure
  ...

25 files changed:
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/include/asm/assembler.h
arch/arm/include/asm/barrier.h
arch/arm/include/asm/delay.h
arch/arm/include/asm/floppy.h
arch/arm/include/asm/ptrace.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/cpuidle.c
arch/arm/kernel/devtree.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/entry-v7m.S
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp_tlb.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/lib/Makefile
arch/arm/lib/delay-loop.S
arch/arm/mm/Kconfig
arch/arm/mm/dma-mapping.c
arch/arm/mm/proc-v7.S

index f0636ec949032276be07527f7f7178d068b8f6c4..4c445fb9c189fe1d527c086f87a572f876830d73 100644 (file)
@@ -1186,6 +1186,60 @@ config ARM_ERRATA_773022
          loop buffer may deliver incorrect instructions. This
          workaround disables the loop buffer to avoid the erratum.
 
+config ARM_ERRATA_818325_852422
+       bool "ARM errata: A12: some seqs of opposed cond code instrs => deadlock or corruption"
+       depends on CPU_V7
+       help
+         This option enables the workaround for:
+         - Cortex-A12 818325: Execution of an UNPREDICTABLE STR or STM
+           instruction might deadlock.  Fixed in r0p1.
+         - Cortex-A12 852422: Execution of a sequence of instructions might
+           lead to either a data corruption or a CPU deadlock.  Not fixed in
+           any Cortex-A12 cores yet.
+         This workaround for all both errata involves setting bit[12] of the
+         Feature Register. This bit disables an optimisation applied to a
+         sequence of 2 instructions that use opposing condition codes.
+
+config ARM_ERRATA_821420
+       bool "ARM errata: A12: sequence of VMOV to core registers might lead to a dead lock"
+       depends on CPU_V7
+       help
+         This option enables the workaround for the 821420 Cortex-A12
+         (all revs) erratum. In very rare timing conditions, a sequence
+         of VMOV to Core registers instructions, for which the second
+         one is in the shadow of a branch or abort, can lead to a
+         deadlock when the VMOV instructions are issued out-of-order.
+
+config ARM_ERRATA_825619
+       bool "ARM errata: A12: DMB NSHST/ISHST mixed ... might cause deadlock"
+       depends on CPU_V7
+       help
+         This option enables the workaround for the 825619 Cortex-A12
+         (all revs) erratum. Within rare timing constraints, executing a
+         DMB NSHST or DMB ISHST instruction followed by a mix of Cacheable
+         and Device/Strongly-Ordered loads and stores might cause deadlock
+
+config ARM_ERRATA_852421
+       bool "ARM errata: A17: DMB ST might fail to create order between stores"
+       depends on CPU_V7
+       help
+         This option enables the workaround for the 852421 Cortex-A17
+         (r1p0, r1p1, r1p2) erratum. Under very rare timing conditions,
+         execution of a DMB ST instruction might fail to properly order
+         stores from GroupA and stores from GroupB.
+
+config ARM_ERRATA_852423
+       bool "ARM errata: A17: some seqs of opposed cond code instrs => deadlock or corruption"
+       depends on CPU_V7
+       help
+         This option enables the workaround for:
+         - Cortex-A17 852423: Execution of a sequence of instructions might
+           lead to either a data corruption or a CPU deadlock.  Not fixed in
+           any Cortex-A17 cores yet.
+         This is identical to Cortex-A12 erratum 852422.  It is a separate
+         config option from the A12 erratum due to the way errata are checked
+         for and handled.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
index 274e8a6582f1cd671731d1acbdda6f0f49c358c8..229afaf2058ba4229a8986ba0e4afb1151403431 100644 (file)
@@ -327,6 +327,7 @@ zImage: Image
 
 $(BOOT_TARGETS): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+       @$(kecho) '  Kernel: $(boot)/$@ is ready'
 
 $(INSTALL_TARGETS):
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
index 5be33a2d59a9d8c685d40e9a4084de8bf374bdb5..bdc1d5af03d2de1d8e35c9dab9d164fb4d006997 100644 (file)
@@ -31,7 +31,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
        $(call if_changed,objcopy)
-       @$(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+       @$(kecho) '  Physical Address of xipImage: $(CONFIG_XIP_PHYS_ADDR)'
 
 $(obj)/Image $(obj)/zImage: FORCE
        @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -46,14 +46,12 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
-       @$(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
-       @$(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -78,14 +76,12 @@ fi
 $(obj)/uImage: $(obj)/zImage FORCE
        @$(check_for_multiple_loadaddr)
        $(call if_changed,uimage)
-       @$(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
        $(Q)$(MAKE) $(build)=$(obj)/bootp $@
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
-       @$(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd install zinstall uinstall
 initrd:
index b2bc8e11471d3ee3e4fcd5f207406222ffa04bf1..4eaea2173bf81e84d47f0453299a538b08d08e87 100644 (file)
@@ -480,13 +480,13 @@ THUMB(    orr     \reg , \reg , #PSR_T_BIT        )
        .macro  uaccess_save, tmp
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
        mrc     p15, 0, \tmp, c3, c0, 0
-       str     \tmp, [sp, #S_FRAME_SIZE]
+       str     \tmp, [sp, #SVC_DACR]
 #endif
        .endm
 
        .macro  uaccess_restore
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
-       ldr     r0, [sp, #S_FRAME_SIZE]
+       ldr     r0, [sp, #SVC_DACR]
        mcr     p15, 0, r0, c3, c0, 0
 #endif
        .endm
index 112cc1a5d47f2ccac216d568e7ba30e2c0eaa8e0..f5d698182d5002179ecb4b5d2a81cc9dd0d23237 100644 (file)
@@ -44,9 +44,7 @@ extern void arm_heavy_mb(void);
 #define __arm_heavy_mb(x...) dsb(x)
 #endif
 
-#ifdef CONFIG_ARCH_HAS_BARRIERS
-#include <mach/barriers.h>
-#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
+#if defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
 #define mb()           __arm_heavy_mb()
 #define rmb()          dsb()
 #define wmb()          __arm_heavy_mb(st)
index dff714d886d58dbdce93a468e6a098cf45db98f6..b7a4281543556cfb82f716e0fc0337dae363187c 100644 (file)
@@ -10,8 +10,8 @@
 #include <asm/param.h> /* HZ */
 
 #define MAX_UDELAY_MS  2
-#define UDELAY_MULT    ((UL(2199023) * HZ) >> 11)
-#define UDELAY_SHIFT   30
+#define UDELAY_MULT    UL(2047 * HZ + 483648 * HZ / 1000000)
+#define UDELAY_SHIFT   31
 
 #ifndef __ASSEMBLY__
 
@@ -34,7 +34,7 @@ extern struct arm_delay_ops {
  * it, it means that you're calling udelay() with an out of range value.
  *
  * With currently imposed limits, this means that we support a max delay
- * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
+ * of 2000us. Further limits: HZ<=1000
  */
 extern void __bad_udelay(void);
 
index f4882553fbb0125927776c0f3a032625937649c6..85a34cc8316ace1b906347fc1de1e79adbd0cb02 100644 (file)
@@ -17,7 +17,7 @@
 
 #define fd_outb(val,port)                      \
        do {                                    \
-               if ((port) == FD_DOR)           \
+               if ((port) == (u32)FD_DOR)      \
                        fd_setdor((val));       \
                else                            \
                        outb((val),(port));     \
index 51622ba7c4a66a91494ecc49be4520fd4b14df88..e9c9a117bd25d5b69e8ba5313990f18f8db7311d 100644 (file)
 #include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
+#include <linux/types.h>
+
 struct pt_regs {
        unsigned long uregs[18];
 };
 
+struct svc_pt_regs {
+       struct pt_regs regs;
+       u32 dacr;
+       u32 addr_limit;
+};
+
+#define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)
+
 #define user_mode(regs)        \
        (((regs)->ARM_cpsr & 0xf) == 0)
 
index 35c9db857ebe9c7d53715ec42518a6e9fbe1dc6e..62a6f65029e61aebf9b64e1df59fb9383f4064a9 100644 (file)
@@ -104,14 +104,6 @@ static inline void set_fs(mm_segment_t fs)
 
 #define segment_eq(a, b)       ((a) == (b))
 
-#define __addr_ok(addr) ({ \
-       unsigned long flag; \
-       __asm__("cmp %2, %0; movlo %0, #0" \
-               : "=&r" (flag) \
-               : "0" (current_thread_info()->addr_limit), "r" (addr) \
-               : "cc"); \
-       (flag == 0); })
-
 /* We use 33-bit arithmetic here... */
 #define __range_ok(addr, size) ({ \
        unsigned long flag, roksum; \
@@ -238,49 +230,23 @@ extern int __put_user_2(void *, unsigned int);
 extern int __put_user_4(void *, unsigned int);
 extern int __put_user_8(void *, unsigned long long);
 
-#define __put_user_x(__r2, __p, __e, __l, __s)                         \
-          __asm__ __volatile__ (                                       \
-               __asmeq("%0", "r0") __asmeq("%2", "r2")                 \
-               __asmeq("%3", "r1")                                     \
-               "bl     __put_user_" #__s                               \
-               : "=&r" (__e)                                           \
-               : "0" (__p), "r" (__r2), "r" (__l)                      \
-               : "ip", "lr", "cc")
-
-#define __put_user_check(x, p)                                         \
+#define __put_user_check(__pu_val, __ptr, __err, __s)                  \
        ({                                                              \
                unsigned long __limit = current_thread_info()->addr_limit - 1; \
-               const typeof(*(p)) __user *__tmp_p = (p);               \
-               register const typeof(*(p)) __r2 asm("r2") = (x);       \
-               register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
+               register typeof(__pu_val) __r2 asm("r2") = __pu_val;    \
+               register const void __user *__p asm("r0") = __ptr;      \
                register unsigned long __l asm("r1") = __limit;         \
                register int __e asm("r0");                             \
-               unsigned int __ua_flags = uaccess_save_and_enable();    \
-               switch (sizeof(*(__p))) {                               \
-               case 1:                                                 \
-                       __put_user_x(__r2, __p, __e, __l, 1);           \
-                       break;                                          \
-               case 2:                                                 \
-                       __put_user_x(__r2, __p, __e, __l, 2);           \
-                       break;                                          \
-               case 4:                                                 \
-                       __put_user_x(__r2, __p, __e, __l, 4);           \
-                       break;                                          \
-               case 8:                                                 \
-                       __put_user_x(__r2, __p, __e, __l, 8);           \
-                       break;                                          \
-               default: __e = __put_user_bad(); break;                 \
-               }                                                       \
-               uaccess_restore(__ua_flags);                            \
-               __e;                                                    \
+               __asm__ __volatile__ (                                  \
+                       __asmeq("%0", "r0") __asmeq("%2", "r2")         \
+                       __asmeq("%3", "r1")                             \
+                       "bl     __put_user_" #__s                       \
+                       : "=&r" (__e)                                   \
+                       : "0" (__p), "r" (__r2), "r" (__l)              \
+                       : "ip", "lr", "cc");                            \
+               __err = __e;                                            \
        })
 
-#define put_user(x, p)                                                 \
-       ({                                                              \
-               might_fault();                                          \
-               __put_user_check(x, p);                                 \
-        })
-
 #else /* CONFIG_MMU */
 
 /*
@@ -298,7 +264,7 @@ static inline void set_fs(mm_segment_t fs)
 }
 
 #define get_user(x, p) __get_user(x, p)
-#define put_user(x, p) __put_user(x, p)
+#define __put_user_check __put_user_nocheck
 
 #endif /* CONFIG_MMU */
 
@@ -389,36 +355,54 @@ do {                                                                      \
 #define __get_user_asm_word(x, addr, err)                      \
        __get_user_asm(x, addr, err, ldr)
 
+
+#define __put_user_switch(x, ptr, __err, __fn)                         \
+       do {                                                            \
+               const __typeof__(*(ptr)) __user *__pu_ptr = (ptr);      \
+               __typeof__(*(ptr)) __pu_val = (x);                      \
+               unsigned int __ua_flags;                                \
+               might_fault();                                          \
+               __ua_flags = uaccess_save_and_enable();                 \
+               switch (sizeof(*(ptr))) {                               \
+               case 1: __fn(__pu_val, __pu_ptr, __err, 1); break;      \
+               case 2: __fn(__pu_val, __pu_ptr, __err, 2); break;      \
+               case 4: __fn(__pu_val, __pu_ptr, __err, 4); break;      \
+               case 8: __fn(__pu_val, __pu_ptr, __err, 8); break;      \
+               default: __err = __put_user_bad(); break;               \
+               }                                                       \
+               uaccess_restore(__ua_flags);                            \
+       } while (0)
+
+#define put_user(x, ptr)                                               \
+({                                                                     \
+       int __pu_err = 0;                                               \
+       __put_user_switch((x), (ptr), __pu_err, __put_user_check);      \
+       __pu_err;                                                       \
+})
+
 #define __put_user(x, ptr)                                             \
 ({                                                                     \
        long __pu_err = 0;                                              \
-       __put_user_err((x), (ptr), __pu_err);                           \
+       __put_user_switch((x), (ptr), __pu_err, __put_user_nocheck);    \
        __pu_err;                                                       \
 })
 
 #define __put_user_error(x, ptr, err)                                  \
 ({                                                                     \
-       __put_user_err((x), (ptr), err);                                \
+       __put_user_switch((x), (ptr), (err), __put_user_nocheck);       \
        (void) 0;                                                       \
 })
 
-#define __put_user_err(x, ptr, err)                                    \
-do {                                                                   \
-       unsigned long __pu_addr = (unsigned long)(ptr);                 \
-       unsigned int __ua_flags;                                        \
-       __typeof__(*(ptr)) __pu_val = (x);                              \
-       __chk_user_ptr(ptr);                                            \
-       might_fault();                                                  \
-       __ua_flags = uaccess_save_and_enable();                         \
-       switch (sizeof(*(ptr))) {                                       \
-       case 1: __put_user_asm_byte(__pu_val, __pu_addr, err);  break;  \
-       case 2: __put_user_asm_half(__pu_val, __pu_addr, err);  break;  \
-       case 4: __put_user_asm_word(__pu_val, __pu_addr, err);  break;  \
-       case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break;  \
-       default: __put_user_bad();                                      \
-       }                                                               \
-       uaccess_restore(__ua_flags);                                    \
-} while (0)
+#define __put_user_nocheck(x, __pu_ptr, __err, __size)                 \
+       do {                                                            \
+               unsigned long __pu_addr = (unsigned long)__pu_ptr;      \
+               __put_user_nocheck_##__size(x, __pu_addr, __err);       \
+       } while (0)
+
+#define __put_user_nocheck_1 __put_user_asm_byte
+#define __put_user_nocheck_2 __put_user_asm_half
+#define __put_user_nocheck_4 __put_user_asm_word
+#define __put_user_nocheck_8 __put_user_asm_dword
 
 #define __put_user_asm(x, __pu_addr, err, instr)               \
        __asm__ __volatile__(                                   \
index 27d05813ff09c09d167a27b2c790bf1ba0135ba5..608008229c7db6881f8d103750153280d96105d7 100644 (file)
@@ -107,7 +107,10 @@ int main(void)
   DEFINE(S_PC,                 offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,                        offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,             offsetof(struct pt_regs, ARM_ORIG_r0));
-  DEFINE(S_FRAME_SIZE,         sizeof(struct pt_regs));
+  DEFINE(PT_REGS_SIZE,         sizeof(struct pt_regs));
+  DEFINE(SVC_DACR,             offsetof(struct svc_pt_regs, dacr));
+  DEFINE(SVC_ADDR_LIMIT,       offsetof(struct svc_pt_regs, addr_limit));
+  DEFINE(SVC_REGS_SIZE,                sizeof(struct svc_pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
   DEFINE(L2X0_R_PHY_BASE,      offsetof(struct l2x0_regs, phy_base));
index a44b268e12e1a2acbc1990afc8b5c2c65512256f..7dccc964d75f2fff2bdbfa89c4b3d0cc7bb92e61 100644 (file)
@@ -47,18 +47,13 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
  * This function calls the underlying arch specific low level PM code as
  * registered at the init time.
  *
- * Returns -EOPNOTSUPP if no suspend callback is defined, the result of the
- * callback otherwise.
+ * Returns the result of the suspend callback.
  */
 int arm_cpuidle_suspend(int index)
 {
-       int ret = -EOPNOTSUPP;
        int cpu = smp_processor_id();
 
-       if (cpuidle_ops[cpu].suspend)
-               ret = cpuidle_ops[cpu].suspend(index);
-
-       return ret;
+       return cpuidle_ops[cpu].suspend(index);
 }
 
 /**
@@ -92,7 +87,8 @@ static const struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
  * process.
  *
  * Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if
- * no cpuidle_ops is registered for the 'enable-method'.
+ * no cpuidle_ops is registered for the 'enable-method', or if either init or
+ * suspend callback isn't defined.
  */
 static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
 {
@@ -110,6 +106,12 @@ static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
                return -EOPNOTSUPP;
        }
 
+       if (!ops->init || !ops->suspend) {
+               pr_warn("cpuidle_ops '%s': no init or suspend callback\n",
+                       enable_method);
+               return -EOPNOTSUPP;
+       }
+
        cpuidle_ops[cpu] = *ops; /* structure copy */
 
        pr_notice("cpuidle: enable-method property '%s'"
@@ -129,7 +131,8 @@ static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
  * Returns:
  *  0 on success,
  *  -ENODEV if it fails to find the cpu node in the device tree,
- *  -EOPNOTSUPP if it does not find a registered cpuidle_ops for this cpu,
+ *  -EOPNOTSUPP if it does not find a registered and valid cpuidle_ops for
+ *  this cpu,
  *  -ENOENT if it fails to find an 'enable-method' property,
  *  -ENXIO if the HW reports a failure or a misconfiguration,
  *  -ENOMEM if the HW report an memory allocation failure 
@@ -143,7 +146,7 @@ int __init arm_cpuidle_init(int cpu)
                return -ENODEV;
 
        ret = arm_cpuidle_read_ops(cpu_node, cpu);
-       if (!ret && cpuidle_ops[cpu].init)
+       if (!ret)
                ret = cpuidle_ops[cpu].init(cpu_node, cpu);
 
        of_node_put(cpu_node);
index 2e26016a91a57116b9956973a19bb4aba723fc04..40ecd5f514a2217181781cbc66ab5e1ca26efa90 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/cputype.h>
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/prom.h>
 #include <asm/smp_plat.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -213,6 +214,8 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 
 #if defined(CONFIG_ARCH_MULTIPLATFORM) || defined(CONFIG_ARM_SINGLE_ARMV7M)
        DT_MACHINE_START(GENERIC_DT, "Generic DT based system")
+               .l2c_aux_val = 0x0,
+               .l2c_aux_mask = ~0x0,
        MACHINE_END
 
        mdesc_best = &__mach_desc_GENERIC_DT;
index e2550500486d497c8455165b37916f2eb4974cd5..bc5f50799d75627fb3eb22b9afe6d849373e77d4 100644 (file)
@@ -92,7 +92,7 @@
  * Invalid mode handlers
  */
        .macro  inv_entry, reason
-       sub     sp, sp, #S_FRAME_SIZE
+       sub     sp, sp, #PT_REGS_SIZE
  ARM(  stmib   sp, {r1 - lr}           )
  THUMB(        stmia   sp, {r0 - r12}          )
  THUMB(        str     sp, [sp, #S_SP]         )
@@ -152,7 +152,7 @@ ENDPROC(__und_invalid)
        .macro  svc_entry, stack_hole=0, trace=1, uaccess=1
  UNWIND(.fnstart               )
  UNWIND(.save {r0 - pc}                )
-       sub     sp, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
+       sub     sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4)
 #ifdef CONFIG_THUMB2_KERNEL
  SPFIX(        str     r0, [sp]        )       @ temporarily saved
  SPFIX(        mov     r0, sp          )
@@ -167,7 +167,7 @@ ENDPROC(__und_invalid)
        ldmia   r0, {r3 - r5}
        add     r7, sp, #S_SP - 4       @ here for interlock avoidance
        mov     r6, #-1                 @  ""  ""      ""       ""
-       add     r2, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
+       add     r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4)
  SPFIX(        addeq   r2, r2, #4      )
        str     r3, [sp, #-4]!          @ save the "real" r0 copied
                                        @ from the exception stack
@@ -185,6 +185,12 @@ ENDPROC(__und_invalid)
        @
        stmia   r7, {r2 - r6}
 
+       get_thread_info tsk
+       ldr     r0, [tsk, #TI_ADDR_LIMIT]
+       mov     r1, #TASK_SIZE
+       str     r1, [tsk, #TI_ADDR_LIMIT]
+       str     r0, [sp, #SVC_ADDR_LIMIT]
+
        uaccess_save r0
        .if \uaccess
        uaccess_disable r0
@@ -213,7 +219,6 @@ __irq_svc:
        irq_handler
 
 #ifdef CONFIG_PREEMPT
-       get_thread_info tsk
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
        ldr     r0, [tsk, #TI_FLAGS]            @ get flags
        teq     r8, #0                          @ if preempt count != 0
@@ -366,17 +371,17 @@ ENDPROC(__fiq_abt)
 /*
  * User mode handlers
  *
- * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
+ * EABI note: sp_svc is always 64-bit aligned here, so should PT_REGS_SIZE
  */
 
-#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (PT_REGS_SIZE & 7)
 #error "sizeof(struct pt_regs) must be a multiple of 8"
 #endif
 
        .macro  usr_entry, trace=1, uaccess=1
  UNWIND(.fnstart       )
  UNWIND(.cantunwind    )       @ don't unwind the user space
-       sub     sp, sp, #S_FRAME_SIZE
+       sub     sp, sp, #PT_REGS_SIZE
  ARM(  stmib   sp, {r1 - r12}  )
  THUMB(        stmia   sp, {r0 - r12}  )
 
index 30a7228eaceba758fb368f9ef16511019b1cb5c5..10c3283d6c196b85bcab35264f80851eddcf0663 100644 (file)
@@ -145,7 +145,7 @@ ENTRY(vector_swi)
 #ifdef CONFIG_CPU_V7M
        v7m_exception_entry
 #else
-       sub     sp, sp, #S_FRAME_SIZE
+       sub     sp, sp, #PT_REGS_SIZE
        stmia   sp, {r0 - r12}                  @ Calling r0 - r12
  ARM(  add     r8, sp, #S_PC           )
  ARM(  stmdb   r8, {sp, lr}^           )       @ Calling sp, lr
index 0d22ad206d5230ba05a40b4101bb1dd2e4addd10..6391728c8f0377019404c6a6744df1e24697b3a8 100644 (file)
@@ -90,7 +90,7 @@
        @ Linux expects to have irqs off. Do it here before taking stack space
        cpsid   i
 
-       sub     sp, #S_FRAME_SIZE-S_IP
+       sub     sp, #PT_REGS_SIZE-S_IP
        stmdb   sp!, {r0-r11}
 
        @ load saved r12, lr, return address and xPSR.
        ldmia   sp!, {r0-r11}
 
        @ restore main sp
-       add     sp, sp, #S_FRAME_SIZE-S_IP
+       add     sp, sp, #PT_REGS_SIZE-S_IP
 
        cpsie   i
        bx      lr
        blne    trace_hardirqs_off
 #endif
        .endif
+       ldr     r1, [sp, #SVC_ADDR_LIMIT]
        uaccess_restore
+       str     r1, [tsk, #TI_ADDR_LIMIT]
 
 #ifndef CONFIG_THUMB2_KERNEL
        @ ARM mode SVC restore
        @ on the stack remains correct).
        @
        .macro  svc_exit_via_fiq
+       ldr     r1, [sp, #SVC_ADDR_LIMIT]
        uaccess_restore
+       str     r1, [tsk, #TI_ADDR_LIMIT]
 #ifndef CONFIG_THUMB2_KERNEL
        @ ARM mode restore
        mov     r0, sp
        .endif
        mov     r0, r0                          @ ARMv5T and earlier require a nop
                                                @ after ldm {}^
-       add     sp, sp, #\offset + S_FRAME_SIZE
+       add     sp, sp, #\offset + PT_REGS_SIZE
        movs    pc, lr                          @ return & move spsr_svc into cpsr
 #elif defined(CONFIG_CPU_V7M)
        @ V7M restore.
        .else
        ldmdb   sp, {r0 - r12}                  @ get calling r0 - r12
        .endif
-       add     sp, sp, #S_FRAME_SIZE - S_SP
+       add     sp, sp, #PT_REGS_SIZE - S_SP
        movs    pc, lr                          @ return & move spsr_svc into cpsr
 #endif /* !CONFIG_THUMB2_KERNEL */
        .endm
index 907534f97053abbc32b667ff43df88dc93c08fb7..abcf4784852593397daf3b1e6cf5d70cf47660e0 100644 (file)
@@ -73,7 +73,7 @@ __irq_entry:
        @ correctness they don't need to be restored. So only r8-r11 must be
        @ restored here. The easiest way to do so is to restore r0-r7, too.
        ldmia   sp!, {r0-r11}
-       add     sp, #S_FRAME_SIZE-S_IP
+       add     sp, #PT_REGS_SIZE-S_IP
        cpsie   i
        bx      lr
 ENDPROC(__irq_entry)
index 4a803c5a1ff7276859b823a7b9b02dc24ee6e564..612eb530f33fcd19bc4539facb26fc30a2583979 100644 (file)
@@ -96,19 +96,23 @@ void __show_regs(struct pt_regs *regs)
        unsigned long flags;
        char buf[64];
 #ifndef CONFIG_CPU_V7M
-       unsigned int domain;
+       unsigned int domain, fs;
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
        /*
         * Get the domain register for the parent context. In user
         * mode, we don't save the DACR, so lets use what it should
         * be. For other modes, we place it after the pt_regs struct.
         */
-       if (user_mode(regs))
+       if (user_mode(regs)) {
                domain = DACR_UACCESS_ENABLE;
-       else
-               domain = *(unsigned int *)(regs + 1);
+               fs = get_fs();
+       } else {
+               domain = to_svc_pt_regs(regs)->dacr;
+               fs = to_svc_pt_regs(regs)->addr_limit;
+       }
 #else
        domain = get_domain();
+       fs = get_fs();
 #endif
 #endif
 
@@ -144,7 +148,7 @@ void __show_regs(struct pt_regs *regs)
                if ((domain & domain_mask(DOMAIN_USER)) ==
                    domain_val(DOMAIN_USER, DOMAIN_NOACCESS))
                        segment = "none";
-               else if (get_fs() == get_ds())
+               else if (fs == get_ds())
                        segment = "kernel";
                else
                        segment = "user";
index 261dae6f3fece20d58cecaaf5618ee9aa70b3fce..85a0bcb1f7ca59704f47f10d8c4bb359fd655513 100644 (file)
@@ -844,7 +844,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
        struct resource *res;
 
        kernel_code.start   = virt_to_phys(_text);
-       kernel_code.end     = virt_to_phys(_etext - 1);
+       kernel_code.end     = virt_to_phys(__init_begin - 1);
        kernel_data.start   = virt_to_phys(_sdata);
        kernel_data.end     = virt_to_phys(_end - 1);
 
index 2e72be4f623e22284f8b0ae1c441b30b867e7c0c..22313cb5336257cffa870b15e21279a1b4684e99 100644 (file)
@@ -93,17 +93,53 @@ void erratum_a15_798181_init(void)
        unsigned int revidr = read_cpuid(CPUID_REVIDR);
 
        /* Brahma-B15 r0p0..r0p2 affected
-        * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
-       if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
+        * Cortex-A15 r0p0..r3p3 w/o ECO fix affected
+        * Fixes applied to A15 with respect to the revision and revidr are:
+        *
+        * r0p0-r2p1: No fixes applied
+        * r2p2,r2p3:
+        *      REVIDR[4]: 798181 Moving a virtual page that is being accessed
+        *                 by an active process can lead to unexpected behavior
+        *      REVIDR[9]: Not defined
+        * r2p4,r3p0,r3p1,r3p2:
+        *      REVIDR[4]: 798181 Moving a virtual page that is being accessed
+        *                 by an active process can lead to unexpected behavior
+        *      REVIDR[9]: 798181 Moving a virtual page that is being accessed
+        *                 by an active process can lead to unexpected behavior
+        *                 - This is an update to a previously released ECO.
+        * r3p3:
+        *      REVIDR[4]: Reserved
+        *      REVIDR[9]: 798181 Moving a virtual page that is being accessed
+        *                 by an active process can lead to unexpected behavior
+        *                 - This is an update to a previously released ECO.
+        *
+        * Handling:
+        *      REVIDR[9] set -> No WA
+        *      REVIDR[4] set, REVIDR[9] cleared -> Partial WA
+        *      Both cleared -> Full WA
+        */
+       if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2) {
                erratum_a15_798181_handler = erratum_a15_798181_broadcast;
-       else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
-                (revidr & 0x210) != 0x210) {
+       } else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f2) {
+               erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+       } else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f4) {
                if (revidr & 0x10)
                        erratum_a15_798181_handler =
                                erratum_a15_798181_partial;
                else
                        erratum_a15_798181_handler =
                                erratum_a15_798181_broadcast;
+       } else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x413fc0f3) {
+               if ((revidr & 0x210) == 0)
+                       erratum_a15_798181_handler =
+                               erratum_a15_798181_broadcast;
+               else if (revidr & 0x10)
+                       erratum_a15_798181_handler =
+                               erratum_a15_798181_partial;
+       } else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x414fc0f0) {
+               if ((revidr & 0x200) == 0)
+                       erratum_a15_798181_handler =
+                               erratum_a15_798181_partial;
        }
 }
 #endif
index e2c6da096cefa491669ae8b4464b89f6df5f0a75..99420fc1f066796fdec9ea5a473a0d893647379b 100644 (file)
@@ -125,6 +125,8 @@ SECTIONS
 #ifdef CONFIG_DEBUG_ALIGN_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
 #endif
+       _etext = .;                     /* End of text section */
+
        RO_DATA(PAGE_SIZE)
 
        . = ALIGN(4);
@@ -155,8 +157,6 @@ SECTIONS
 
        NOTES
 
-       _etext = .;                     /* End of text and rodata section */
-
 #ifdef CONFIG_DEBUG_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
 #else
index d8a780799506b59bc2edd3f6a513021bcb45ebc0..27f4d96258a2e66193d6a3701bb4cf9a44399aad 100644 (file)
@@ -29,7 +29,10 @@ else
   lib-y        += io-readsw-armv4.o io-writesw-armv4.o
 endif
 
-lib-$(CONFIG_ARCH_RPC)         += ecard.o io-acorn.o floppydma.o
+ifeq ($(CONFIG_ARCH_RPC),y)
+  lib-y                                += ecard.o io-acorn.o floppydma.o
+  AFLAGS_delay-loop.o          += -march=armv4
+endif
 
 $(obj)/csumpartialcopy.o:      $(obj)/csumpartialcopygeneric.S
 $(obj)/csumpartialcopyuser.o:  $(obj)/csumpartialcopygeneric.S
index 518bf6e93f78a2cb1c74f7b857c6fa96b1018f53..792c59d885bc9d8274eaef7ea8c3a68539d9dc0a 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/delay.h>
+
                .text
 
 .LC0:          .word   loops_per_jiffy
@@ -17,7 +18,6 @@
 
 /*
  * r0  <= 2000
- * lpj <= 0x01ffffff (max. 3355 bogomips)
  * HZ  <= 1000
  */
 
@@ -25,16 +25,11 @@ ENTRY(__loop_udelay)
                ldr     r2, .LC1
                mul     r0, r2, r0
 ENTRY(__loop_const_udelay)                     @ 0 <= r0 <= 0x7fffff06
-               mov     r1, #-1
                ldr     r2, .LC0
-               ldr     r2, [r2]                @ max = 0x01ffffff
-               add     r0, r0, r1, lsr #32-14
-               mov     r0, r0, lsr #14         @ max = 0x0001ffff
-               add     r2, r2, r1, lsr #32-10
-               mov     r2, r2, lsr #10         @ max = 0x00007fff
-               mul     r0, r2, r0              @ max = 2^32-1
-               add     r0, r0, r1, lsr #32-6
-               movs    r0, r0, lsr #6
+               ldr     r2, [r2]
+               umull   r1, r0, r2, r0
+               adds    r1, r1, #0xffffffff
+               adcs    r0, r0, r0
                reteq   lr
 
 /*
index cb569b65a54ddcdaa8cce08d047799a24ba75f4b..d15a7fe51618ad70da5de7cf05408f882c6a4076 100644 (file)
@@ -1025,12 +1025,6 @@ config ARM_DMA_MEM_BUFFERABLE
 
          You are recommended say 'Y' here and debug any affected drivers.
 
-config ARCH_HAS_BARRIERS
-       bool
-       help
-         This option allows the use of custom mandatory barriers
-         included via the mach/barriers.h file.
-
 config ARM_HEAVY_MB
        bool
 
index ff7ed5697d3e4b67ba1691dded0f79029ec8f921..b7eed75960febac3fbc1103d09487e72f04564f5 100644 (file)
@@ -49,6 +49,7 @@ struct arm_dma_alloc_args {
        pgprot_t prot;
        const void *caller;
        bool want_vaddr;
+       int coherent_flag;
 };
 
 struct arm_dma_free_args {
@@ -59,6 +60,9 @@ struct arm_dma_free_args {
        bool want_vaddr;
 };
 
+#define NORMAL     0
+#define COHERENT    1
+
 struct arm_dma_allocator {
        void *(*alloc)(struct arm_dma_alloc_args *args,
                       struct page **ret_page);
@@ -272,7 +276,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
        return mask;
 }
 
-static void __dma_clear_buffer(struct page *page, size_t size)
+static void __dma_clear_buffer(struct page *page, size_t size, int coherent_flag)
 {
        /*
         * Ensure that the allocated pages are zeroed, and that any data
@@ -284,17 +288,21 @@ static void __dma_clear_buffer(struct page *page, size_t size)
                while (size > 0) {
                        void *ptr = kmap_atomic(page);
                        memset(ptr, 0, PAGE_SIZE);
-                       dmac_flush_range(ptr, ptr + PAGE_SIZE);
+                       if (coherent_flag != COHERENT)
+                               dmac_flush_range(ptr, ptr + PAGE_SIZE);
                        kunmap_atomic(ptr);
                        page++;
                        size -= PAGE_SIZE;
                }
-               outer_flush_range(base, end);
+               if (coherent_flag != COHERENT)
+                       outer_flush_range(base, end);
        } else {
                void *ptr = page_address(page);
                memset(ptr, 0, size);
-               dmac_flush_range(ptr, ptr + size);
-               outer_flush_range(__pa(ptr), __pa(ptr) + size);
+               if (coherent_flag != COHERENT) {
+                       dmac_flush_range(ptr, ptr + size);
+                       outer_flush_range(__pa(ptr), __pa(ptr) + size);
+               }
        }
 }
 
@@ -302,7 +310,8 @@ static void __dma_clear_buffer(struct page *page, size_t size)
  * Allocate a DMA buffer for 'dev' of size 'size' using the
  * specified gfp mask.  Note that 'size' must be page aligned.
  */
-static struct page *__dma_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
+static struct page *__dma_alloc_buffer(struct device *dev, size_t size,
+                                      gfp_t gfp, int coherent_flag)
 {
        unsigned long order = get_order(size);
        struct page *page, *p, *e;
@@ -318,7 +327,7 @@ static struct page *__dma_alloc_buffer(struct device *dev, size_t size, gfp_t gf
        for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++)
                __free_page(p);
 
-       __dma_clear_buffer(page, size);
+       __dma_clear_buffer(page, size, coherent_flag);
 
        return page;
 }
@@ -340,7 +349,8 @@ static void __dma_free_buffer(struct page *page, size_t size)
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
                                     pgprot_t prot, struct page **ret_page,
-                                    const void *caller, bool want_vaddr);
+                                    const void *caller, bool want_vaddr,
+                                    int coherent_flag);
 
 static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
                                 pgprot_t prot, struct page **ret_page,
@@ -405,10 +415,13 @@ static int __init atomic_pool_init(void)
        atomic_pool = gen_pool_create(PAGE_SHIFT, -1);
        if (!atomic_pool)
                goto out;
-
+       /*
+        * The atomic pool is only used for non-coherent allocations
+        * so we must pass NORMAL for coherent_flag.
+        */
        if (dev_get_cma_area(NULL))
                ptr = __alloc_from_contiguous(NULL, atomic_pool_size, prot,
-                                             &page, atomic_pool_init, true);
+                                     &page, atomic_pool_init, true, NORMAL);
        else
                ptr = __alloc_remap_buffer(NULL, atomic_pool_size, gfp, prot,
                                           &page, atomic_pool_init, true);
@@ -522,7 +535,11 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
 {
        struct page *page;
        void *ptr = NULL;
-       page = __dma_alloc_buffer(dev, size, gfp);
+       /*
+        * __alloc_remap_buffer is only called when the device is
+        * non-coherent
+        */
+       page = __dma_alloc_buffer(dev, size, gfp, NORMAL);
        if (!page)
                return NULL;
        if (!want_vaddr)
@@ -577,7 +594,8 @@ static int __free_from_pool(void *start, size_t size)
 
 static void *__alloc_from_contiguous(struct device *dev, size_t size,
                                     pgprot_t prot, struct page **ret_page,
-                                    const void *caller, bool want_vaddr)
+                                    const void *caller, bool want_vaddr,
+                                    int coherent_flag)
 {
        unsigned long order = get_order(size);
        size_t count = size >> PAGE_SHIFT;
@@ -588,7 +606,7 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size,
        if (!page)
                return NULL;
 
-       __dma_clear_buffer(page, size);
+       __dma_clear_buffer(page, size, coherent_flag);
 
        if (!want_vaddr)
                goto out;
@@ -638,7 +656,7 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
 #define __get_dma_pgprot(attrs, prot)                          __pgprot(0)
 #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv) NULL
 #define __alloc_from_pool(size, ret_page)                      NULL
-#define __alloc_from_contiguous(dev, size, prot, ret, c, wv)   NULL
+#define __alloc_from_contiguous(dev, size, prot, ret, c, wv, coherent_flag)    NULL
 #define __free_from_pool(cpu_addr, size)                       do { } while (0)
 #define __free_from_contiguous(dev, page, cpu_addr, size, wv)  do { } while (0)
 #define __dma_free_remap(cpu_addr, size)                       do { } while (0)
@@ -649,7 +667,8 @@ static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp,
                                   struct page **ret_page)
 {
        struct page *page;
-       page = __dma_alloc_buffer(dev, size, gfp);
+       /* __alloc_simple_buffer is only called when the device is coherent */
+       page = __dma_alloc_buffer(dev, size, gfp, COHERENT);
        if (!page)
                return NULL;
 
@@ -679,7 +698,7 @@ static void *cma_allocator_alloc(struct arm_dma_alloc_args *args,
 {
        return __alloc_from_contiguous(args->dev, args->size, args->prot,
                                       ret_page, args->caller,
-                                      args->want_vaddr);
+                                      args->want_vaddr, args->coherent_flag);
 }
 
 static void cma_allocator_free(struct arm_dma_free_args *args)
@@ -746,6 +765,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                .prot = prot,
                .caller = caller,
                .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+               .coherent_flag = is_coherent ? COHERENT : NORMAL,
        };
 
 #ifdef CONFIG_DMA_API_DEBUG
@@ -1253,7 +1273,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
 static const int iommu_order_array[] = { 9, 8, 4, 0 };
 
 static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
-                                         gfp_t gfp, struct dma_attrs *attrs)
+                                         gfp_t gfp, struct dma_attrs *attrs,
+                                         int coherent_flag)
 {
        struct page **pages;
        int count = size >> PAGE_SHIFT;
@@ -1277,7 +1298,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
                if (!page)
                        goto error;
 
-               __dma_clear_buffer(page, size);
+               __dma_clear_buffer(page, size, coherent_flag);
 
                for (i = 0; i < count; i++)
                        pages[i] = page + i;
@@ -1327,7 +1348,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
                                pages[i + j] = pages[i] + j;
                }
 
-               __dma_clear_buffer(pages[i], PAGE_SIZE << order);
+               __dma_clear_buffer(pages[i], PAGE_SIZE << order, coherent_flag);
                i += 1 << order;
                count -= 1 << order;
        }
@@ -1455,13 +1476,16 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
        return NULL;
 }
 
-static void *__iommu_alloc_atomic(struct device *dev, size_t size,
-                                 dma_addr_t *handle)
+static void *__iommu_alloc_simple(struct device *dev, size_t size, gfp_t gfp,
+                                 dma_addr_t *handle, int coherent_flag)
 {
        struct page *page;
        void *addr;
 
-       addr = __alloc_from_pool(size, &page);
+       if (coherent_flag  == COHERENT)
+               addr = __alloc_simple_buffer(dev, size, gfp, &page);
+       else
+               addr = __alloc_from_pool(size, &page);
        if (!addr)
                return NULL;
 
@@ -1477,14 +1501,18 @@ err_mapping:
 }
 
 static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
-                               dma_addr_t handle, size_t size)
+                       dma_addr_t handle, size_t size, int coherent_flag)
 {
        __iommu_remove_mapping(dev, handle, size);
-       __free_from_pool(cpu_addr, size);
+       if (coherent_flag == COHERENT)
+               __dma_free_buffer(virt_to_page(cpu_addr), size);
+       else
+               __free_from_pool(cpu_addr, size);
 }
 
-static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
-           dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size,
+           dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs,
+           int coherent_flag)
 {
        pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
        struct page **pages;
@@ -1493,8 +1521,9 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
-       if (!gfpflags_allow_blocking(gfp))
-               return __iommu_alloc_atomic(dev, size, handle);
+       if (coherent_flag  == COHERENT || !gfpflags_allow_blocking(gfp))
+               return __iommu_alloc_simple(dev, size, gfp, handle,
+                                           coherent_flag);
 
        /*
         * Following is a work-around (a.k.a. hack) to prevent pages
@@ -1505,7 +1534,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
         */
        gfp &= ~(__GFP_COMP);
 
-       pages = __iommu_alloc_buffer(dev, size, gfp, attrs);
+       pages = __iommu_alloc_buffer(dev, size, gfp, attrs, coherent_flag);
        if (!pages)
                return NULL;
 
@@ -1530,7 +1559,19 @@ err_buffer:
        return NULL;
 }
 
-static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
+static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
+                   dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+{
+       return __arm_iommu_alloc_attrs(dev, size, handle, gfp, attrs, NORMAL);
+}
+
+static void *arm_coherent_iommu_alloc_attrs(struct device *dev, size_t size,
+                   dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+{
+       return __arm_iommu_alloc_attrs(dev, size, handle, gfp, attrs, COHERENT);
+}
+
+static int __arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
                    void *cpu_addr, dma_addr_t dma_addr, size_t size,
                    struct dma_attrs *attrs)
 {
@@ -1540,8 +1581,6 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
        unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
        unsigned long off = vma->vm_pgoff;
 
-       vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
-
        if (!pages)
                return -ENXIO;
 
@@ -1562,19 +1601,34 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 
        return 0;
 }
+static int arm_iommu_mmap_attrs(struct device *dev,
+               struct vm_area_struct *vma, void *cpu_addr,
+               dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+{
+       vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
+
+       return __arm_iommu_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, attrs);
+}
+
+static int arm_coherent_iommu_mmap_attrs(struct device *dev,
+               struct vm_area_struct *vma, void *cpu_addr,
+               dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+{
+       return __arm_iommu_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, attrs);
+}
 
 /*
  * free a page as defined by the above mapping.
  * Must not be called with IRQs disabled.
  */
-void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-                         dma_addr_t handle, struct dma_attrs *attrs)
+void __arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
+       dma_addr_t handle, struct dma_attrs *attrs, int coherent_flag)
 {
        struct page **pages;
        size = PAGE_ALIGN(size);
 
-       if (__in_atomic_pool(cpu_addr, size)) {
-               __iommu_free_atomic(dev, cpu_addr, handle, size);
+       if (coherent_flag == COHERENT || __in_atomic_pool(cpu_addr, size)) {
+               __iommu_free_atomic(dev, cpu_addr, handle, size, coherent_flag);
                return;
        }
 
@@ -1593,6 +1647,18 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
        __iommu_free_buffer(dev, pages, size, attrs);
 }
 
+void arm_iommu_free_attrs(struct device *dev, size_t size,
+                   void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs)
+{
+       __arm_iommu_free_attrs(dev, size, cpu_addr, handle, attrs, NORMAL);
+}
+
+void arm_coherent_iommu_free_attrs(struct device *dev, size_t size,
+                   void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs)
+{
+       __arm_iommu_free_attrs(dev, size, cpu_addr, handle, attrs, COHERENT);
+}
+
 static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
                                 void *cpu_addr, dma_addr_t dma_addr,
                                 size_t size, struct dma_attrs *attrs)
@@ -1997,9 +2063,9 @@ struct dma_map_ops iommu_ops = {
 };
 
 struct dma_map_ops iommu_coherent_ops = {
-       .alloc          = arm_iommu_alloc_attrs,
-       .free           = arm_iommu_free_attrs,
-       .mmap           = arm_iommu_mmap_attrs,
+       .alloc          = arm_coherent_iommu_alloc_attrs,
+       .free           = arm_coherent_iommu_free_attrs,
+       .mmap           = arm_coherent_iommu_mmap_attrs,
        .get_sgtable    = arm_iommu_get_sgtable,
 
        .map_page       = arm_coherent_iommu_map_page,
index 6fcaac8e200f888e18207ae6cdfeca8adc000c5e..a7123b4e129dfc40f9c0d0df4417d086e23ee9a0 100644 (file)
@@ -362,6 +362,39 @@ __ca15_errata:
 #endif
        b       __errata_finish
 
+__ca12_errata:
+#ifdef CONFIG_ARM_ERRATA_818325_852422
+       mrc     p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orr     r10, r10, #1 << 12              @ set bit #12
+       mcr     p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_821420
+       mrc     p15, 0, r10, c15, c0, 2         @ read internal feature reg
+       orr     r10, r10, #1 << 1               @ set bit #1
+       mcr     p15, 0, r10, c15, c0, 2         @ write internal feature reg
+#endif
+#ifdef CONFIG_ARM_ERRATA_825619
+       mrc     p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orr     r10, r10, #1 << 24              @ set bit #24
+       mcr     p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
+       b       __errata_finish
+
+__ca17_errata:
+#ifdef CONFIG_ARM_ERRATA_852421
+       cmp     r6, #0x12                       @ only present up to r1p2
+       mrcle   p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orrle   r10, r10, #1 << 24              @ set bit #24
+       mcrle   p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
+#ifdef CONFIG_ARM_ERRATA_852423
+       cmp     r6, #0x12                       @ only present up to r1p2
+       mrcle   p15, 0, r10, c15, c0, 1         @ read diagnostic register
+       orrle   r10, r10, #1 << 12              @ set bit #12
+       mcrle   p15, 0, r10, c15, c0, 1         @ write diagnostic register
+#endif
+       b       __errata_finish
+
 __v7_pj4b_setup:
 #ifdef CONFIG_CPU_PJ4B
 
@@ -443,6 +476,16 @@ __v7_setup_cont:
        teq     r0, r10
        beq     __ca9_errata
 
+       /* Cortex-A12 Errata */
+       ldr     r10, =0x00000c0d                @ Cortex-A12 primary part number
+       teq     r0, r10
+       beq     __ca12_errata
+
+       /* Cortex-A17 Errata */
+       ldr     r10, =0x00000c0e                @ Cortex-A17 primary part number
+       teq     r0, r10
+       beq     __ca17_errata
+
        /* Cortex-A15 Errata */
        ldr     r10, =0x00000c0f                @ Cortex-A15 primary part number
        teq     r0, r10