From 47fd761b81a0c6729d4e833740d050f4e22e7184 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 1 Nov 2016 22:32:59 +0100 Subject: linux: update to 4.8.6, add realtime patch --- target/linux/config/Config.in.kernel | 6 +- target/linux/patches/4.1.35/patch-realtime | 11278 ++++---- target/linux/patches/4.8.5/crisv32.patch | 33 - .../patches/4.8.5/crisv32_ethernet_driver.patch | 4048 --- .../patches/4.8.5/initramfs-nosizelimit.patch | 57 - target/linux/patches/4.8.5/ld-or1k.patch | 12 - target/linux/patches/4.8.5/macsonic.patch | 11 - target/linux/patches/4.8.5/startup.patch | 34 - target/linux/patches/4.8.5/vdso2.patch | 27 - target/linux/patches/4.8.6/crisv32.patch | 33 + .../patches/4.8.6/crisv32_ethernet_driver.patch | 4048 +++ .../patches/4.8.6/initramfs-nosizelimit.patch | 57 + target/linux/patches/4.8.6/ld-or1k.patch | 12 + target/linux/patches/4.8.6/macsonic.patch | 11 + target/linux/patches/4.8.6/patch-realtime | 25908 +++++++++++++++++++ target/linux/patches/4.8.6/startup.patch | 34 + target/linux/patches/4.8.6/vdso2.patch | 27 + 17 files changed, 36516 insertions(+), 9120 deletions(-) delete mode 100644 target/linux/patches/4.8.5/crisv32.patch delete mode 100644 target/linux/patches/4.8.5/crisv32_ethernet_driver.patch delete mode 100644 target/linux/patches/4.8.5/initramfs-nosizelimit.patch delete mode 100644 target/linux/patches/4.8.5/ld-or1k.patch delete mode 100644 target/linux/patches/4.8.5/macsonic.patch delete mode 100644 target/linux/patches/4.8.5/startup.patch delete mode 100644 target/linux/patches/4.8.5/vdso2.patch create mode 100644 target/linux/patches/4.8.6/crisv32.patch create mode 100644 target/linux/patches/4.8.6/crisv32_ethernet_driver.patch create mode 100644 target/linux/patches/4.8.6/initramfs-nosizelimit.patch create mode 100644 target/linux/patches/4.8.6/ld-or1k.patch create mode 100644 target/linux/patches/4.8.6/macsonic.patch create mode 100644 target/linux/patches/4.8.6/patch-realtime create mode 100644 target/linux/patches/4.8.6/startup.patch create mode 100644 target/linux/patches/4.8.6/vdso2.patch (limited to 'target/linux') diff --git a/target/linux/config/Config.in.kernel b/target/linux/config/Config.in.kernel index 393b1628b..ad0e01819 100644 --- a/target/linux/config/Config.in.kernel +++ b/target/linux/config/Config.in.kernel @@ -146,7 +146,8 @@ config ADK_KERNEL_PREEMPT_RTB select ADK_KERNEL_PATCH_REALTIME depends on !ADK_KERNEL_OPROFILE depends on ADK_TARGET_KERNEL_VERSION_4_1 \ - || ADK_TARGET_KERNEL_VERSION_4_4 + || ADK_TARGET_KERNEL_VERSION_4_4 \ + || ADK_TARGET_KERNEL_VERSION_4_8 help Preemptible Kernel (Basic RT) @@ -156,7 +157,8 @@ config ADK_KERNEL_PREEMPT_RT_FULL select ADK_KERNEL_PATCH_REALTIME depends on !ADK_KERNEL_OPROFILE depends on ADK_TARGET_KERNEL_VERSION_4_1 \ - || ADK_TARGET_KERNEL_VERSION_4_4 + || ADK_TARGET_KERNEL_VERSION_4_4 \ + || ADK_TARGET_KERNEL_VERSION_4_8 help Fully Preemptible Kernel (RealTime) https://www.kernel.org/pub/linux/kernel/projects/rt/ diff --git a/target/linux/patches/4.1.35/patch-realtime b/target/linux/patches/4.1.35/patch-realtime index 6ecf019b9..94d6fe355 100644 --- a/target/linux/patches/4.1.35/patch-realtime +++ b/target/linux/patches/4.1.35/patch-realtime @@ -1,858 +1,990 @@ -diff -Nur linux-4.1.26.orig/arch/alpha/mm/fault.c linux-4.1.26/arch/alpha/mm/fault.c ---- linux-4.1.26.orig/arch/alpha/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/alpha/mm/fault.c 2016-06-19 15:30:54.915151887 +0200 -@@ -23,8 +23,7 @@ - #include - #include - #include -- --#include -+#include - - extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); - -@@ -107,7 +106,7 @@ - - /* If we're in an interrupt context, or have no user context, - we must not take the fault. */ -- if (!mm || in_atomic()) -+ if (!mm || faulthandler_disabled()) - goto no_context; - - #ifdef CONFIG_ALPHA_LARGE_VMALLOC -diff -Nur linux-4.1.26.orig/arch/arc/include/asm/futex.h linux-4.1.26/arch/arc/include/asm/futex.h ---- linux-4.1.26.orig/arch/arc/include/asm/futex.h 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arc/include/asm/futex.h 2016-06-19 15:30:54.915151887 +0200 -@@ -53,7 +53,7 @@ - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - -- pagefault_disable(); /* implies preempt_disable() */ -+ pagefault_disable(); - - switch (op) { - case FUTEX_OP_SET: -@@ -75,7 +75,7 @@ - ret = -ENOSYS; - } - -- pagefault_enable(); /* subsumes preempt_enable() */ -+ pagefault_enable(); - - if (!ret) { - switch (cmp) { -@@ -104,7 +104,7 @@ - return ret; - } - --/* Compare-xchg with preemption disabled. -+/* Compare-xchg with pagefaults disabled. - * Notes: - * -Best-Effort: Exchg happens only if compare succeeds. - * If compare fails, returns; leaving retry/looping to upper layers -@@ -121,7 +121,7 @@ - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - -- pagefault_disable(); /* implies preempt_disable() */ -+ pagefault_disable(); - - /* TBD : can use llock/scond */ - __asm__ __volatile__( -@@ -142,7 +142,7 @@ - : "r"(oldval), "r"(newval), "r"(uaddr), "ir"(-EFAULT) - : "cc", "memory"); - -- pagefault_enable(); /* subsumes preempt_enable() */ -+ pagefault_enable(); - - *uval = val; - return val; -diff -Nur linux-4.1.26.orig/arch/arc/mm/fault.c linux-4.1.26/arch/arc/mm/fault.c ---- linux-4.1.26.orig/arch/arc/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arc/mm/fault.c 2016-06-19 15:30:54.915151887 +0200 -@@ -86,7 +86,7 @@ - * If we're in an interrupt or have no user - * context, we must not take the fault.. - */ -- if (in_atomic() || !mm) -+ if (faulthandler_disabled() || !mm) - goto no_context; - - if (user_mode(regs)) -diff -Nur linux-4.1.26.orig/arch/arm/include/asm/cmpxchg.h linux-4.1.26/arch/arm/include/asm/cmpxchg.h ---- linux-4.1.26.orig/arch/arm/include/asm/cmpxchg.h 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/include/asm/cmpxchg.h 2016-06-19 15:30:54.919152041 +0200 -@@ -129,6 +129,8 @@ - - #else /* min ARCH >= ARMv6 */ - -+#define __HAVE_ARCH_CMPXCHG 1 +diff --git a/Documentation/hwlat_detector.txt b/Documentation/hwlat_detector.txt +new file mode 100644 +index 000000000000..cb61516483d3 +--- /dev/null ++++ b/Documentation/hwlat_detector.txt +@@ -0,0 +1,64 @@ ++Introduction: ++------------- + - extern void __bad_cmpxchg(volatile void *ptr, int size); - - /* -diff -Nur linux-4.1.26.orig/arch/arm/include/asm/futex.h linux-4.1.26/arch/arm/include/asm/futex.h ---- linux-4.1.26.orig/arch/arm/include/asm/futex.h 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/include/asm/futex.h 2016-06-19 15:30:54.919152041 +0200 -@@ -93,6 +93,7 @@ - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) - return -EFAULT; - -+ preempt_disable(); - __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" - "1: " TUSER(ldr) " %1, [%4]\n" - " teq %1, %2\n" -@@ -104,6 +105,8 @@ - : "cc", "memory"); - - *uval = val; -+ preempt_enable(); ++The module hwlat_detector is a special purpose kernel module that is used to ++detect large system latencies induced by the behavior of certain underlying ++hardware or firmware, independent of Linux itself. The code was developed ++originally to detect SMIs (System Management Interrupts) on x86 systems, ++however there is nothing x86 specific about this patchset. It was ++originally written for use by the "RT" patch since the Real Time ++kernel is highly latency sensitive. + - return ret; - } - -@@ -124,7 +127,10 @@ - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) - return -EFAULT; - -- pagefault_disable(); /* implies preempt_disable() */ -+#ifndef CONFIG_SMP -+ preempt_disable(); -+#endif -+ pagefault_disable(); - - switch (op) { - case FUTEX_OP_SET: -@@ -146,7 +152,10 @@ - ret = -ENOSYS; - } - -- pagefault_enable(); /* subsumes preempt_enable() */ -+ pagefault_enable(); -+#ifndef CONFIG_SMP -+ preempt_enable(); -+#endif - - if (!ret) { - switch (cmp) { -diff -Nur linux-4.1.26.orig/arch/arm/include/asm/switch_to.h linux-4.1.26/arch/arm/include/asm/switch_to.h ---- linux-4.1.26.orig/arch/arm/include/asm/switch_to.h 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/include/asm/switch_to.h 2016-06-19 15:30:54.919152041 +0200 -@@ -3,6 +3,13 @@ - - #include - -+#if defined CONFIG_PREEMPT_RT_FULL && defined CONFIG_HIGHMEM -+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p); -+#else -+static inline void -+switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { } -+#endif ++SMIs are usually not serviced by the Linux kernel, which typically does not ++even know that they are occuring. SMIs are instead are set up by BIOS code ++and are serviced by BIOS code, usually for "critical" events such as ++management of thermal sensors and fans. Sometimes though, SMIs are used for ++other tasks and those tasks can spend an inordinate amount of time in the ++handler (sometimes measured in milliseconds). Obviously this is a problem if ++you are trying to keep event service latencies down in the microsecond range. + - /* - * For v7 SMP cores running a preemptible kernel we may be pre-empted - * during a TLB maintenance operation, so execute an inner-shareable dsb -@@ -22,6 +29,7 @@ - - #define switch_to(prev,next,last) \ - do { \ -+ switch_kmaps(prev, next); \ - last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ - } while (0) - -diff -Nur linux-4.1.26.orig/arch/arm/include/asm/thread_info.h linux-4.1.26/arch/arm/include/asm/thread_info.h ---- linux-4.1.26.orig/arch/arm/include/asm/thread_info.h 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/include/asm/thread_info.h 2016-06-19 15:30:54.919152041 +0200 -@@ -50,6 +50,7 @@ - struct thread_info { - unsigned long flags; /* low level flags */ - int preempt_count; /* 0 => preemptable, <0 => bug */ -+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ - mm_segment_t addr_limit; /* address limit */ - struct task_struct *task; /* main task structure */ - __u32 cpu; /* cpu */ -@@ -147,6 +148,7 @@ - #define TIF_SIGPENDING 0 - #define TIF_NEED_RESCHED 1 - #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ -+#define TIF_NEED_RESCHED_LAZY 3 - #define TIF_UPROBE 7 - #define TIF_SYSCALL_TRACE 8 - #define TIF_SYSCALL_AUDIT 9 -@@ -160,6 +162,7 @@ - #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) - #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) - #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) -+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) - #define _TIF_UPROBE (1 << TIF_UPROBE) - #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) - #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -diff -Nur linux-4.1.26.orig/arch/arm/Kconfig linux-4.1.26/arch/arm/Kconfig ---- linux-4.1.26.orig/arch/arm/Kconfig 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/Kconfig 2016-06-19 15:30:54.919152041 +0200 -@@ -31,7 +31,7 @@ - select HARDIRQS_SW_RESEND - select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) - select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 -- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL -+ select HAVE_ARCH_JUMP_LABEL if (!XIP_KERNEL && !PREEMPT_RT_BASE) - select HAVE_ARCH_KGDB - select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) - select HAVE_ARCH_TRACEHOOK -@@ -66,6 +66,7 @@ - select HAVE_PERF_EVENTS - select HAVE_PERF_REGS - select HAVE_PERF_USER_STACK_DUMP -+ select HAVE_PREEMPT_LAZY - select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE) - select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_SYSCALL_TRACEPOINTS -diff -Nur linux-4.1.26.orig/arch/arm/kernel/asm-offsets.c linux-4.1.26/arch/arm/kernel/asm-offsets.c ---- linux-4.1.26.orig/arch/arm/kernel/asm-offsets.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kernel/asm-offsets.c 2016-06-19 15:30:54.919152041 +0200 -@@ -65,6 +65,7 @@ - BLANK(); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); -+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); -diff -Nur linux-4.1.26.orig/arch/arm/kernel/entry-armv.S linux-4.1.26/arch/arm/kernel/entry-armv.S ---- linux-4.1.26.orig/arch/arm/kernel/entry-armv.S 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kernel/entry-armv.S 2016-06-19 15:30:54.919152041 +0200 -@@ -208,11 +208,18 @@ - #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 -+ bne 1f @ return from exeption -+ ldr r0, [tsk, #TI_FLAGS] @ get flags -+ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set -+ blne svc_preempt @ preempt! ++The hardware latency detector works by hogging all of the cpus for configurable ++amounts of time (by calling stop_machine()), polling the CPU Time Stamp Counter ++for some period, then looking for gaps in the TSC data. Any gap indicates a ++time when the polling was interrupted and since the machine is stopped and ++interrupts turned off the only thing that could do that would be an SMI. + -+ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count -+ teq r8, #0 @ if preempt lazy count != 0 - movne r0, #0 @ force flags to 0 -- tst r0, #_TIF_NEED_RESCHED -+ tst r0, #_TIF_NEED_RESCHED_LAZY - blne svc_preempt -+1: - #endif - - svc_exit r5, irq = 1 @ return from exception -@@ -227,6 +234,8 @@ - 1: bl preempt_schedule_irq @ irq en/disable is done inside - ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS - tst r0, #_TIF_NEED_RESCHED -+ bne 1b -+ tst r0, #_TIF_NEED_RESCHED_LAZY - reteq r8 @ go again - b 1b - #endif -diff -Nur linux-4.1.26.orig/arch/arm/kernel/process.c linux-4.1.26/arch/arm/kernel/process.c ---- linux-4.1.26.orig/arch/arm/kernel/process.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kernel/process.c 2016-06-19 15:30:54.919152041 +0200 -@@ -290,6 +290,30 @@ - } - - #ifdef CONFIG_MMU -+/* -+ * CONFIG_SPLIT_PTLOCK_CPUS results in a page->ptl lock. If the lock is not -+ * initialized by pgtable_page_ctor() then a coredump of the vector page will -+ * fail. -+ */ -+static int __init vectors_user_mapping_init_page(void) -+{ -+ struct page *page; -+ unsigned long addr = 0xffff0000; -+ pgd_t *pgd; -+ pud_t *pud; -+ pmd_t *pmd; ++Note that the SMI detector should *NEVER* be used in a production environment. ++It is intended to be run manually to determine if the hardware platform has a ++problem with long system firmware service routines. + -+ pgd = pgd_offset_k(addr); -+ pud = pud_offset(pgd, addr); -+ pmd = pmd_offset(pud, addr); -+ page = pmd_page(*(pmd)); ++Usage: ++------ + -+ pgtable_page_ctor(page); ++Loading the module hwlat_detector passing the parameter "enabled=1" (or by ++setting the "enable" entry in "hwlat_detector" debugfs toggled on) is the only ++step required to start the hwlat_detector. It is possible to redefine the ++threshold in microseconds (us) above which latency spikes will be taken ++into account (parameter "threshold="). + -+ return 0; -+} -+late_initcall(vectors_user_mapping_init_page); ++Example: + - #ifdef CONFIG_KUSER_HELPERS - /* - * The vectors page is always readable from user space for the -diff -Nur linux-4.1.26.orig/arch/arm/kernel/signal.c linux-4.1.26/arch/arm/kernel/signal.c ---- linux-4.1.26.orig/arch/arm/kernel/signal.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kernel/signal.c 2016-06-19 15:30:54.919152041 +0200 -@@ -568,7 +568,8 @@ - do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) - { - do { -- if (likely(thread_flags & _TIF_NEED_RESCHED)) { -+ if (likely(thread_flags & (_TIF_NEED_RESCHED | -+ _TIF_NEED_RESCHED_LAZY))) { - schedule(); - } else { - if (unlikely(!user_mode(regs))) -diff -Nur linux-4.1.26.orig/arch/arm/kernel/smp.c linux-4.1.26/arch/arm/kernel/smp.c ---- linux-4.1.26.orig/arch/arm/kernel/smp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kernel/smp.c 2016-06-19 15:30:54.919152041 +0200 -@@ -213,8 +213,6 @@ - flush_cache_louis(); - local_flush_tlb_all(); ++ # modprobe hwlat_detector enabled=1 threshold=100 ++ ++After the module is loaded, it creates a directory named "hwlat_detector" under ++the debugfs mountpoint, "/debug/hwlat_detector" for this text. It is necessary ++to have debugfs mounted, which might be on /sys/debug on your system. ++ ++The /debug/hwlat_detector interface contains the following files: ++ ++count - number of latency spikes observed since last reset ++enable - a global enable/disable toggle (0/1), resets count ++max - maximum hardware latency actually observed (usecs) ++sample - a pipe from which to read current raw sample data ++ in the format ++ (can be opened O_NONBLOCK for a single sample) ++threshold - minimum latency value to be considered (usecs) ++width - time period to sample with CPUs held (usecs) ++ must be less than the total window size (enforced) ++window - total period of sampling, width being inside (usecs) ++ ++By default we will set width to 500,000 and window to 1,000,000, meaning that ++we will sample every 1,000,000 usecs (1s) for 500,000 usecs (0.5s). If we ++observe any latencies that exceed the threshold (initially 100 usecs), ++then we write to a global sample ring buffer of 8K samples, which is ++consumed by reading from the "sample" (pipe) debugfs file interface. +diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt +index 0e307c94809a..6964d0f80ae7 100644 +--- a/Documentation/sysrq.txt ++++ b/Documentation/sysrq.txt +@@ -59,10 +59,17 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - , + On other - If you know of the key combos for other architectures, please + let me know so I can add them to this section. -- clear_tasks_mm_cpumask(cpu); +-On all - write a character to /proc/sysrq-trigger. e.g.: - - return 0; - } ++On all - write a character to /proc/sysrq-trigger, e.g.: + echo t > /proc/sysrq-trigger -@@ -230,6 +228,9 @@ - pr_err("CPU%u: cpu didn't die\n", cpu); - return; - } ++On all - Enable network SysRq by writing a cookie to icmp_echo_sysrq, e.g. ++ echo 0x01020304 >/proc/sys/net/ipv4/icmp_echo_sysrq ++ Send an ICMP echo request with this pattern plus the particular ++ SysRq command key. Example: ++ # ping -c1 -s57 -p0102030468 ++ will trigger the SysRq-H (help) command. + -+ clear_tasks_mm_cpumask(cpu); + - pr_notice("CPU%u: shutdown\n", cpu); - - /* -diff -Nur linux-4.1.26.orig/arch/arm/kernel/unwind.c linux-4.1.26/arch/arm/kernel/unwind.c ---- linux-4.1.26.orig/arch/arm/kernel/unwind.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kernel/unwind.c 2016-06-19 15:30:54.919152041 +0200 -@@ -93,7 +93,7 @@ - static const struct unwind_idx *__origin_unwind_idx; - extern const struct unwind_idx __stop_unwind_idx[]; - --static DEFINE_SPINLOCK(unwind_lock); -+static DEFINE_RAW_SPINLOCK(unwind_lock); - static LIST_HEAD(unwind_tables); - - /* Convert a prel31 symbol to an absolute address */ -@@ -201,7 +201,7 @@ - /* module unwind tables */ - struct unwind_table *table; - -- spin_lock_irqsave(&unwind_lock, flags); -+ raw_spin_lock_irqsave(&unwind_lock, flags); - list_for_each_entry(table, &unwind_tables, list) { - if (addr >= table->begin_addr && - addr < table->end_addr) { -@@ -213,7 +213,7 @@ - break; - } - } -- spin_unlock_irqrestore(&unwind_lock, flags); -+ raw_spin_unlock_irqrestore(&unwind_lock, flags); - } - - pr_debug("%s: idx = %p\n", __func__, idx); -@@ -529,9 +529,9 @@ - tab->begin_addr = text_addr; - tab->end_addr = text_addr + text_size; - -- spin_lock_irqsave(&unwind_lock, flags); -+ raw_spin_lock_irqsave(&unwind_lock, flags); - list_add_tail(&tab->list, &unwind_tables); -- spin_unlock_irqrestore(&unwind_lock, flags); -+ raw_spin_unlock_irqrestore(&unwind_lock, flags); - - return tab; - } -@@ -543,9 +543,9 @@ - if (!tab) - return; - -- spin_lock_irqsave(&unwind_lock, flags); -+ raw_spin_lock_irqsave(&unwind_lock, flags); - list_del(&tab->list); -- spin_unlock_irqrestore(&unwind_lock, flags); -+ raw_spin_unlock_irqrestore(&unwind_lock, flags); - - kfree(tab); - } -diff -Nur linux-4.1.26.orig/arch/arm/kvm/arm.c linux-4.1.26/arch/arm/kvm/arm.c ---- linux-4.1.26.orig/arch/arm/kvm/arm.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kvm/arm.c 2016-06-19 15:30:54.919152041 +0200 -@@ -474,9 +474,9 @@ - - static void vcpu_pause(struct kvm_vcpu *vcpu) - { -- wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); -+ struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); - -- wait_event_interruptible(*wq, !vcpu->arch.pause); -+ swait_event_interruptible(*wq, !vcpu->arch.pause); - } - - static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) -diff -Nur linux-4.1.26.orig/arch/arm/kvm/psci.c linux-4.1.26/arch/arm/kvm/psci.c ---- linux-4.1.26.orig/arch/arm/kvm/psci.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/kvm/psci.c 2016-06-19 15:30:54.919152041 +0200 -@@ -68,7 +68,7 @@ - { - struct kvm *kvm = source_vcpu->kvm; - struct kvm_vcpu *vcpu = NULL; -- wait_queue_head_t *wq; -+ struct swait_head *wq; - unsigned long cpu_id; - unsigned long context_id; - phys_addr_t target_pc; -@@ -117,7 +117,7 @@ - smp_mb(); /* Make sure the above is visible */ - - wq = kvm_arch_vcpu_wq(vcpu); -- wake_up_interruptible(wq); -+ swait_wake_interruptible(wq); - - return PSCI_RET_SUCCESS; - } -diff -Nur linux-4.1.26.orig/arch/arm/mach-exynos/platsmp.c linux-4.1.26/arch/arm/mach-exynos/platsmp.c ---- linux-4.1.26.orig/arch/arm/mach-exynos/platsmp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-exynos/platsmp.c 2016-06-19 15:30:54.919152041 +0200 -@@ -231,7 +231,7 @@ - return (void __iomem *)(S5P_VA_SCU); - } - --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); - - static void exynos_secondary_init(unsigned int cpu) - { -@@ -244,8 +244,8 @@ - /* - * Synchronise with the boot thread. - */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); -+ raw_spin_lock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } - - static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) -@@ -259,7 +259,7 @@ - * Set synchronisation state between this boot processor - * and the secondary one - */ -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); - - /* - * The secondary processor is waiting to be released from -@@ -286,7 +286,7 @@ - - if (timeout == 0) { - printk(KERN_ERR "cpu1 power enable failed"); -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - return -ETIMEDOUT; - } - } -@@ -342,7 +342,7 @@ - * calibrations, then wait for it to finish - */ - fail: -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - - return pen_release != -1 ? ret : 0; - } -diff -Nur linux-4.1.26.orig/arch/arm/mach-hisi/platmcpm.c linux-4.1.26/arch/arm/mach-hisi/platmcpm.c ---- linux-4.1.26.orig/arch/arm/mach-hisi/platmcpm.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-hisi/platmcpm.c 2016-06-19 15:30:54.923152195 +0200 -@@ -57,7 +57,7 @@ - - static void __iomem *sysctrl, *fabric; - static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER]; --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); - static u32 fabric_phys_addr; - /* - * [0]: bootwrapper physical address -@@ -104,7 +104,7 @@ - if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER) - return -EINVAL; - -- spin_lock_irq(&boot_lock); -+ raw_spin_lock_irq(&boot_lock); - - if (hip04_cpu_table[cluster][cpu]) - goto out; -@@ -133,7 +133,7 @@ - udelay(20); - out: - hip04_cpu_table[cluster][cpu]++; -- spin_unlock_irq(&boot_lock); -+ raw_spin_unlock_irq(&boot_lock); - - return 0; - } -@@ -149,7 +149,7 @@ - - __mcpm_cpu_going_down(cpu, cluster); - -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); - BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP); - hip04_cpu_table[cluster][cpu]--; - if (hip04_cpu_table[cluster][cpu] == 1) { -@@ -162,7 +162,7 @@ - - last_man = hip04_cluster_is_down(cluster); - if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) { -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - /* Since it's Cortex A15, disable L2 prefetching. */ - asm volatile( - "mcr p15, 1, %0, c15, c0, 3 \n\t" -@@ -173,7 +173,7 @@ - hip04_set_snoop_filter(cluster, 0); - __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN); - } else { -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - v7_exit_coherency_flush(louis); - } - -@@ -192,7 +192,7 @@ - cpu >= HIP04_MAX_CPUS_PER_CLUSTER); - - count = TIMEOUT_MSEC / POLL_MSEC; -- spin_lock_irq(&boot_lock); -+ raw_spin_lock_irq(&boot_lock); - for (tries = 0; tries < count; tries++) { - if (hip04_cpu_table[cluster][cpu]) { - ret = -EBUSY; -@@ -202,10 +202,10 @@ - data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster)); - if (data & CORE_WFI_STATUS(cpu)) - break; -- spin_unlock_irq(&boot_lock); -+ raw_spin_unlock_irq(&boot_lock); - /* Wait for clean L2 when the whole cluster is down. */ - msleep(POLL_MSEC); -- spin_lock_irq(&boot_lock); -+ raw_spin_lock_irq(&boot_lock); - } - if (tries >= count) - goto err; -@@ -220,10 +220,10 @@ - } - if (tries >= count) - goto err; -- spin_unlock_irq(&boot_lock); -+ raw_spin_unlock_irq(&boot_lock); - return 0; - err: -- spin_unlock_irq(&boot_lock); -+ raw_spin_unlock_irq(&boot_lock); - return ret; - } - -@@ -235,10 +235,10 @@ - cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); - cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); - -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); - if (!hip04_cpu_table[cluster][cpu]) - hip04_cpu_table[cluster][cpu] = 1; -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } + * What are the 'command' keys? + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 'b' - Will immediately reboot the system without syncing or unmounting +diff --git a/Documentation/trace/histograms.txt b/Documentation/trace/histograms.txt +new file mode 100644 +index 000000000000..6f2aeabf7faa +--- /dev/null ++++ b/Documentation/trace/histograms.txt +@@ -0,0 +1,186 @@ ++ Using the Linux Kernel Latency Histograms ++ ++ ++This document gives a short explanation how to enable, configure and use ++latency histograms. Latency histograms are primarily relevant in the ++context of real-time enabled kernels (CONFIG_PREEMPT/CONFIG_PREEMPT_RT) ++and are used in the quality management of the Linux real-time ++capabilities. ++ ++ ++* Purpose of latency histograms ++ ++A latency histogram continuously accumulates the frequencies of latency ++data. There are two types of histograms ++- potential sources of latencies ++- effective latencies ++ ++ ++* Potential sources of latencies ++ ++Potential sources of latencies are code segments where interrupts, ++preemption or both are disabled (aka critical sections). To create ++histograms of potential sources of latency, the kernel stores the time ++stamp at the start of a critical section, determines the time elapsed ++when the end of the section is reached, and increments the frequency ++counter of that latency value - irrespective of whether any concurrently ++running process is affected by latency or not. ++- Configuration items (in the Kernel hacking/Tracers submenu) ++ CONFIG_INTERRUPT_OFF_LATENCY ++ CONFIG_PREEMPT_OFF_LATENCY ++ ++ ++* Effective latencies ++ ++Effective latencies are actually occuring during wakeup of a process. To ++determine effective latencies, the kernel stores the time stamp when a ++process is scheduled to be woken up, and determines the duration of the ++wakeup time shortly before control is passed over to this process. Note ++that the apparent latency in user space may be somewhat longer, since the ++process may be interrupted after control is passed over to it but before ++the execution in user space takes place. Simply measuring the interval ++between enqueuing and wakeup may also not appropriate in cases when a ++process is scheduled as a result of a timer expiration. The timer may have ++missed its deadline, e.g. due to disabled interrupts, but this latency ++would not be registered. Therefore, the offsets of missed timers are ++recorded in a separate histogram. If both wakeup latency and missed timer ++offsets are configured and enabled, a third histogram may be enabled that ++records the overall latency as a sum of the timer latency, if any, and the ++wakeup latency. This histogram is called "timerandwakeup". ++- Configuration items (in the Kernel hacking/Tracers submenu) ++ CONFIG_WAKEUP_LATENCY ++ CONFIG_MISSED_TIMER_OFSETS ++ ++ ++* Usage ++ ++The interface to the administration of the latency histograms is located ++in the debugfs file system. To mount it, either enter ++ ++mount -t sysfs nodev /sys ++mount -t debugfs nodev /sys/kernel/debug ++ ++from shell command line level, or add ++ ++nodev /sys sysfs defaults 0 0 ++nodev /sys/kernel/debug debugfs defaults 0 0 ++ ++to the file /etc/fstab. All latency histogram related files are then ++available in the directory /sys/kernel/debug/tracing/latency_hist. A ++particular histogram type is enabled by writing non-zero to the related ++variable in the /sys/kernel/debug/tracing/latency_hist/enable directory. ++Select "preemptirqsoff" for the histograms of potential sources of ++latencies and "wakeup" for histograms of effective latencies etc. The ++histogram data - one per CPU - are available in the files ++ ++/sys/kernel/debug/tracing/latency_hist/preemptoff/CPUx ++/sys/kernel/debug/tracing/latency_hist/irqsoff/CPUx ++/sys/kernel/debug/tracing/latency_hist/preemptirqsoff/CPUx ++/sys/kernel/debug/tracing/latency_hist/wakeup/CPUx ++/sys/kernel/debug/tracing/latency_hist/wakeup/sharedprio/CPUx ++/sys/kernel/debug/tracing/latency_hist/missed_timer_offsets/CPUx ++/sys/kernel/debug/tracing/latency_hist/timerandwakeup/CPUx ++ ++The histograms are reset by writing non-zero to the file "reset" in a ++particular latency directory. To reset all latency data, use ++ ++#!/bin/sh ++ ++TRACINGDIR=/sys/kernel/debug/tracing ++HISTDIR=$TRACINGDIR/latency_hist ++ ++if test -d $HISTDIR ++then ++ cd $HISTDIR ++ for i in `find . | grep /reset$` ++ do ++ echo 1 >$i ++ done ++fi ++ ++ ++* Data format ++ ++Latency data are stored with a resolution of one microsecond. The ++maximum latency is 10,240 microseconds. The data are only valid, if the ++overflow register is empty. Every output line contains the latency in ++microseconds in the first row and the number of samples in the second ++row. To display only lines with a positive latency count, use, for ++example, ++ ++grep -v " 0$" /sys/kernel/debug/tracing/latency_hist/preemptoff/CPU0 ++ ++#Minimum latency: 0 microseconds. ++#Average latency: 0 microseconds. ++#Maximum latency: 25 microseconds. ++#Total samples: 3104770694 ++#There are 0 samples greater or equal than 10240 microseconds ++#usecs samples ++ 0 2984486876 ++ 1 49843506 ++ 2 58219047 ++ 3 5348126 ++ 4 2187960 ++ 5 3388262 ++ 6 959289 ++ 7 208294 ++ 8 40420 ++ 9 4485 ++ 10 14918 ++ 11 18340 ++ 12 25052 ++ 13 19455 ++ 14 5602 ++ 15 969 ++ 16 47 ++ 17 18 ++ 18 14 ++ 19 1 ++ 20 3 ++ 21 2 ++ 22 5 ++ 23 2 ++ 25 1 ++ ++ ++* Wakeup latency of a selected process ++ ++To only collect wakeup latency data of a particular process, write the ++PID of the requested process to ++ ++/sys/kernel/debug/tracing/latency_hist/wakeup/pid ++ ++PIDs are not considered, if this variable is set to 0. ++ ++ ++* Details of the process with the highest wakeup latency so far ++ ++Selected data of the process that suffered from the highest wakeup ++latency that occurred in a particular CPU are available in the file ++ ++/sys/kernel/debug/tracing/latency_hist/wakeup/max_latency-CPUx. ++ ++In addition, other relevant system data at the time when the ++latency occurred are given. ++ ++The format of the data is (all in one line): ++ () \ ++<- ++ ++The value of is only relevant in the combined timer ++and wakeup latency recording. In the wakeup recording, it is ++always 0, in the missed_timer_offsets recording, it is the same ++as . ++ ++When retrospectively searching for the origin of a latency and ++tracing was not enabled, it may be helpful to know the name and ++some basic data of the task that (finally) was switching to the ++late real-tlme task. In addition to the victim's data, also the ++data of the possible culprit are therefore displayed after the ++"<-" symbol. ++ ++Finally, the timestamp of the time when the latency occurred ++in . after the most recent system boot ++is provided. ++ ++These data are also reset when the wakeup histogram is reset. +diff --git a/arch/Kconfig b/arch/Kconfig +index a65eafb24997..78d3ed24484a 100644 +--- a/arch/Kconfig ++++ b/arch/Kconfig +@@ -6,6 +6,7 @@ config OPROFILE + tristate "OProfile system profiling" + depends on PROFILING + depends on HAVE_OPROFILE ++ depends on !PREEMPT_RT_FULL + select RING_BUFFER + select RING_BUFFER_ALLOW_SWAP + help +@@ -49,6 +50,7 @@ config KPROBES + config JUMP_LABEL + bool "Optimize very unlikely/likely branches" + depends on HAVE_ARCH_JUMP_LABEL ++ depends on (!INTERRUPT_OFF_HIST && !PREEMPT_OFF_HIST && !WAKEUP_LATENCY_HIST && !MISSED_TIMER_OFFSETS_HIST) + help + This option enables a transparent branch optimization that + makes certain almost-always-true or almost-always-false branch +diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c +index 9d0ac091a52a..4a905bd667e2 100644 +--- a/arch/alpha/mm/fault.c ++++ b/arch/alpha/mm/fault.c +@@ -23,8 +23,7 @@ + #include + #include + #include +- +-#include ++#include - static void __naked hip04_mcpm_power_up_setup(unsigned int affinity_level) -diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/gpio.c linux-4.1.26/arch/arm/mach-omap2/gpio.c ---- linux-4.1.26.orig/arch/arm/mach-omap2/gpio.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-omap2/gpio.c 2016-06-19 15:30:54.923152195 +0200 -@@ -130,7 +130,6 @@ - } + extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); - pwrdm = omap_hwmod_get_pwrdm(oh); -- pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); +@@ -107,7 +106,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, - pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata)); - kfree(pdata); -diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/omap-smp.c linux-4.1.26/arch/arm/mach-omap2/omap-smp.c ---- linux-4.1.26.orig/arch/arm/mach-omap2/omap-smp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-omap2/omap-smp.c 2016-06-19 15:30:54.923152195 +0200 -@@ -43,7 +43,7 @@ - /* SCU base address */ - static void __iomem *scu_base; + /* If we're in an interrupt context, or have no user context, + we must not take the fault. */ +- if (!mm || in_atomic()) ++ if (!mm || faulthandler_disabled()) + goto no_context; --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); + #ifdef CONFIG_ALPHA_LARGE_VMALLOC +diff --git a/arch/arc/include/asm/futex.h b/arch/arc/include/asm/futex.h +index 4dc64ddebece..05b5aaf5b0f9 100644 +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -53,7 +53,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; - void __iomem *omap4_get_scu_base(void) - { -@@ -74,8 +74,8 @@ - /* - * Synchronise with the boot thread. - */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); -+ raw_spin_lock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } +- pagefault_disable(); /* implies preempt_disable() */ ++ pagefault_disable(); - static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) -@@ -89,7 +89,7 @@ - * Set synchronisation state between this boot processor - * and the secondary one - */ -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); + switch (op) { + case FUTEX_OP_SET: +@@ -75,7 +75,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + ret = -ENOSYS; + } - /* - * Update the AuxCoreBoot0 with boot state for secondary core. -@@ -166,7 +166,7 @@ - * Now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); +- pagefault_enable(); /* subsumes preempt_enable() */ ++ pagefault_enable(); - return 0; - } -diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.c linux-4.1.26/arch/arm/mach-omap2/powerdomain.c ---- linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-omap2/powerdomain.c 2016-06-19 15:30:54.923152195 +0200 -@@ -1166,43 +1166,3 @@ - return count; + if (!ret) { + switch (cmp) { +@@ -104,7 +104,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) + return ret; } --/** -- * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? -- * @pwrdm: struct powerdomain * -- * -- * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain -- * can lose either memory or logic context or if @pwrdm is invalid, or -- * returns 0 otherwise. This function is not concerned with how the -- * powerdomain registers are programmed (i.e., to go off or not); it's -- * concerned with whether it's ever possible for this powerdomain to -- * go off while some other part of the chip is active. This function -- * assumes that every powerdomain can go to either ON or INACTIVE. -- */ --bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) --{ -- int i; -- -- if (!pwrdm) { -- pr_debug("powerdomain: %s: invalid powerdomain pointer\n", -- __func__); -- return 1; -- } -- -- if (pwrdm->pwrsts & PWRSTS_OFF) -- return 1; -- -- if (pwrdm->pwrsts & PWRSTS_RET) { -- if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) -- return 1; -- -- for (i = 0; i < pwrdm->banks; i++) -- if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) -- return 1; -- } -- -- for (i = 0; i < pwrdm->banks; i++) -- if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) -- return 1; -- -- return 0; --} -diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.h linux-4.1.26/arch/arm/mach-omap2/powerdomain.h ---- linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.h 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-omap2/powerdomain.h 2016-06-19 15:30:54.923152195 +0200 -@@ -244,7 +244,6 @@ - int pwrdm_pre_transition(struct powerdomain *pwrdm); - int pwrdm_post_transition(struct powerdomain *pwrdm); - int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); --bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); - - extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state); - -diff -Nur linux-4.1.26.orig/arch/arm/mach-prima2/platsmp.c linux-4.1.26/arch/arm/mach-prima2/platsmp.c ---- linux-4.1.26.orig/arch/arm/mach-prima2/platsmp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-prima2/platsmp.c 2016-06-19 15:30:54.923152195 +0200 -@@ -22,7 +22,7 @@ - - static void __iomem *clk_base; - --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); +-/* Compare-xchg with preemption disabled. ++/* Compare-xchg with pagefaults disabled. + * Notes: + * -Best-Effort: Exchg happens only if compare succeeds. + * If compare fails, returns; leaving retry/looping to upper layers +@@ -121,7 +121,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; - static void sirfsoc_secondary_init(unsigned int cpu) - { -@@ -36,8 +36,8 @@ - /* - * Synchronise with the boot thread. - */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); -+ raw_spin_lock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } +- pagefault_disable(); /* implies preempt_disable() */ ++ pagefault_disable(); - static const struct of_device_id clk_ids[] = { -@@ -75,7 +75,7 @@ - /* make sure write buffer is drained */ - mb(); + /* TBD : can use llock/scond */ + __asm__ __volatile__( +@@ -142,7 +142,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, + : "r"(oldval), "r"(newval), "r"(uaddr), "ir"(-EFAULT) + : "cc", "memory"); -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); +- pagefault_enable(); /* subsumes preempt_enable() */ ++ pagefault_enable(); - /* - * The secondary processor is waiting to be released from -@@ -107,7 +107,7 @@ - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish + *uval = val; + return val; +diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c +index 6a2e006cbcce..d948e4e9d89c 100644 +--- a/arch/arc/mm/fault.c ++++ b/arch/arc/mm/fault.c +@@ -86,7 +86,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) + * If we're in an interrupt or have no user + * context, we must not take the fault.. */ -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - - return pen_release != -1 ? -ENOSYS : 0; - } -diff -Nur linux-4.1.26.orig/arch/arm/mach-qcom/platsmp.c linux-4.1.26/arch/arm/mach-qcom/platsmp.c ---- linux-4.1.26.orig/arch/arm/mach-qcom/platsmp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-qcom/platsmp.c 2016-06-19 15:30:54.923152195 +0200 -@@ -46,7 +46,7 @@ +- if (in_atomic() || !mm) ++ if (faulthandler_disabled() || !mm) + goto no_context; - extern void secondary_startup_arm(void); + if (user_mode(regs)) +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 19f4cc634b0e..e16a259177d4 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -31,7 +31,7 @@ config ARM + select HARDIRQS_SW_RESEND + select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) + select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 +- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL ++ select HAVE_ARCH_JUMP_LABEL if (!XIP_KERNEL && !PREEMPT_RT_BASE) + select HAVE_ARCH_KGDB + select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) + select HAVE_ARCH_TRACEHOOK +@@ -66,6 +66,7 @@ config ARM + select HAVE_PERF_EVENTS + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP ++ select HAVE_PREEMPT_LAZY + select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE) + select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_SYSCALL_TRACEPOINTS +diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h +index abb2c3769b01..2386e9745ba4 100644 +--- a/arch/arm/include/asm/cmpxchg.h ++++ b/arch/arm/include/asm/cmpxchg.h +@@ -129,6 +129,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); + #else /* min ARCH >= ARMv6 */ - #ifdef CONFIG_HOTPLUG_CPU - static void __ref qcom_cpu_die(unsigned int cpu) -@@ -60,8 +60,8 @@ - /* - * Synchronise with the boot thread. - */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); -+ raw_spin_lock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } ++#define __HAVE_ARCH_CMPXCHG 1 ++ + extern void __bad_cmpxchg(volatile void *ptr, int size); - static int scss_release_secondary(unsigned int cpu) -@@ -284,7 +284,7 @@ - * set synchronisation state between this boot processor - * and the secondary one - */ -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); + /* +diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h +index 4e78065a16aa..5eed82809d82 100644 +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -93,6 +93,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; - /* - * Send the secondary CPU a soft interrupt, thereby causing -@@ -297,7 +297,7 @@ - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); ++ preempt_disable(); + __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" + "1: " TUSER(ldr) " %1, [%4]\n" + " teq %1, %2\n" +@@ -104,6 +105,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + : "cc", "memory"); + *uval = val; ++ preempt_enable(); ++ return ret; } -diff -Nur linux-4.1.26.orig/arch/arm/mach-spear/platsmp.c linux-4.1.26/arch/arm/mach-spear/platsmp.c ---- linux-4.1.26.orig/arch/arm/mach-spear/platsmp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-spear/platsmp.c 2016-06-19 15:30:54.923152195 +0200 -@@ -32,7 +32,7 @@ - sync_cache_w(&pen_release); - } --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); +@@ -124,7 +127,10 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; - static void __iomem *scu_base = IOMEM(VA_SCU_BASE); +- pagefault_disable(); /* implies preempt_disable() */ ++#ifndef CONFIG_SMP ++ preempt_disable(); ++#endif ++ pagefault_disable(); -@@ -47,8 +47,8 @@ - /* - * Synchronise with the boot thread. - */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); -+ raw_spin_lock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } + switch (op) { + case FUTEX_OP_SET: +@@ -146,7 +152,10 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + ret = -ENOSYS; + } - static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle) -@@ -59,7 +59,7 @@ - * set synchronisation state between this boot processor - * and the secondary one - */ -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); +- pagefault_enable(); /* subsumes preempt_enable() */ ++ pagefault_enable(); ++#ifndef CONFIG_SMP ++ preempt_enable(); ++#endif - /* - * The secondary processor is waiting to be released from -@@ -84,7 +84,7 @@ - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); + if (!ret) { + switch (cmp) { +diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h +index c99e259469f7..f3e3d800c407 100644 +--- a/arch/arm/include/asm/switch_to.h ++++ b/arch/arm/include/asm/switch_to.h +@@ -3,6 +3,13 @@ - return pen_release != -1 ? -ENOSYS : 0; - } -diff -Nur linux-4.1.26.orig/arch/arm/mach-sti/platsmp.c linux-4.1.26/arch/arm/mach-sti/platsmp.c ---- linux-4.1.26.orig/arch/arm/mach-sti/platsmp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-sti/platsmp.c 2016-06-19 15:30:54.923152195 +0200 -@@ -34,7 +34,7 @@ - sync_cache_w(&pen_release); - } + #include --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); ++#if defined CONFIG_PREEMPT_RT_FULL && defined CONFIG_HIGHMEM ++void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p); ++#else ++static inline void ++switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { } ++#endif ++ + /* + * For v7 SMP cores running a preemptible kernel we may be pre-empted + * during a TLB maintenance operation, so execute an inner-shareable dsb +@@ -22,6 +29,7 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info - static void sti_secondary_init(unsigned int cpu) - { -@@ -49,8 +49,8 @@ - /* - * Synchronise with the boot thread. - */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); -+ raw_spin_lock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - } + #define switch_to(prev,next,last) \ + do { \ ++ switch_kmaps(prev, next); \ + last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ + } while (0) - static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) -@@ -61,7 +61,7 @@ - * set synchronisation state between this boot processor - * and the secondary one - */ -- spin_lock(&boot_lock); -+ raw_spin_lock(&boot_lock); +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index bd32eded3e50..b5a616376f60 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -50,6 +50,7 @@ struct cpu_context_save { + struct thread_info { + unsigned long flags; /* low level flags */ + int preempt_count; /* 0 => preemptable, <0 => bug */ ++ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ + mm_segment_t addr_limit; /* address limit */ + struct task_struct *task; /* main task structure */ + __u32 cpu; /* cpu */ +@@ -147,6 +148,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, + #define TIF_SIGPENDING 0 + #define TIF_NEED_RESCHED 1 + #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ ++#define TIF_NEED_RESCHED_LAZY 3 + #define TIF_UPROBE 7 + #define TIF_SYSCALL_TRACE 8 + #define TIF_SYSCALL_AUDIT 9 +@@ -160,6 +162,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) + #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) ++#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) + #define _TIF_UPROBE (1 << TIF_UPROBE) + #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) + #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c +index 871b8267d211..4dbe70de7318 100644 +--- a/arch/arm/kernel/asm-offsets.c ++++ b/arch/arm/kernel/asm-offsets.c +@@ -65,6 +65,7 @@ int main(void) + BLANK(); + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); ++ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count)); + DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); + DEFINE(TI_TASK, offsetof(struct thread_info, task)); + DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index 570306c49406..797a13d959b7 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -208,11 +208,18 @@ __irq_svc: + #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 ++ bne 1f @ return from exeption ++ ldr r0, [tsk, #TI_FLAGS] @ get flags ++ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set ++ blne svc_preempt @ preempt! ++ ++ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count ++ teq r8, #0 @ if preempt lazy count != 0 + movne r0, #0 @ force flags to 0 +- tst r0, #_TIF_NEED_RESCHED ++ tst r0, #_TIF_NEED_RESCHED_LAZY + blne svc_preempt ++1: + #endif + + svc_exit r5, irq = 1 @ return from exception +@@ -227,8 +234,14 @@ svc_preempt: + 1: bl preempt_schedule_irq @ irq en/disable is done inside + ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS + tst r0, #_TIF_NEED_RESCHED ++ bne 1b ++ tst r0, #_TIF_NEED_RESCHED_LAZY + reteq r8 @ go again +- b 1b ++ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count ++ teq r0, #0 @ if preempt lazy count != 0 ++ beq 1b ++ ret r8 @ go again ++ + #endif + + __und_fault: +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index f192a2a41719..649247ac00e6 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -290,6 +290,30 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) + } + + #ifdef CONFIG_MMU ++/* ++ * CONFIG_SPLIT_PTLOCK_CPUS results in a page->ptl lock. If the lock is not ++ * initialized by pgtable_page_ctor() then a coredump of the vector page will ++ * fail. ++ */ ++static int __init vectors_user_mapping_init_page(void) ++{ ++ struct page *page; ++ unsigned long addr = 0xffff0000; ++ pgd_t *pgd; ++ pud_t *pud; ++ pmd_t *pmd; ++ ++ pgd = pgd_offset_k(addr); ++ pud = pud_offset(pgd, addr); ++ pmd = pmd_offset(pud, addr); ++ page = pmd_page(*(pmd)); ++ ++ pgtable_page_ctor(page); ++ ++ return 0; ++} ++late_initcall(vectors_user_mapping_init_page); ++ + #ifdef CONFIG_KUSER_HELPERS + /* + * The vectors page is always readable from user space for the +diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c +index 586eef26203d..25bd12ef0b36 100644 +--- a/arch/arm/kernel/signal.c ++++ b/arch/arm/kernel/signal.c +@@ -568,7 +568,8 @@ asmlinkage int + do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) + { + do { +- if (likely(thread_flags & _TIF_NEED_RESCHED)) { ++ if (likely(thread_flags & (_TIF_NEED_RESCHED | ++ _TIF_NEED_RESCHED_LAZY))) { + schedule(); + } else { + if (unlikely(!user_mode(regs))) +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index f11d82527076..e561aef093c7 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -213,8 +213,6 @@ int __cpu_disable(void) + flush_cache_louis(); + local_flush_tlb_all(); + +- clear_tasks_mm_cpumask(cpu); +- + return 0; + } + +@@ -230,6 +228,9 @@ void __cpu_die(unsigned int cpu) + pr_err("CPU%u: cpu didn't die\n", cpu); + return; + } ++ ++ clear_tasks_mm_cpumask(cpu); ++ + pr_notice("CPU%u: shutdown\n", cpu); /* - * The secondary processor is waiting to be released from -@@ -92,7 +92,7 @@ - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); +diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c +index 0bee233fef9a..314cfb232a63 100644 +--- a/arch/arm/kernel/unwind.c ++++ b/arch/arm/kernel/unwind.c +@@ -93,7 +93,7 @@ extern const struct unwind_idx __start_unwind_idx[]; + static const struct unwind_idx *__origin_unwind_idx; + extern const struct unwind_idx __stop_unwind_idx[]; - return pen_release != -1 ? -ENOSYS : 0; +-static DEFINE_SPINLOCK(unwind_lock); ++static DEFINE_RAW_SPINLOCK(unwind_lock); + static LIST_HEAD(unwind_tables); + + /* Convert a prel31 symbol to an absolute address */ +@@ -201,7 +201,7 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr) + /* module unwind tables */ + struct unwind_table *table; + +- spin_lock_irqsave(&unwind_lock, flags); ++ raw_spin_lock_irqsave(&unwind_lock, flags); + list_for_each_entry(table, &unwind_tables, list) { + if (addr >= table->begin_addr && + addr < table->end_addr) { +@@ -213,7 +213,7 @@ static const struct unwind_idx *unwind_find_idx(unsigned long addr) + break; + } + } +- spin_unlock_irqrestore(&unwind_lock, flags); ++ raw_spin_unlock_irqrestore(&unwind_lock, flags); + } + + pr_debug("%s: idx = %p\n", __func__, idx); +@@ -529,9 +529,9 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, + tab->begin_addr = text_addr; + tab->end_addr = text_addr + text_size; + +- spin_lock_irqsave(&unwind_lock, flags); ++ raw_spin_lock_irqsave(&unwind_lock, flags); + list_add_tail(&tab->list, &unwind_tables); +- spin_unlock_irqrestore(&unwind_lock, flags); ++ raw_spin_unlock_irqrestore(&unwind_lock, flags); + + return tab; } -diff -Nur linux-4.1.26.orig/arch/arm/mach-ux500/platsmp.c linux-4.1.26/arch/arm/mach-ux500/platsmp.c ---- linux-4.1.26.orig/arch/arm/mach-ux500/platsmp.c 2016-06-07 01:13:11.000000000 +0200 -+++ linux-4.1.26/arch/arm/mach-ux500/platsmp.c 2016-06-19 15:30:54.923152195 +0200 -@@ -51,7 +51,7 @@ - return NULL; +@@ -543,9 +543,9 @@ void unwind_table_del(struct unwind_table *tab) + if (!tab) + return; + +- spin_lock_irqsave(&unwind_lock, flags); ++ raw_spin_lock_irqsave(&unwind_lock, flags); + list_del(&tab->list); +- spin_unlock_irqrestore(&unwind_lock, flags); ++ raw_spin_unlock_irqrestore(&unwind_lock, flags); + + kfree(tab); + } +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index 87b2663a5564..ce5e58d76cf9 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -473,9 +473,9 @@ bool kvm_arch_intc_initialized(struct kvm *kvm) + + static void vcpu_pause(struct kvm_vcpu *vcpu) + { +- wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); ++ struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); + +- wait_event_interruptible(*wq, !vcpu->arch.pause); ++ swait_event_interruptible(*wq, !vcpu->arch.pause); + } + + static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) +diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c +index 531e922486b2..e24f0461ea2d 100644 +--- a/arch/arm/kvm/psci.c ++++ b/arch/arm/kvm/psci.c +@@ -68,7 +68,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + { + struct kvm *kvm = source_vcpu->kvm; + struct kvm_vcpu *vcpu = NULL; +- wait_queue_head_t *wq; ++ struct swait_head *wq; + unsigned long cpu_id; + unsigned long context_id; + phys_addr_t target_pc; +@@ -117,7 +117,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) + smp_mb(); /* Make sure the above is visible */ + + wq = kvm_arch_vcpu_wq(vcpu); +- wake_up_interruptible(wq); ++ swait_wake_interruptible(wq); + + return PSCI_RET_SUCCESS; + } +diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c +index eaf58f88ef5d..8d3cb458a99c 100644 +--- a/arch/arm/mach-at91/at91rm9200.c ++++ b/arch/arm/mach-at91/at91rm9200.c +@@ -13,7 +13,6 @@ + #include + + #include +-#include + + #include "generic.h" + #include "soc.h" +@@ -34,7 +33,6 @@ static void __init at91rm9200_dt_device_init(void) + + of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); + +- arm_pm_idle = at91rm9200_idle; + at91rm9200_pm_init(); + } + +diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c +index e47a2093a0e7..d2bede665a1b 100644 +--- a/arch/arm/mach-at91/at91sam9.c ++++ b/arch/arm/mach-at91/at91sam9.c +@@ -62,8 +62,6 @@ static void __init at91sam9_common_init(void) + soc_dev = soc_device_to_device(soc); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev); +- +- arm_pm_idle = at91sam9_idle; + } + + static void __init at91sam9_dt_device_init(void) +diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h +index b0fa7dc7286d..28ca57a2060f 100644 +--- a/arch/arm/mach-at91/generic.h ++++ b/arch/arm/mach-at91/generic.h +@@ -11,27 +11,18 @@ + #ifndef _AT91_GENERIC_H + #define _AT91_GENERIC_H + +-#include +-#include +- +- /* Map io */ +-extern void __init at91_map_io(void); +-extern void __init at91_alt_map_io(void); +- +-/* idle */ +-extern void at91rm9200_idle(void); +-extern void at91sam9_idle(void); +- + #ifdef CONFIG_PM + extern void __init at91rm9200_pm_init(void); + extern void __init at91sam9260_pm_init(void); + extern void __init at91sam9g45_pm_init(void); + extern void __init at91sam9x5_pm_init(void); ++extern void __init sama5_pm_init(void); + #else + static inline void __init at91rm9200_pm_init(void) { } + static inline void __init at91sam9260_pm_init(void) { } + static inline void __init at91sam9g45_pm_init(void) { } + static inline void __init at91sam9x5_pm_init(void) { } ++static inline void __init sama5_pm_init(void) { } + #endif + + #endif /* _AT91_GENERIC_H */ +diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c +index 5062699cbb12..3be82cf983dd 100644 +--- a/arch/arm/mach-at91/pm.c ++++ b/arch/arm/mach-at91/pm.c +@@ -31,10 +31,13 @@ + #include + #include + #include ++#include + + #include "generic.h" + #include "pm.h" + ++static void __iomem *pmc; ++ + /* + * FIXME: this is needed to communicate between the pinctrl driver and + * the PM implementation in the machine. Possibly part of the PM +@@ -85,7 +88,7 @@ static int at91_pm_verify_clocks(void) + unsigned long scsr; + int i; + +- scsr = at91_pmc_read(AT91_PMC_SCSR); ++ scsr = readl(pmc + AT91_PMC_SCSR); + + /* USB must not be using PLLB */ + if ((scsr & at91_pm_data.uhp_udp_mask) != 0) { +@@ -99,8 +102,7 @@ static int at91_pm_verify_clocks(void) + + if ((scsr & (AT91_PMC_PCK0 << i)) == 0) + continue; +- +- css = at91_pmc_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; ++ css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + if (css != AT91_PMC_CSS_SLOW) { + pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); + return 0; +@@ -143,8 +145,8 @@ static void at91_pm_suspend(suspend_state_t state) + flush_cache_all(); + outer_disable(); + +- at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0], +- at91_ramc_base[1], pm_data); ++ at91_suspend_sram_fn(pmc, at91_ramc_base[0], ++ at91_ramc_base[1], pm_data); + + outer_resume(); + } +@@ -348,6 +350,21 @@ static __init void at91_dt_ramc(void) + at91_pm_set_standby(standby); + } + ++void at91rm9200_idle(void) ++{ ++ /* ++ * Disable the processor clock. The processor will be automatically ++ * re-enabled by an interrupt or by a reset. ++ */ ++ writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); ++} ++ ++void at91sam9_idle(void) ++{ ++ writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR); ++ cpu_do_idle(); ++} ++ + static void __init at91_pm_sram_init(void) + { + struct gen_pool *sram_pool; +@@ -394,13 +411,36 @@ static void __init at91_pm_sram_init(void) + &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); + } + +-static void __init at91_pm_init(void) ++static const struct of_device_id atmel_pmc_ids[] __initconst = { ++ { .compatible = "atmel,at91rm9200-pmc" }, ++ { .compatible = "atmel,at91sam9260-pmc" }, ++ { .compatible = "atmel,at91sam9g45-pmc" }, ++ { .compatible = "atmel,at91sam9n12-pmc" }, ++ { .compatible = "atmel,at91sam9x5-pmc" }, ++ { .compatible = "atmel,sama5d3-pmc" }, ++ { .compatible = "atmel,sama5d2-pmc" }, ++ { /* sentinel */ }, ++}; ++ ++static void __init at91_pm_init(void (*pm_idle)(void)) + { +- at91_pm_sram_init(); ++ struct device_node *pmc_np; + + if (at91_cpuidle_device.dev.platform_data) + platform_device_register(&at91_cpuidle_device); + ++ pmc_np = of_find_matching_node(NULL, atmel_pmc_ids); ++ pmc = of_iomap(pmc_np, 0); ++ if (!pmc) { ++ pr_err("AT91: PM not supported, PMC not found\n"); ++ return; ++ } ++ ++ if (pm_idle) ++ arm_pm_idle = pm_idle; ++ ++ at91_pm_sram_init(); ++ + if (at91_suspend_sram_fn) + suspend_set_ops(&at91_pm_ops); + else +@@ -419,7 +459,7 @@ void __init at91rm9200_pm_init(void) + at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP; + at91_pm_data.memctrl = AT91_MEMCTRL_MC; + +- at91_pm_init(); ++ at91_pm_init(at91rm9200_idle); + } + + void __init at91sam9260_pm_init(void) +@@ -427,7 +467,7 @@ void __init at91sam9260_pm_init(void) + at91_dt_ramc(); + at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC; + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; +- return at91_pm_init(); ++ at91_pm_init(at91sam9_idle); + } + + void __init at91sam9g45_pm_init(void) +@@ -435,7 +475,7 @@ void __init at91sam9g45_pm_init(void) + at91_dt_ramc(); + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP; + at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; +- return at91_pm_init(); ++ at91_pm_init(at91sam9_idle); + } + + void __init at91sam9x5_pm_init(void) +@@ -443,5 +483,13 @@ void __init at91sam9x5_pm_init(void) + at91_dt_ramc(); + at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; + at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; +- return at91_pm_init(); ++ at91_pm_init(at91sam9_idle); ++} ++ ++void __init sama5_pm_init(void) ++{ ++ at91_dt_ramc(); ++ at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP; ++ at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR; ++ at91_pm_init(NULL); + } +diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c +index 41d829d8e7d5..3755da6decf5 100644 +--- a/arch/arm/mach-at91/sama5.c ++++ b/arch/arm/mach-at91/sama5.c +@@ -49