summaryrefslogtreecommitdiff
path: root/target/linux
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2015-06-03 16:53:31 -0500
committerWaldemar Brodkorb <wbx@openadk.org>2015-06-03 16:54:21 -0500
commite38204a8348094cf703ad70680d4b50b865759e0 (patch)
tree1ebb31885a3d30075c030c8c42ce3c678f96689f /target/linux
parentf81fe6f2d52cc051f11a9be53e937b242390a2d1 (diff)
update kernel to 3.18.14, refresh realtime and rpi patches
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/patches/3.18.14/bsd-compatibility.patch (renamed from target/linux/patches/3.18.12/bsd-compatibility.patch)0
-rw-r--r--target/linux/patches/3.18.14/cleankernel.patch (renamed from target/linux/patches/3.18.12/cleankernel.patch)0
-rw-r--r--target/linux/patches/3.18.14/cris-header.patch (renamed from target/linux/patches/3.18.12/cris-header.patch)0
-rw-r--r--target/linux/patches/3.18.14/cris-initramfs.patch (renamed from target/linux/patches/3.18.12/cris-initramfs.patch)0
-rw-r--r--target/linux/patches/3.18.14/defaults.patch (renamed from target/linux/patches/3.18.12/defaults.patch)0
-rw-r--r--target/linux/patches/3.18.14/export-symbol-for-exmap.patch (renamed from target/linux/patches/3.18.12/export-symbol-for-exmap.patch)0
-rw-r--r--target/linux/patches/3.18.14/fblogo.patch (renamed from target/linux/patches/3.18.12/fblogo.patch)0
-rw-r--r--target/linux/patches/3.18.14/gemalto.patch (renamed from target/linux/patches/3.18.12/gemalto.patch)0
-rw-r--r--target/linux/patches/3.18.14/initramfs-nosizelimit.patch (renamed from target/linux/patches/3.18.12/initramfs-nosizelimit.patch)0
-rw-r--r--target/linux/patches/3.18.14/lemote-rfkill.patch (renamed from target/linux/patches/3.18.12/lemote-rfkill.patch)0
-rw-r--r--target/linux/patches/3.18.14/microblaze-ethernet.patch (renamed from target/linux/patches/3.18.12/microblaze-ethernet.patch)0
-rw-r--r--target/linux/patches/3.18.14/mkpiggy.patch (renamed from target/linux/patches/3.18.12/mkpiggy.patch)0
-rw-r--r--target/linux/patches/3.18.14/mtd-rootfs.patch (renamed from target/linux/patches/3.18.12/mtd-rootfs.patch)0
-rw-r--r--target/linux/patches/3.18.14/nfsv3-tcp.patch (renamed from target/linux/patches/3.18.12/nfsv3-tcp.patch)0
-rw-r--r--target/linux/patches/3.18.14/non-static.patch (renamed from target/linux/patches/3.18.12/non-static.patch)0
-rw-r--r--target/linux/patches/3.18.14/ppc64-missing-zlib.patch (renamed from target/linux/patches/3.18.12/ppc64-missing-zlib.patch)0
-rw-r--r--target/linux/patches/3.18.14/realtime.patch (renamed from target/linux/patches/3.18.12/realtime.patch)25536
-rw-r--r--target/linux/patches/3.18.14/regmap-bool.patch (renamed from target/linux/patches/3.18.12/regmap-bool.patch)0
-rw-r--r--target/linux/patches/3.18.14/relocs.patch (renamed from target/linux/patches/3.18.12/relocs.patch)0
-rw-r--r--target/linux/patches/3.18.14/sgidefs.patch (renamed from target/linux/patches/3.18.12/sgidefs.patch)0
-rw-r--r--target/linux/patches/3.18.14/sortext.patch (renamed from target/linux/patches/3.18.12/sortext.patch)0
-rw-r--r--target/linux/patches/3.18.14/startup.patch (renamed from target/linux/patches/3.18.12/startup.patch)0
-rw-r--r--target/linux/patches/3.18.14/wlan-cf.patch (renamed from target/linux/patches/3.18.12/wlan-cf.patch)0
-rw-r--r--target/linux/patches/3.18.14/xargs.patch (renamed from target/linux/patches/3.18.12/xargs.patch)0
-rw-r--r--target/linux/patches/3.18.14/yaffs2.patch (renamed from target/linux/patches/3.18.12/yaffs2.patch)0
25 files changed, 13026 insertions, 12510 deletions
diff --git a/target/linux/patches/3.18.12/bsd-compatibility.patch b/target/linux/patches/3.18.14/bsd-compatibility.patch
index b954b658f..b954b658f 100644
--- a/target/linux/patches/3.18.12/bsd-compatibility.patch
+++ b/target/linux/patches/3.18.14/bsd-compatibility.patch
diff --git a/target/linux/patches/3.18.12/cleankernel.patch b/target/linux/patches/3.18.14/cleankernel.patch
index d8c055dc3..d8c055dc3 100644
--- a/target/linux/patches/3.18.12/cleankernel.patch
+++ b/target/linux/patches/3.18.14/cleankernel.patch
diff --git a/target/linux/patches/3.18.12/cris-header.patch b/target/linux/patches/3.18.14/cris-header.patch
index 3db07e530..3db07e530 100644
--- a/target/linux/patches/3.18.12/cris-header.patch
+++ b/target/linux/patches/3.18.14/cris-header.patch
diff --git a/target/linux/patches/3.18.12/cris-initramfs.patch b/target/linux/patches/3.18.14/cris-initramfs.patch
index b709e705e..b709e705e 100644
--- a/target/linux/patches/3.18.12/cris-initramfs.patch
+++ b/target/linux/patches/3.18.14/cris-initramfs.patch
diff --git a/target/linux/patches/3.18.12/defaults.patch b/target/linux/patches/3.18.14/defaults.patch
index 6cdca084e..6cdca084e 100644
--- a/target/linux/patches/3.18.12/defaults.patch
+++ b/target/linux/patches/3.18.14/defaults.patch
diff --git a/target/linux/patches/3.18.12/export-symbol-for-exmap.patch b/target/linux/patches/3.18.14/export-symbol-for-exmap.patch
index 4f0fc8449..4f0fc8449 100644
--- a/target/linux/patches/3.18.12/export-symbol-for-exmap.patch
+++ b/target/linux/patches/3.18.14/export-symbol-for-exmap.patch
diff --git a/target/linux/patches/3.18.12/fblogo.patch b/target/linux/patches/3.18.14/fblogo.patch
index 5b9070242..5b9070242 100644
--- a/target/linux/patches/3.18.12/fblogo.patch
+++ b/target/linux/patches/3.18.14/fblogo.patch
diff --git a/target/linux/patches/3.18.12/gemalto.patch b/target/linux/patches/3.18.14/gemalto.patch
index 65f7af1d7..65f7af1d7 100644
--- a/target/linux/patches/3.18.12/gemalto.patch
+++ b/target/linux/patches/3.18.14/gemalto.patch
diff --git a/target/linux/patches/3.18.12/initramfs-nosizelimit.patch b/target/linux/patches/3.18.14/initramfs-nosizelimit.patch
index 40d2f6bd8..40d2f6bd8 100644
--- a/target/linux/patches/3.18.12/initramfs-nosizelimit.patch
+++ b/target/linux/patches/3.18.14/initramfs-nosizelimit.patch
diff --git a/target/linux/patches/3.18.12/lemote-rfkill.patch b/target/linux/patches/3.18.14/lemote-rfkill.patch
index a61488434..a61488434 100644
--- a/target/linux/patches/3.18.12/lemote-rfkill.patch
+++ b/target/linux/patches/3.18.14/lemote-rfkill.patch
diff --git a/target/linux/patches/3.18.12/microblaze-ethernet.patch b/target/linux/patches/3.18.14/microblaze-ethernet.patch
index 742ab477e..742ab477e 100644
--- a/target/linux/patches/3.18.12/microblaze-ethernet.patch
+++ b/target/linux/patches/3.18.14/microblaze-ethernet.patch
diff --git a/target/linux/patches/3.18.12/mkpiggy.patch b/target/linux/patches/3.18.14/mkpiggy.patch
index 751678b74..751678b74 100644
--- a/target/linux/patches/3.18.12/mkpiggy.patch
+++ b/target/linux/patches/3.18.14/mkpiggy.patch
diff --git a/target/linux/patches/3.18.12/mtd-rootfs.patch b/target/linux/patches/3.18.14/mtd-rootfs.patch
index 775d5fc80..775d5fc80 100644
--- a/target/linux/patches/3.18.12/mtd-rootfs.patch
+++ b/target/linux/patches/3.18.14/mtd-rootfs.patch
diff --git a/target/linux/patches/3.18.12/nfsv3-tcp.patch b/target/linux/patches/3.18.14/nfsv3-tcp.patch
index d5e07e1c2..d5e07e1c2 100644
--- a/target/linux/patches/3.18.12/nfsv3-tcp.patch
+++ b/target/linux/patches/3.18.14/nfsv3-tcp.patch
diff --git a/target/linux/patches/3.18.12/non-static.patch b/target/linux/patches/3.18.14/non-static.patch
index a967703d0..a967703d0 100644
--- a/target/linux/patches/3.18.12/non-static.patch
+++ b/target/linux/patches/3.18.14/non-static.patch
diff --git a/target/linux/patches/3.18.12/ppc64-missing-zlib.patch b/target/linux/patches/3.18.14/ppc64-missing-zlib.patch
index c6e0616be..c6e0616be 100644
--- a/target/linux/patches/3.18.12/ppc64-missing-zlib.patch
+++ b/target/linux/patches/3.18.14/ppc64-missing-zlib.patch
diff --git a/target/linux/patches/3.18.12/realtime.patch b/target/linux/patches/3.18.14/realtime.patch
index e91381e07..28b9b271c 100644
--- a/target/linux/patches/3.18.12/realtime.patch
+++ b/target/linux/patches/3.18.14/realtime.patch
@@ -1,6 +1,6 @@
-diff -Nur linux-3.18.12.orig/arch/alpha/mm/fault.c linux-3.18.12/arch/alpha/mm/fault.c
---- linux-3.18.12.orig/arch/alpha/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/alpha/mm/fault.c 2015-04-26 13:32:22.351684003 -0500
+diff -Nur linux-3.18.14.orig/arch/alpha/mm/fault.c linux-3.18.14-rt/arch/alpha/mm/fault.c
+--- linux-3.18.14.orig/arch/alpha/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/alpha/mm/fault.c 2015-05-31 15:32:45.517635394 -0500
@@ -107,7 +107,7 @@
/* If we're in an interrupt context, or have no user context,
@@ -10,9 +10,9 @@ diff -Nur linux-3.18.12.orig/arch/alpha/mm/fault.c linux-3.18.12/arch/alpha/mm/f
goto no_context;
#ifdef CONFIG_ALPHA_LARGE_VMALLOC
-diff -Nur linux-3.18.12.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.12/arch/arm/include/asm/cmpxchg.h
---- linux-3.18.12.orig/arch/arm/include/asm/cmpxchg.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/include/asm/cmpxchg.h 2015-04-26 13:32:22.351684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.14-rt/arch/arm/include/asm/cmpxchg.h
+--- linux-3.18.14.orig/arch/arm/include/asm/cmpxchg.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/include/asm/cmpxchg.h 2015-05-31 15:32:45.557635393 -0500
@@ -129,6 +129,8 @@
#else /* min ARCH >= ARMv6 */
@@ -22,9 +22,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.12/arch/a
extern void __bad_cmpxchg(volatile void *ptr, int size);
/*
-diff -Nur linux-3.18.12.orig/arch/arm/include/asm/futex.h linux-3.18.12/arch/arm/include/asm/futex.h
---- linux-3.18.12.orig/arch/arm/include/asm/futex.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/include/asm/futex.h 2015-04-26 13:32:22.351684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/include/asm/futex.h linux-3.18.14-rt/arch/arm/include/asm/futex.h
+--- linux-3.18.14.orig/arch/arm/include/asm/futex.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/include/asm/futex.h 2015-05-31 15:32:45.561635393 -0500
@@ -93,6 +93,8 @@
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
return -EFAULT;
@@ -43,9 +43,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/futex.h linux-3.18.12/arch/arm
return ret;
}
-diff -Nur linux-3.18.12.orig/arch/arm/include/asm/switch_to.h linux-3.18.12/arch/arm/include/asm/switch_to.h
---- linux-3.18.12.orig/arch/arm/include/asm/switch_to.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/include/asm/switch_to.h 2015-04-26 13:32:22.355684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/include/asm/switch_to.h linux-3.18.14-rt/arch/arm/include/asm/switch_to.h
+--- linux-3.18.14.orig/arch/arm/include/asm/switch_to.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/include/asm/switch_to.h 2015-05-31 15:32:45.565635393 -0500
@@ -3,6 +3,13 @@
#include <linux/thread_info.h>
@@ -68,9 +68,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/switch_to.h linux-3.18.12/arch
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
} while (0)
-diff -Nur linux-3.18.12.orig/arch/arm/include/asm/thread_info.h linux-3.18.12/arch/arm/include/asm/thread_info.h
---- linux-3.18.12.orig/arch/arm/include/asm/thread_info.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/include/asm/thread_info.h 2015-04-26 13:32:22.355684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/include/asm/thread_info.h linux-3.18.14-rt/arch/arm/include/asm/thread_info.h
+--- linux-3.18.14.orig/arch/arm/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/include/asm/thread_info.h 2015-05-31 15:32:45.585635393 -0500
@@ -51,6 +51,7 @@
struct thread_info {
unsigned long flags; /* low level flags */
@@ -95,9 +95,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/thread_info.h linux-3.18.12/ar
#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-3.18.12.orig/arch/arm/Kconfig linux-3.18.12/arch/arm/Kconfig
---- linux-3.18.12.orig/arch/arm/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/Kconfig 2015-04-26 13:32:22.351684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/Kconfig linux-3.18.14-rt/arch/arm/Kconfig
+--- linux-3.18.14.orig/arch/arm/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/Kconfig 2015-05-31 15:32:45.529635394 -0500
@@ -62,6 +62,7 @@
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
@@ -106,9 +106,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/Kconfig linux-3.18.12/arch/arm/Kconfig
select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE)
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_SYSCALL_TRACEPOINTS
-diff -Nur linux-3.18.12.orig/arch/arm/kernel/asm-offsets.c linux-3.18.12/arch/arm/kernel/asm-offsets.c
---- linux-3.18.12.orig/arch/arm/kernel/asm-offsets.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kernel/asm-offsets.c 2015-04-26 13:32:22.355684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/kernel/asm-offsets.c linux-3.18.14-rt/arch/arm/kernel/asm-offsets.c
+--- linux-3.18.14.orig/arch/arm/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kernel/asm-offsets.c 2015-05-31 15:32:45.605635393 -0500
@@ -64,6 +64,7 @@
BLANK();
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
@@ -117,9 +117,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/asm-offsets.c linux-3.18.12/arch/ar
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
-diff -Nur linux-3.18.12.orig/arch/arm/kernel/entry-armv.S linux-3.18.12/arch/arm/kernel/entry-armv.S
---- linux-3.18.12.orig/arch/arm/kernel/entry-armv.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kernel/entry-armv.S 2015-04-26 13:32:22.355684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/kernel/entry-armv.S linux-3.18.14-rt/arch/arm/kernel/entry-armv.S
+--- linux-3.18.14.orig/arch/arm/kernel/entry-armv.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kernel/entry-armv.S 2015-05-31 15:32:45.613635393 -0500
@@ -207,11 +207,18 @@
#ifdef CONFIG_PREEMPT
get_thread_info tsk
@@ -150,10 +150,10 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/entry-armv.S linux-3.18.12/arch/arm
reteq r8 @ go again
b 1b
#endif
-diff -Nur linux-3.18.12.orig/arch/arm/kernel/process.c linux-3.18.12/arch/arm/kernel/process.c
---- linux-3.18.12.orig/arch/arm/kernel/process.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kernel/process.c 2015-04-26 13:32:22.355684003 -0500
-@@ -431,6 +431,30 @@
+diff -Nur linux-3.18.14.orig/arch/arm/kernel/process.c linux-3.18.14-rt/arch/arm/kernel/process.c
+--- linux-3.18.14.orig/arch/arm/kernel/process.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kernel/process.c 2015-05-31 15:32:45.617635393 -0500
+@@ -437,6 +437,30 @@
}
#ifdef CONFIG_MMU
@@ -184,9 +184,573 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/process.c linux-3.18.12/arch/arm/ke
#ifdef CONFIG_KUSER_HELPERS
/*
* The vectors page is always readable from user space for the
-diff -Nur linux-3.18.12.orig/arch/arm/kernel/signal.c linux-3.18.12/arch/arm/kernel/signal.c
---- linux-3.18.12.orig/arch/arm/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kernel/signal.c 2015-04-26 13:32:22.359684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/kernel/process.c.orig linux-3.18.14-rt/arch/arm/kernel/process.c.orig
+--- linux-3.18.14.orig/arch/arm/kernel/process.c.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/arch/arm/kernel/process.c.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,560 @@
++/*
++ * linux/arch/arm/kernel/process.c
++ *
++ * Copyright (C) 1996-2000 Russell King - Converted to ARM.
++ * Original Copyright (C) 1995 Linus Torvalds
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <stdarg.h>
++
++#include <linux/export.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/user.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/init.h>
++#include <linux/cpu.h>
++#include <linux/elfcore.h>
++#include <linux/pm.h>
++#include <linux/tick.h>
++#include <linux/utsname.h>
++#include <linux/uaccess.h>
++#include <linux/random.h>
++#include <linux/hw_breakpoint.h>
++#include <linux/leds.h>
++#include <linux/reboot.h>
++
++#include <asm/cacheflush.h>
++#include <asm/idmap.h>
++#include <asm/processor.h>
++#include <asm/thread_notify.h>
++#include <asm/stacktrace.h>
++#include <asm/system_misc.h>
++#include <asm/mach/time.h>
++#include <asm/tls.h>
++#include "reboot.h"
++
++#ifdef CONFIG_CC_STACKPROTECTOR
++#include <linux/stackprotector.h>
++unsigned long __stack_chk_guard __read_mostly;
++EXPORT_SYMBOL(__stack_chk_guard);
++#endif
++
++static const char *processor_modes[] __maybe_unused = {
++ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
++ "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
++ "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
++ "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
++};
++
++static const char *isa_modes[] __maybe_unused = {
++ "ARM" , "Thumb" , "Jazelle", "ThumbEE"
++};
++
++extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
++typedef void (*phys_reset_t)(unsigned long);
++
++/*
++ * A temporary stack to use for CPU reset. This is static so that we
++ * don't clobber it with the identity mapping. When running with this
++ * stack, any references to the current task *will not work* so you
++ * should really do as little as possible before jumping to your reset
++ * code.
++ */
++static u64 soft_restart_stack[16];
++
++static void __soft_restart(void *addr)
++{
++ phys_reset_t phys_reset;
++
++ /* Take out a flat memory mapping. */
++ setup_mm_for_reboot();
++
++ /* Clean and invalidate caches */
++ flush_cache_all();
++
++ /* Turn off caching */
++ cpu_proc_fin();
++
++ /* Push out any further dirty data, and ensure cache is empty */
++ flush_cache_all();
++
++ /* Switch to the identity mapping. */
++ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
++ phys_reset((unsigned long)addr);
++
++ /* Should never get here. */
++ BUG();
++}
++
++void _soft_restart(unsigned long addr, bool disable_l2)
++{
++ u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
++
++ /* Disable interrupts first */
++ raw_local_irq_disable();
++ local_fiq_disable();
++
++ /* Disable the L2 if we're the last man standing. */
++ if (disable_l2)
++ outer_disable();
++
++ /* Change to the new stack and continue with the reset. */
++ call_with_stack(__soft_restart, (void *)addr, (void *)stack);
++
++ /* Should never get here. */
++ BUG();
++}
++
++void soft_restart(unsigned long addr)
++{
++ _soft_restart(addr, num_online_cpus() == 1);
++}
++
++/*
++ * Function pointers to optional machine specific functions
++ */
++void (*pm_power_off)(void);
++EXPORT_SYMBOL(pm_power_off);
++
++void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
++
++/*
++ * This is our default idle handler.
++ */
++
++void (*arm_pm_idle)(void);
++
++/*
++ * Called from the core idle loop.
++ */
++
++void arch_cpu_idle(void)
++{
++ if (arm_pm_idle)
++ arm_pm_idle();
++ else
++ cpu_do_idle();
++ local_irq_enable();
++}
++
++void arch_cpu_idle_prepare(void)
++{
++ local_fiq_enable();
++}
++
++void arch_cpu_idle_enter(void)
++{
++ ledtrig_cpu(CPU_LED_IDLE_START);
++#ifdef CONFIG_PL310_ERRATA_769419
++ wmb();
++#endif
++}
++
++void arch_cpu_idle_exit(void)
++{
++ ledtrig_cpu(CPU_LED_IDLE_END);
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++void arch_cpu_idle_dead(void)
++{
++ cpu_die();
++}
++#endif
++
++/*
++ * Called by kexec, immediately prior to machine_kexec().
++ *
++ * This must completely disable all secondary CPUs; simply causing those CPUs
++ * to execute e.g. a RAM-based pin loop is not sufficient. This allows the
++ * kexec'd kernel to use any and all RAM as it sees fit, without having to
++ * avoid any code or data used by any SW CPU pin loop. The CPU hotplug
++ * functionality embodied in disable_nonboot_cpus() to achieve this.
++ */
++void machine_shutdown(void)
++{
++ disable_nonboot_cpus();
++}
++
++/*
++ * Halting simply requires that the secondary CPUs stop performing any
++ * activity (executing tasks, handling interrupts). smp_send_stop()
++ * achieves this.
++ */
++void machine_halt(void)
++{
++ local_irq_disable();
++ smp_send_stop();
++
++ local_irq_disable();
++ while (1);
++}
++
++/*
++ * Power-off simply requires that the secondary CPUs stop performing any
++ * activity (executing tasks, handling interrupts). smp_send_stop()
++ * achieves this. When the system power is turned off, it will take all CPUs
++ * with it.
++ */
++void machine_power_off(void)
++{
++ local_irq_disable();
++ smp_send_stop();
++
++ if (pm_power_off)
++ pm_power_off();
++}
++
++/*
++ * Restart requires that the secondary CPUs stop performing any activity
++ * while the primary CPU resets the system. Systems with a single CPU can
++ * use soft_restart() as their machine descriptor's .restart hook, since that
++ * will cause the only available CPU to reset. Systems with multiple CPUs must
++ * provide a HW restart implementation, to ensure that all CPUs reset at once.
++ * This is required so that any code running after reset on the primary CPU
++ * doesn't have to co-ordinate with other CPUs to ensure they aren't still
++ * executing pre-reset code, and using RAM that the primary CPU's code wishes
++ * to use. Implementing such co-ordination would be essentially impossible.
++ */
++void machine_restart(char *cmd)
++{
++ local_irq_disable();
++ smp_send_stop();
++
++ if (arm_pm_restart)
++ arm_pm_restart(reboot_mode, cmd);
++ else
++ do_kernel_restart(cmd);
++
++ /* Give a grace period for failure to restart of 1s */
++ mdelay(1000);
++
++ /* Whoops - the platform was unable to reboot. Tell the user! */
++ printk("Reboot failed -- System halted\n");
++ local_irq_disable();
++ while (1);
++}
++
++void __show_regs(struct pt_regs *regs)
++{
++ unsigned long flags;
++ char buf[64];
++
++ show_regs_print_info(KERN_DEFAULT);
++
++ print_symbol("PC is at %s\n", instruction_pointer(regs));
++ print_symbol("LR is at %s\n", regs->ARM_lr);
++ printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n"
++ "sp : %08lx ip : %08lx fp : %08lx\n",
++ regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
++ regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
++ printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
++ regs->ARM_r10, regs->ARM_r9,
++ regs->ARM_r8);
++ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
++ regs->ARM_r7, regs->ARM_r6,
++ regs->ARM_r5, regs->ARM_r4);
++ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
++ regs->ARM_r3, regs->ARM_r2,
++ regs->ARM_r1, regs->ARM_r0);
++
++ flags = regs->ARM_cpsr;
++ buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
++ buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
++ buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
++ buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
++ buf[4] = '\0';
++
++#ifndef CONFIG_CPU_V7M
++ printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n",
++ buf, interrupts_enabled(regs) ? "n" : "ff",
++ fast_interrupts_enabled(regs) ? "n" : "ff",
++ processor_modes[processor_mode(regs)],
++ isa_modes[isa_mode(regs)],
++ get_fs() == get_ds() ? "kernel" : "user");
++#else
++ printk("xPSR: %08lx\n", regs->ARM_cpsr);
++#endif
++
++#ifdef CONFIG_CPU_CP15
++ {
++ unsigned int ctrl;
++
++ buf[0] = '\0';
++#ifdef CONFIG_CPU_CP15_MMU
++ {
++ unsigned int transbase, dac;
++ asm("mrc p15, 0, %0, c2, c0\n\t"
++ "mrc p15, 0, %1, c3, c0\n"
++ : "=r" (transbase), "=r" (dac));
++ snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x",
++ transbase, dac);
++ }
++#endif
++ asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));
++
++ printk("Control: %08x%s\n", ctrl, buf);
++ }
++#endif
++}
++
++void show_regs(struct pt_regs * regs)
++{
++ __show_regs(regs);
++ dump_stack();
++}
++
++ATOMIC_NOTIFIER_HEAD(thread_notify_head);
++
++EXPORT_SYMBOL_GPL(thread_notify_head);
++
++/*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++ thread_notify(THREAD_NOTIFY_EXIT, current_thread_info());
++}
++
++void flush_thread(void)
++{
++ struct thread_info *thread = current_thread_info();
++ struct task_struct *tsk = current;
++
++ flush_ptrace_hw_breakpoint(tsk);
++
++ memset(thread->used_cp, 0, sizeof(thread->used_cp));
++ memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
++ memset(&thread->fpstate, 0, sizeof(union fp_state));
++
++ flush_tls();
++
++ thread_notify(THREAD_NOTIFY_FLUSH, thread);
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++}
++
++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
++
++int
++copy_thread(unsigned long clone_flags, unsigned long stack_start,
++ unsigned long stk_sz, struct task_struct *p)
++{
++ struct thread_info *thread = task_thread_info(p);
++ struct pt_regs *childregs = task_pt_regs(p);
++
++ memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
++
++ if (likely(!(p->flags & PF_KTHREAD))) {
++ *childregs = *current_pt_regs();
++ childregs->ARM_r0 = 0;
++ if (stack_start)
++ childregs->ARM_sp = stack_start;
++ } else {
++ memset(childregs, 0, sizeof(struct pt_regs));
++ thread->cpu_context.r4 = stk_sz;
++ thread->cpu_context.r5 = stack_start;
++ childregs->ARM_cpsr = SVC_MODE;
++ }
++ thread->cpu_context.pc = (unsigned long)ret_from_fork;
++ thread->cpu_context.sp = (unsigned long)childregs;
++
++ clear_ptrace_hw_breakpoint(p);
++
++ if (clone_flags & CLONE_SETTLS)
++ thread->tp_value[0] = childregs->ARM_r3;
++ thread->tp_value[1] = get_tpuser();
++
++ thread_notify(THREAD_NOTIFY_COPY, thread);
++
++ return 0;
++}
++
++/*
++ * Fill in the task's elfregs structure for a core dump.
++ */
++int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
++{
++ elf_core_copy_regs(elfregs, task_pt_regs(t));
++ return 1;
++}
++
++/*
++ * fill in the fpe structure for a core dump...
++ */
++int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
++{
++ struct thread_info *thread = current_thread_info();
++ int used_math = thread->used_cp[1] | thread->used_cp[2];
++
++ if (used_math)
++ memcpy(fp, &thread->fpstate.soft, sizeof (*fp));
++
++ return used_math != 0;
++}
++EXPORT_SYMBOL(dump_fpu);
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ struct stackframe frame;
++ unsigned long stack_page;
++ int count = 0;
++ if (!p || p == current || p->state == TASK_RUNNING)
++ return 0;
++
++ frame.fp = thread_saved_fp(p);
++ frame.sp = thread_saved_sp(p);
++ frame.lr = 0; /* recovered from the stack */
++ frame.pc = thread_saved_pc(p);
++ stack_page = (unsigned long)task_stack_page(p);
++ do {
++ if (frame.sp < stack_page ||
++ frame.sp >= stack_page + THREAD_SIZE ||
++ unwind_frame(&frame) < 0)
++ return 0;
++ if (!in_sched_functions(frame.pc))
++ return frame.pc;
++ } while (count ++ < 16);
++ return 0;
++}
++
++unsigned long arch_randomize_brk(struct mm_struct *mm)
++{
++ unsigned long range_end = mm->brk + 0x02000000;
++ return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
++}
++
++#ifdef CONFIG_MMU
++#ifdef CONFIG_KUSER_HELPERS
++/*
++ * The vectors page is always readable from user space for the
++ * atomic helpers. Insert it into the gate_vma so that it is visible
++ * through ptrace and /proc/<pid>/mem.
++ */
++static struct vm_area_struct gate_vma = {
++ .vm_start = 0xffff0000,
++ .vm_end = 0xffff0000 + PAGE_SIZE,
++ .vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
++};
++
++static int __init gate_vma_init(void)
++{
++ gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
++ return 0;
++}
++arch_initcall(gate_vma_init);
++
++struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
++{
++ return &gate_vma;
++}
++
++int in_gate_area(struct mm_struct *mm, unsigned long addr)
++{
++ return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end);
++}
++
++int in_gate_area_no_mm(unsigned long addr)
++{
++ return in_gate_area(NULL, addr);
++}
++#define is_gate_vma(vma) ((vma) == &gate_vma)
++#else
++#define is_gate_vma(vma) 0
++#endif
++
++const char *arch_vma_name(struct vm_area_struct *vma)
++{
++ return is_gate_vma(vma) ? "[vectors]" : NULL;
++}
++
++/* If possible, provide a placement hint at a random offset from the
++ * stack for the signal page.
++ */
++static unsigned long sigpage_addr(const struct mm_struct *mm,
++ unsigned int npages)
++{
++ unsigned long offset;
++ unsigned long first;
++ unsigned long last;
++ unsigned long addr;
++ unsigned int slots;
++
++ first = PAGE_ALIGN(mm->start_stack);
++
++ last = TASK_SIZE - (npages << PAGE_SHIFT);
++
++ /* No room after stack? */
++ if (first > last)
++ return 0;
++
++ /* Just enough room? */
++ if (first == last)
++ return first;
++
++ slots = ((last - first) >> PAGE_SHIFT) + 1;
++
++ offset = get_random_int() % slots;
++
++ addr = first + (offset << PAGE_SHIFT);
++
++ return addr;
++}
++
++static struct page *signal_page;
++extern struct page *get_signal_page(void);
++
++static const struct vm_special_mapping sigpage_mapping = {
++ .name = "[sigpage]",
++ .pages = &signal_page,
++};
++
++int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
++{
++ struct mm_struct *mm = current->mm;
++ struct vm_area_struct *vma;
++ unsigned long addr;
++ unsigned long hint;
++ int ret = 0;
++
++ if (!signal_page)
++ signal_page = get_signal_page();
++ if (!signal_page)
++ return -ENOMEM;
++
++ down_write(&mm->mmap_sem);
++ hint = sigpage_addr(mm, 1);
++ addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
++ if (IS_ERR_VALUE(addr)) {
++ ret = addr;
++ goto up_fail;
++ }
++
++ vma = _install_special_mapping(mm, addr, PAGE_SIZE,
++ VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
++ &sigpage_mapping);
++
++ if (IS_ERR(vma)) {
++ ret = PTR_ERR(vma);
++ goto up_fail;
++ }
++
++ mm->context.sigpage = addr;
++
++ up_fail:
++ up_write(&mm->mmap_sem);
++ return ret;
++}
++#endif
+diff -Nur linux-3.18.14.orig/arch/arm/kernel/signal.c linux-3.18.14-rt/arch/arm/kernel/signal.c
+--- linux-3.18.14.orig/arch/arm/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kernel/signal.c 2015-05-31 15:32:45.617635393 -0500
@@ -574,7 +574,8 @@
do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
{
@@ -197,9 +761,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/signal.c linux-3.18.12/arch/arm/ker
schedule();
} else {
if (unlikely(!user_mode(regs)))
-diff -Nur linux-3.18.12.orig/arch/arm/kernel/unwind.c linux-3.18.12/arch/arm/kernel/unwind.c
---- linux-3.18.12.orig/arch/arm/kernel/unwind.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kernel/unwind.c 2015-04-26 13:32:22.359684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/kernel/unwind.c linux-3.18.14-rt/arch/arm/kernel/unwind.c
+--- linux-3.18.14.orig/arch/arm/kernel/unwind.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kernel/unwind.c 2015-05-31 15:32:45.653635392 -0500
@@ -93,7 +93,7 @@
static const struct unwind_idx *__origin_unwind_idx;
extern const struct unwind_idx __stop_unwind_idx[];
@@ -251,10 +815,10 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/unwind.c linux-3.18.12/arch/arm/ker
kfree(tab);
}
-diff -Nur linux-3.18.12.orig/arch/arm/kvm/arm.c linux-3.18.12/arch/arm/kvm/arm.c
---- linux-3.18.12.orig/arch/arm/kvm/arm.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kvm/arm.c 2015-04-26 13:32:22.359684003 -0500
-@@ -441,9 +441,9 @@
+diff -Nur linux-3.18.14.orig/arch/arm/kvm/arm.c linux-3.18.14-rt/arch/arm/kvm/arm.c
+--- linux-3.18.14.orig/arch/arm/kvm/arm.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kvm/arm.c 2015-05-31 15:32:45.669635392 -0500
+@@ -455,9 +455,9 @@
static void vcpu_pause(struct kvm_vcpu *vcpu)
{
@@ -266,10 +830,1074 @@ diff -Nur linux-3.18.12.orig/arch/arm/kvm/arm.c linux-3.18.12/arch/arm/kvm/arm.c
}
static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
-diff -Nur linux-3.18.12.orig/arch/arm/kvm/psci.c linux-3.18.12/arch/arm/kvm/psci.c
---- linux-3.18.12.orig/arch/arm/kvm/psci.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/kvm/psci.c 2015-04-26 13:32:22.359684003 -0500
-@@ -66,7 +66,7 @@
+diff -Nur linux-3.18.14.orig/arch/arm/kvm/arm.c.orig linux-3.18.14-rt/arch/arm/kvm/arm.c.orig
+--- linux-3.18.14.orig/arch/arm/kvm/arm.c.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/arch/arm/kvm/arm.c.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,1060 @@
++/*
++ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
++ * Author: Christoffer Dall <c.dall@virtualopensystems.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License, version 2, as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include <linux/cpu.h>
++#include <linux/cpu_pm.h>
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/kvm_host.h>
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/fs.h>
++#include <linux/mman.h>
++#include <linux/sched.h>
++#include <linux/kvm.h>
++#include <trace/events/kvm.h>
++
++#define CREATE_TRACE_POINTS
++#include "trace.h"
++
++#include <asm/uaccess.h>
++#include <asm/ptrace.h>
++#include <asm/mman.h>
++#include <asm/tlbflush.h>
++#include <asm/cacheflush.h>
++#include <asm/virt.h>
++#include <asm/kvm_arm.h>
++#include <asm/kvm_asm.h>
++#include <asm/kvm_mmu.h>
++#include <asm/kvm_emulate.h>
++#include <asm/kvm_coproc.h>
++#include <asm/kvm_psci.h>
++
++#ifdef REQUIRES_VIRT
++__asm__(".arch_extension virt");
++#endif
++
++static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
++static kvm_cpu_context_t __percpu *kvm_host_cpu_state;
++static unsigned long hyp_default_vectors;
++
++/* Per-CPU variable containing the currently running vcpu. */
++static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
++
++/* The VMID used in the VTTBR */
++static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
++static u8 kvm_next_vmid;
++static DEFINE_SPINLOCK(kvm_vmid_lock);
++
++static bool vgic_present;
++
++static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
++{
++ BUG_ON(preemptible());
++ __this_cpu_write(kvm_arm_running_vcpu, vcpu);
++}
++
++/**
++ * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU.
++ * Must be called from non-preemptible context
++ */
++struct kvm_vcpu *kvm_arm_get_running_vcpu(void)
++{
++ BUG_ON(preemptible());
++ return __this_cpu_read(kvm_arm_running_vcpu);
++}
++
++/**
++ * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus.
++ */
++struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
++{
++ return &kvm_arm_running_vcpu;
++}
++
++int kvm_arch_hardware_enable(void)
++{
++ return 0;
++}
++
++int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
++{
++ return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
++}
++
++int kvm_arch_hardware_setup(void)
++{
++ return 0;
++}
++
++void kvm_arch_check_processor_compat(void *rtn)
++{
++ *(int *)rtn = 0;
++}
++
++
++/**
++ * kvm_arch_init_vm - initializes a VM data structure
++ * @kvm: pointer to the KVM struct
++ */
++int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
++{
++ int ret = 0;
++
++ if (type)
++ return -EINVAL;
++
++ ret = kvm_alloc_stage2_pgd(kvm);
++ if (ret)
++ goto out_fail_alloc;
++
++ ret = create_hyp_mappings(kvm, kvm + 1);
++ if (ret)
++ goto out_free_stage2_pgd;
++
++ kvm_timer_init(kvm);
++
++ /* Mark the initial VMID generation invalid */
++ kvm->arch.vmid_gen = 0;
++
++ return ret;
++out_free_stage2_pgd:
++ kvm_free_stage2_pgd(kvm);
++out_fail_alloc:
++ return ret;
++}
++
++int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
++{
++ return VM_FAULT_SIGBUS;
++}
++
++
++/**
++ * kvm_arch_destroy_vm - destroy the VM data structure
++ * @kvm: pointer to the KVM struct
++ */
++void kvm_arch_destroy_vm(struct kvm *kvm)
++{
++ int i;
++
++ kvm_free_stage2_pgd(kvm);
++
++ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
++ if (kvm->vcpus[i]) {
++ kvm_arch_vcpu_free(kvm->vcpus[i]);
++ kvm->vcpus[i] = NULL;
++ }
++ }
++
++ kvm_vgic_destroy(kvm);
++}
++
++int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
++{
++ int r;
++ switch (ext) {
++ case KVM_CAP_IRQCHIP:
++ r = vgic_present;
++ break;
++ case KVM_CAP_DEVICE_CTRL:
++ case KVM_CAP_USER_MEMORY:
++ case KVM_CAP_SYNC_MMU:
++ case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
++ case KVM_CAP_ONE_REG:
++ case KVM_CAP_ARM_PSCI:
++ case KVM_CAP_ARM_PSCI_0_2:
++ case KVM_CAP_READONLY_MEM:
++ r = 1;
++ break;
++ case KVM_CAP_COALESCED_MMIO:
++ r = KVM_COALESCED_MMIO_PAGE_OFFSET;
++ break;
++ case KVM_CAP_ARM_SET_DEVICE_ADDR:
++ r = 1;
++ break;
++ case KVM_CAP_NR_VCPUS:
++ r = num_online_cpus();
++ break;
++ case KVM_CAP_MAX_VCPUS:
++ r = KVM_MAX_VCPUS;
++ break;
++ default:
++ r = kvm_arch_dev_ioctl_check_extension(ext);
++ break;
++ }
++ return r;
++}
++
++long kvm_arch_dev_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ return -EINVAL;
++}
++
++
++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
++{
++ int err;
++ struct kvm_vcpu *vcpu;
++
++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) {
++ err = -EBUSY;
++ goto out;
++ }
++
++ vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
++ if (!vcpu) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ err = kvm_vcpu_init(vcpu, kvm, id);
++ if (err)
++ goto free_vcpu;
++
++ err = create_hyp_mappings(vcpu, vcpu + 1);
++ if (err)
++ goto vcpu_uninit;
++
++ return vcpu;
++vcpu_uninit:
++ kvm_vcpu_uninit(vcpu);
++free_vcpu:
++ kmem_cache_free(kvm_vcpu_cache, vcpu);
++out:
++ return ERR_PTR(err);
++}
++
++int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
++{
++ return 0;
++}
++
++void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
++{
++ kvm_mmu_free_memory_caches(vcpu);
++ kvm_timer_vcpu_terminate(vcpu);
++ kvm_vgic_vcpu_destroy(vcpu);
++ kmem_cache_free(kvm_vcpu_cache, vcpu);
++}
++
++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
++{
++ kvm_arch_vcpu_free(vcpu);
++}
++
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
++{
++ return 0;
++}
++
++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
++{
++ /* Force users to call KVM_ARM_VCPU_INIT */
++ vcpu->arch.target = -1;
++
++ /* Set up the timer */
++ kvm_timer_vcpu_init(vcpu);
++
++ return 0;
++}
++
++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
++{
++ vcpu->cpu = cpu;
++ vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state);
++
++ /*
++ * Check whether this vcpu requires the cache to be flushed on
++ * this physical CPU. This is a consequence of doing dcache
++ * operations by set/way on this vcpu. We do it here to be in
++ * a non-preemptible section.
++ */
++ if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush))
++ flush_cache_all(); /* We'd really want v7_flush_dcache_all() */
++
++ kvm_arm_set_running_vcpu(vcpu);
++}
++
++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
++{
++ /*
++ * The arch-generic KVM code expects the cpu field of a vcpu to be -1
++ * if the vcpu is no longer assigned to a cpu. This is used for the
++ * optimized make_all_cpus_request path.
++ */
++ vcpu->cpu = -1;
++
++ kvm_arm_set_running_vcpu(NULL);
++}
++
++int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
++ struct kvm_guest_debug *dbg)
++{
++ return -EINVAL;
++}
++
++
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL;
++}
++
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state)
++{
++ return -EINVAL;
++}
++
++/**
++ * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled
++ * @v: The VCPU pointer
++ *
++ * If the guest CPU is not waiting for interrupts or an interrupt line is
++ * asserted, the CPU is by definition runnable.
++ */
++int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
++{
++ return !!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v);
++}
++
++/* Just ensure a guest exit from a particular CPU */
++static void exit_vm_noop(void *info)
++{
++}
++
++void force_vm_exit(const cpumask_t *mask)
++{
++ smp_call_function_many(mask, exit_vm_noop, NULL, true);
++}
++
++/**
++ * need_new_vmid_gen - check that the VMID is still valid
++ * @kvm: The VM's VMID to checkt
++ *
++ * return true if there is a new generation of VMIDs being used
++ *
++ * The hardware supports only 256 values with the value zero reserved for the
++ * host, so we check if an assigned value belongs to a previous generation,
++ * which which requires us to assign a new value. If we're the first to use a
++ * VMID for the new generation, we must flush necessary caches and TLBs on all
++ * CPUs.
++ */
++static bool need_new_vmid_gen(struct kvm *kvm)
++{
++ return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen));
++}
++
++/**
++ * update_vttbr - Update the VTTBR with a valid VMID before the guest runs
++ * @kvm The guest that we are about to run
++ *
++ * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the
++ * VM has a valid VMID, otherwise assigns a new one and flushes corresponding
++ * caches and TLBs.
++ */
++static void update_vttbr(struct kvm *kvm)
++{
++ phys_addr_t pgd_phys;
++ u64 vmid;
++
++ if (!need_new_vmid_gen(kvm))
++ return;
++
++ spin_lock(&kvm_vmid_lock);
++
++ /*
++ * We need to re-check the vmid_gen here to ensure that if another vcpu
++ * already allocated a valid vmid for this vm, then this vcpu should
++ * use the same vmid.
++ */
++ if (!need_new_vmid_gen(kvm)) {
++ spin_unlock(&kvm_vmid_lock);
++ return;
++ }
++
++ /* First user of a new VMID generation? */
++ if (unlikely(kvm_next_vmid == 0)) {
++ atomic64_inc(&kvm_vmid_gen);
++ kvm_next_vmid = 1;
++
++ /*
++ * On SMP we know no other CPUs can use this CPU's or each
++ * other's VMID after force_vm_exit returns since the
++ * kvm_vmid_lock blocks them from reentry to the guest.
++ */
++ force_vm_exit(cpu_all_mask);
++ /*
++ * Now broadcast TLB + ICACHE invalidation over the inner
++ * shareable domain to make sure all data structures are
++ * clean.
++ */
++ kvm_call_hyp(__kvm_flush_vm_context);
++ }
++
++ kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen);
++ kvm->arch.vmid = kvm_next_vmid;
++ kvm_next_vmid++;
++
++ /* update vttbr to be used with the new vmid */
++ pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm));
++ BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK);
++ vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK;
++ kvm->arch.vttbr = pgd_phys | vmid;
++
++ spin_unlock(&kvm_vmid_lock);
++}
++
++static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
++{
++ struct kvm *kvm = vcpu->kvm;
++ int ret;
++
++ if (likely(vcpu->arch.has_run_once))
++ return 0;
++
++ vcpu->arch.has_run_once = true;
++
++ /*
++ * Map the VGIC hardware resources before running a vcpu the first
++ * time on this VM.
++ */
++ if (unlikely(!vgic_initialized(kvm))) {
++ ret = kvm_vgic_map_resources(kvm);
++ if (ret)
++ return ret;
++ }
++
++ /*
++ * Enable the arch timers only if we have an in-kernel VGIC
++ * and it has been properly initialized, since we cannot handle
++ * interrupts from the virtual timer with a userspace gic.
++ */
++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
++ kvm_timer_enable(kvm);
++
++ return 0;
++}
++
++static void vcpu_pause(struct kvm_vcpu *vcpu)
++{
++ wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
++
++ wait_event_interruptible(*wq, !vcpu->arch.pause);
++}
++
++static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
++{
++ return vcpu->arch.target >= 0;
++}
++
++/**
++ * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
++ * @vcpu: The VCPU pointer
++ * @run: The kvm_run structure pointer used for userspace state exchange
++ *
++ * This function is called through the VCPU_RUN ioctl called from user space. It
++ * will execute VM code in a loop until the time slice for the process is used
++ * or some emulation is needed from user space in which case the function will
++ * return with return value 0 and with the kvm_run structure filled in with the
++ * required data for the requested emulation.
++ */
++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
++{
++ int ret;
++ sigset_t sigsaved;
++
++ if (unlikely(!kvm_vcpu_initialized(vcpu)))
++ return -ENOEXEC;
++
++ ret = kvm_vcpu_first_run_init(vcpu);
++ if (ret)
++ return ret;
++
++ if (run->exit_reason == KVM_EXIT_MMIO) {
++ ret = kvm_handle_mmio_return(vcpu, vcpu->run);
++ if (ret)
++ return ret;
++ }
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
++
++ ret = 1;
++ run->exit_reason = KVM_EXIT_UNKNOWN;
++ while (ret > 0) {
++ /*
++ * Check conditions before entering the guest
++ */
++ cond_resched();
++
++ update_vttbr(vcpu->kvm);
++
++ if (vcpu->arch.pause)
++ vcpu_pause(vcpu);
++
++ kvm_vgic_flush_hwstate(vcpu);
++ kvm_timer_flush_hwstate(vcpu);
++
++ local_irq_disable();
++
++ /*
++ * Re-check atomic conditions
++ */
++ if (signal_pending(current)) {
++ ret = -EINTR;
++ run->exit_reason = KVM_EXIT_INTR;
++ }
++
++ if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
++ local_irq_enable();
++ kvm_timer_sync_hwstate(vcpu);
++ kvm_vgic_sync_hwstate(vcpu);
++ continue;
++ }
++
++ /**************************************************************
++ * Enter the guest
++ */
++ trace_kvm_entry(*vcpu_pc(vcpu));
++ kvm_guest_enter();
++ vcpu->mode = IN_GUEST_MODE;
++
++ ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
++
++ vcpu->mode = OUTSIDE_GUEST_MODE;
++ vcpu->arch.last_pcpu = smp_processor_id();
++ kvm_guest_exit();
++ trace_kvm_exit(*vcpu_pc(vcpu));
++ /*
++ * We may have taken a host interrupt in HYP mode (ie
++ * while executing the guest). This interrupt is still
++ * pending, as we haven't serviced it yet!
++ *
++ * We're now back in SVC mode, with interrupts
++ * disabled. Enabling the interrupts now will have
++ * the effect of taking the interrupt again, in SVC
++ * mode this time.
++ */
++ local_irq_enable();
++
++ /*
++ * Back from guest
++ *************************************************************/
++
++ kvm_timer_sync_hwstate(vcpu);
++ kvm_vgic_sync_hwstate(vcpu);
++
++ ret = handle_exit(vcpu, run, ret);
++ }
++
++ if (vcpu->sigset_active)
++ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
++ return ret;
++}
++
++static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level)
++{
++ int bit_index;
++ bool set;
++ unsigned long *ptr;
++
++ if (number == KVM_ARM_IRQ_CPU_IRQ)
++ bit_index = __ffs(HCR_VI);
++ else /* KVM_ARM_IRQ_CPU_FIQ */
++ bit_index = __ffs(HCR_VF);
++
++ ptr = (unsigned long *)&vcpu->arch.irq_lines;
++ if (level)
++ set = test_and_set_bit(bit_index, ptr);
++ else
++ set = test_and_clear_bit(bit_index, ptr);
++
++ /*
++ * If we didn't change anything, no need to wake up or kick other CPUs
++ */
++ if (set == level)
++ return 0;
++
++ /*
++ * The vcpu irq_lines field was updated, wake up sleeping VCPUs and
++ * trigger a world-switch round on the running physical CPU to set the
++ * virtual IRQ/FIQ fields in the HCR appropriately.
++ */
++ kvm_vcpu_kick(vcpu);
++
++ return 0;
++}
++
++int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
++ bool line_status)
++{
++ u32 irq = irq_level->irq;
++ unsigned int irq_type, vcpu_idx, irq_num;
++ int nrcpus = atomic_read(&kvm->online_vcpus);
++ struct kvm_vcpu *vcpu = NULL;
++ bool level = irq_level->level;
++
++ irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK;
++ vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK;
++ irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK;
++
++ trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level);
++
++ switch (irq_type) {
++ case KVM_ARM_IRQ_TYPE_CPU:
++ if (irqchip_in_kernel(kvm))
++ return -ENXIO;
++
++ if (vcpu_idx >= nrcpus)
++ return -EINVAL;
++
++ vcpu = kvm_get_vcpu(kvm, vcpu_idx);
++ if (!vcpu)
++ return -EINVAL;
++
++ if (irq_num > KVM_ARM_IRQ_CPU_FIQ)
++ return -EINVAL;
++
++ return vcpu_interrupt_line(vcpu, irq_num, level);
++ case KVM_ARM_IRQ_TYPE_PPI:
++ if (!irqchip_in_kernel(kvm))
++ return -ENXIO;
++
++ if (vcpu_idx >= nrcpus)
++ return -EINVAL;
++
++ vcpu = kvm_get_vcpu(kvm, vcpu_idx);
++ if (!vcpu)
++ return -EINVAL;
++
++ if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS)
++ return -EINVAL;
++
++ return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level);
++ case KVM_ARM_IRQ_TYPE_SPI:
++ if (!irqchip_in_kernel(kvm))
++ return -ENXIO;
++
++ if (irq_num < VGIC_NR_PRIVATE_IRQS)
++ return -EINVAL;
++
++ return kvm_vgic_inject_irq(kvm, 0, irq_num, level);
++ }
++
++ return -EINVAL;
++}
++
++static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
++ struct kvm_vcpu_init *init)
++{
++ int ret;
++
++ ret = kvm_vcpu_set_target(vcpu, init);
++ if (ret)
++ return ret;
++
++ /*
++ * Ensure a rebooted VM will fault in RAM pages and detect if the
++ * guest MMU is turned off and flush the caches as needed.
++ */
++ if (vcpu->arch.has_run_once)
++ stage2_unmap_vm(vcpu->kvm);
++
++ vcpu_reset_hcr(vcpu);
++
++ /*
++ * Handle the "start in power-off" case by marking the VCPU as paused.
++ */
++ if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
++ vcpu->arch.pause = true;
++ else
++ vcpu->arch.pause = false;
++
++ return 0;
++}
++
++long kvm_arch_vcpu_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ struct kvm_vcpu *vcpu = filp->private_data;
++ void __user *argp = (void __user *)arg;
++
++ switch (ioctl) {
++ case KVM_ARM_VCPU_INIT: {
++ struct kvm_vcpu_init init;
++
++ if (copy_from_user(&init, argp, sizeof(init)))
++ return -EFAULT;
++
++ return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init);
++ }
++ case KVM_SET_ONE_REG:
++ case KVM_GET_ONE_REG: {
++ struct kvm_one_reg reg;
++
++ if (unlikely(!kvm_vcpu_initialized(vcpu)))
++ return -ENOEXEC;
++
++ if (copy_from_user(&reg, argp, sizeof(reg)))
++ return -EFAULT;
++ if (ioctl == KVM_SET_ONE_REG)
++ return kvm_arm_set_reg(vcpu, &reg);
++ else
++ return kvm_arm_get_reg(vcpu, &reg);
++ }
++ case KVM_GET_REG_LIST: {
++ struct kvm_reg_list __user *user_list = argp;
++ struct kvm_reg_list reg_list;
++ unsigned n;
++
++ if (unlikely(!kvm_vcpu_initialized(vcpu)))
++ return -ENOEXEC;
++
++ if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
++ return -EFAULT;
++ n = reg_list.n;
++ reg_list.n = kvm_arm_num_regs(vcpu);
++ if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
++ return -EFAULT;
++ if (n < reg_list.n)
++ return -E2BIG;
++ return kvm_arm_copy_reg_indices(vcpu, user_list->reg);
++ }
++ default:
++ return -EINVAL;
++ }
++}
++
++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
++{
++ return -EINVAL;
++}
++
++static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
++ struct kvm_arm_device_addr *dev_addr)
++{
++ unsigned long dev_id, type;
++
++ dev_id = (dev_addr->id & KVM_ARM_DEVICE_ID_MASK) >>
++ KVM_ARM_DEVICE_ID_SHIFT;
++ type = (dev_addr->id & KVM_ARM_DEVICE_TYPE_MASK) >>
++ KVM_ARM_DEVICE_TYPE_SHIFT;
++
++ switch (dev_id) {
++ case KVM_ARM_DEVICE_VGIC_V2:
++ if (!vgic_present)
++ return -ENXIO;
++ return kvm_vgic_addr(kvm, type, &dev_addr->addr, true);
++ default:
++ return -ENODEV;
++ }
++}
++
++long kvm_arch_vm_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg)
++{
++ struct kvm *kvm = filp->private_data;
++ void __user *argp = (void __user *)arg;
++
++ switch (ioctl) {
++ case KVM_CREATE_IRQCHIP: {
++ if (vgic_present)
++ return kvm_vgic_create(kvm);
++ else
++ return -ENXIO;
++ }
++ case KVM_ARM_SET_DEVICE_ADDR: {
++ struct kvm_arm_device_addr dev_addr;
++
++ if (copy_from_user(&dev_addr, argp, sizeof(dev_addr)))
++ return -EFAULT;
++ return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr);
++ }
++ case KVM_ARM_PREFERRED_TARGET: {
++ int err;
++ struct kvm_vcpu_init init;
++
++ err = kvm_vcpu_preferred_target(&init);
++ if (err)
++ return err;
++
++ if (copy_to_user(argp, &init, sizeof(init)))
++ return -EFAULT;
++
++ return 0;
++ }
++ default:
++ return -EINVAL;
++ }
++}
++
++static void cpu_init_hyp_mode(void *dummy)
++{
++ phys_addr_t boot_pgd_ptr;
++ phys_addr_t pgd_ptr;
++ unsigned long hyp_stack_ptr;
++ unsigned long stack_page;
++ unsigned long vector_ptr;
++
++ /* Switch from the HYP stub to our own HYP init vector */
++ __hyp_set_vectors(kvm_get_idmap_vector());
++
++ boot_pgd_ptr = kvm_mmu_get_boot_httbr();
++ pgd_ptr = kvm_mmu_get_httbr();
++ stack_page = __this_cpu_read(kvm_arm_hyp_stack_page);
++ hyp_stack_ptr = stack_page + PAGE_SIZE;
++ vector_ptr = (unsigned long)__kvm_hyp_vector;
++
++ __cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
++}
++
++static int hyp_init_cpu_notify(struct notifier_block *self,
++ unsigned long action, void *cpu)
++{
++ switch (action) {
++ case CPU_STARTING:
++ case CPU_STARTING_FROZEN:
++ if (__hyp_get_vectors() == hyp_default_vectors)
++ cpu_init_hyp_mode(NULL);
++ break;
++ }
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block hyp_init_cpu_nb = {
++ .notifier_call = hyp_init_cpu_notify,
++};
++
++#ifdef CONFIG_CPU_PM
++static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
++ unsigned long cmd,
++ void *v)
++{
++ if (cmd == CPU_PM_EXIT &&
++ __hyp_get_vectors() == hyp_default_vectors) {
++ cpu_init_hyp_mode(NULL);
++ return NOTIFY_OK;
++ }
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block hyp_init_cpu_pm_nb = {
++ .notifier_call = hyp_init_cpu_pm_notifier,
++};
++
++static void __init hyp_cpu_pm_init(void)
++{
++ cpu_pm_register_notifier(&hyp_init_cpu_pm_nb);
++}
++#else
++static inline void hyp_cpu_pm_init(void)
++{
++}
++#endif
++
++/**
++ * Inits Hyp-mode on all online CPUs
++ */
++static int init_hyp_mode(void)
++{
++ int cpu;
++ int err = 0;
++
++ /*
++ * Allocate Hyp PGD and setup Hyp identity mapping
++ */
++ err = kvm_mmu_init();
++ if (err)
++ goto out_err;
++
++ /*
++ * It is probably enough to obtain the default on one
++ * CPU. It's unlikely to be different on the others.
++ */
++ hyp_default_vectors = __hyp_get_vectors();
++
++ /*
++ * Allocate stack pages for Hypervisor-mode
++ */
++ for_each_possible_cpu(cpu) {
++ unsigned long stack_page;
++
++ stack_page = __get_free_page(GFP_KERNEL);
++ if (!stack_page) {
++ err = -ENOMEM;
++ goto out_free_stack_pages;
++ }
++
++ per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page;
++ }
++
++ /*
++ * Map the Hyp-code called directly from the host
++ */
++ err = create_hyp_mappings(__kvm_hyp_code_start, __kvm_hyp_code_end);
++ if (err) {
++ kvm_err("Cannot map world-switch code\n");
++ goto out_free_mappings;
++ }
++
++ /*
++ * Map the Hyp stack pages
++ */
++ for_each_possible_cpu(cpu) {
++ char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu);
++ err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE);
++
++ if (err) {
++ kvm_err("Cannot map hyp stack\n");
++ goto out_free_mappings;
++ }
++ }
++
++ /*
++ * Map the host CPU structures
++ */
++ kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t);
++ if (!kvm_host_cpu_state) {
++ err = -ENOMEM;
++ kvm_err("Cannot allocate host CPU state\n");
++ goto out_free_mappings;
++ }
++
++ for_each_possible_cpu(cpu) {
++ kvm_cpu_context_t *cpu_ctxt;
++
++ cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu);
++ err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1);
++
++ if (err) {
++ kvm_err("Cannot map host CPU state: %d\n", err);
++ goto out_free_context;
++ }
++ }
++
++ /*
++ * Execute the init code on each CPU.
++ */
++ on_each_cpu(cpu_init_hyp_mode, NULL, 1);
++
++ /*
++ * Init HYP view of VGIC
++ */
++ err = kvm_vgic_hyp_init();
++ if (err)
++ goto out_free_context;
++
++#ifdef CONFIG_KVM_ARM_VGIC
++ vgic_present = true;
++#endif
++
++ /*
++ * Init HYP architected timer support
++ */
++ err = kvm_timer_hyp_init();
++ if (err)
++ goto out_free_mappings;
++
++#ifndef CONFIG_HOTPLUG_CPU
++ free_boot_hyp_pgd();
++#endif
++
++ kvm_perf_init();
++
++ kvm_info("Hyp mode initialized successfully\n");
++
++ return 0;
++out_free_context:
++ free_percpu(kvm_host_cpu_state);
++out_free_mappings:
++ free_hyp_pgds();
++out_free_stack_pages:
++ for_each_possible_cpu(cpu)
++ free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
++out_err:
++ kvm_err("error initializing Hyp mode: %d\n", err);
++ return err;
++}
++
++static void check_kvm_target_cpu(void *ret)
++{
++ *(int *)ret = kvm_target_cpu();
++}
++
++/**
++ * Initialize Hyp-mode and memory mappings on all CPUs.
++ */
++int kvm_arch_init(void *opaque)
++{
++ int err;
++ int ret, cpu;
++
++ if (!is_hyp_mode_available()) {
++ kvm_err("HYP mode not available\n");
++ return -ENODEV;
++ }
++
++ for_each_online_cpu(cpu) {
++ smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1);
++ if (ret < 0) {
++ kvm_err("Error, CPU %d not supported!\n", cpu);
++ return -ENODEV;
++ }
++ }
++
++ cpu_notifier_register_begin();
++
++ err = init_hyp_mode();
++ if (err)
++ goto out_err;
++
++ err = __register_cpu_notifier(&hyp_init_cpu_nb);
++ if (err) {
++ kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
++ goto out_err;
++ }
++
++ cpu_notifier_register_done();
++
++ hyp_cpu_pm_init();
++
++ kvm_coproc_table_init();
++ return 0;
++out_err:
++ cpu_notifier_register_done();
++ return err;
++}
++
++/* NOP: Compiling as a module not supported */
++void kvm_arch_exit(void)
++{
++ kvm_perf_teardown();
++}
++
++static int arm_init(void)
++{
++ int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
++ return rc;
++}
++
++module_init(arm_init);
+diff -Nur linux-3.18.14.orig/arch/arm/kvm/psci.c linux-3.18.14-rt/arch/arm/kvm/psci.c
+--- linux-3.18.14.orig/arch/arm/kvm/psci.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/kvm/psci.c 2015-05-31 15:32:45.673635392 -0500
+@@ -67,7 +67,7 @@
{
struct kvm *kvm = source_vcpu->kvm;
struct kvm_vcpu *vcpu = NULL, *tmp;
@@ -278,7 +1906,7 @@ diff -Nur linux-3.18.12.orig/arch/arm/kvm/psci.c linux-3.18.12/arch/arm/kvm/psci
unsigned long cpu_id;
unsigned long context_id;
unsigned long mpidr;
-@@ -123,7 +123,7 @@
+@@ -124,7 +124,7 @@
smp_mb(); /* Make sure the above is visible */
wq = kvm_arch_vcpu_wq(vcpu);
@@ -287,9 +1915,350 @@ diff -Nur linux-3.18.12.orig/arch/arm/kvm/psci.c linux-3.18.12/arch/arm/kvm/psci
return PSCI_RET_SUCCESS;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.12/arch/arm/mach-at91/at91rm9200_time.c
---- linux-3.18.12.orig/arch/arm/mach-at91/at91rm9200_time.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-at91/at91rm9200_time.c 2015-04-26 13:32:22.359684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/kvm/psci.c.orig linux-3.18.14-rt/arch/arm/kvm/psci.c.orig
+--- linux-3.18.14.orig/arch/arm/kvm/psci.c.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/arch/arm/kvm/psci.c.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,337 @@
++/*
++ * Copyright (C) 2012 - ARM Ltd
++ * Author: Marc Zyngier <marc.zyngier@arm.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/preempt.h>
++#include <linux/kvm_host.h>
++#include <linux/wait.h>
++
++#include <asm/cputype.h>
++#include <asm/kvm_emulate.h>
++#include <asm/kvm_psci.h>
++
++/*
++ * This is an implementation of the Power State Coordination Interface
++ * as described in ARM document number ARM DEN 0022A.
++ */
++
++#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
++
++static unsigned long psci_affinity_mask(unsigned long affinity_level)
++{
++ if (affinity_level <= 3)
++ return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level);
++
++ return 0;
++}
++
++static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu)
++{
++ /*
++ * NOTE: For simplicity, we make VCPU suspend emulation to be
++ * same-as WFI (Wait-for-interrupt) emulation.
++ *
++ * This means for KVM the wakeup events are interrupts and
++ * this is consistent with intended use of StateID as described
++ * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A).
++ *
++ * Further, we also treat power-down request to be same as
++ * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2
++ * specification (ARM DEN 0022A). This means all suspend states
++ * for KVM will preserve the register state.
++ */
++ kvm_vcpu_block(vcpu);
++
++ return PSCI_RET_SUCCESS;
++}
++
++static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
++{
++ vcpu->arch.pause = true;
++}
++
++static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
++{
++ struct kvm *kvm = source_vcpu->kvm;
++ struct kvm_vcpu *vcpu = NULL, *tmp;
++ wait_queue_head_t *wq;
++ unsigned long cpu_id;
++ unsigned long context_id;
++ unsigned long mpidr;
++ phys_addr_t target_pc;
++ int i;
++
++ cpu_id = *vcpu_reg(source_vcpu, 1);
++ if (vcpu_mode_is_32bit(source_vcpu))
++ cpu_id &= ~((u32) 0);
++
++ kvm_for_each_vcpu(i, tmp, kvm) {
++ mpidr = kvm_vcpu_get_mpidr(tmp);
++ if ((mpidr & MPIDR_HWID_BITMASK) == (cpu_id & MPIDR_HWID_BITMASK)) {
++ vcpu = tmp;
++ break;
++ }
++ }
++
++ /*
++ * Make sure the caller requested a valid CPU and that the CPU is
++ * turned off.
++ */
++ if (!vcpu)
++ return PSCI_RET_INVALID_PARAMS;
++ if (!vcpu->arch.pause) {
++ if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
++ return PSCI_RET_ALREADY_ON;
++ else
++ return PSCI_RET_INVALID_PARAMS;
++ }
++
++ target_pc = *vcpu_reg(source_vcpu, 2);
++ context_id = *vcpu_reg(source_vcpu, 3);
++
++ kvm_reset_vcpu(vcpu);
++
++ /* Gracefully handle Thumb2 entry point */
++ if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
++ target_pc &= ~((phys_addr_t) 1);
++ vcpu_set_thumb(vcpu);
++ }
++
++ /* Propagate caller endianness */
++ if (kvm_vcpu_is_be(source_vcpu))
++ kvm_vcpu_set_be(vcpu);
++
++ *vcpu_pc(vcpu) = target_pc;
++ /*
++ * NOTE: We always update r0 (or x0) because for PSCI v0.1
++ * the general puspose registers are undefined upon CPU_ON.
++ */
++ *vcpu_reg(vcpu, 0) = context_id;
++ vcpu->arch.pause = false;
++ smp_mb(); /* Make sure the above is visible */
++
++ wq = kvm_arch_vcpu_wq(vcpu);
++ wake_up_interruptible(wq);
++
++ return PSCI_RET_SUCCESS;
++}
++
++static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
++{
++ int i;
++ unsigned long mpidr;
++ unsigned long target_affinity;
++ unsigned long target_affinity_mask;
++ unsigned long lowest_affinity_level;
++ struct kvm *kvm = vcpu->kvm;
++ struct kvm_vcpu *tmp;
++
++ target_affinity = *vcpu_reg(vcpu, 1);
++ lowest_affinity_level = *vcpu_reg(vcpu, 2);
++
++ /* Determine target affinity mask */
++ target_affinity_mask = psci_affinity_mask(lowest_affinity_level);
++ if (!target_affinity_mask)
++ return PSCI_RET_INVALID_PARAMS;
++
++ /* Ignore other bits of target affinity */
++ target_affinity &= target_affinity_mask;
++
++ /*
++ * If one or more VCPU matching target affinity are running
++ * then ON else OFF
++ */
++ kvm_for_each_vcpu(i, tmp, kvm) {
++ mpidr = kvm_vcpu_get_mpidr(tmp);
++ if (((mpidr & target_affinity_mask) == target_affinity) &&
++ !tmp->arch.pause) {
++ return PSCI_0_2_AFFINITY_LEVEL_ON;
++ }
++ }
++
++ return PSCI_0_2_AFFINITY_LEVEL_OFF;
++}
++
++static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type)
++{
++ int i;
++ struct kvm_vcpu *tmp;
++
++ /*
++ * The KVM ABI specifies that a system event exit may call KVM_RUN
++ * again and may perform shutdown/reboot at a later time that when the
++ * actual request is made. Since we are implementing PSCI and a
++ * caller of PSCI reboot and shutdown expects that the system shuts
++ * down or reboots immediately, let's make sure that VCPUs are not run
++ * after this call is handled and before the VCPUs have been
++ * re-initialized.
++ */
++ kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
++ tmp->arch.pause = true;
++ kvm_vcpu_kick(tmp);
++ }
++
++ memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
++ vcpu->run->system_event.type = type;
++ vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
++}
++
++static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
++{
++ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN);
++}
++
++static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
++{
++ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
++}
++
++int kvm_psci_version(struct kvm_vcpu *vcpu)
++{
++ if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
++ return KVM_ARM_PSCI_0_2;
++
++ return KVM_ARM_PSCI_0_1;
++}
++
++static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
++{
++ int ret = 1;
++ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
++ unsigned long val;
++
++ switch (psci_fn) {
++ case PSCI_0_2_FN_PSCI_VERSION:
++ /*
++ * Bits[31:16] = Major Version = 0
++ * Bits[15:0] = Minor Version = 2
++ */
++ val = 2;
++ break;
++ case PSCI_0_2_FN_CPU_SUSPEND:
++ case PSCI_0_2_FN64_CPU_SUSPEND:
++ val = kvm_psci_vcpu_suspend(vcpu);
++ break;
++ case PSCI_0_2_FN_CPU_OFF:
++ kvm_psci_vcpu_off(vcpu);
++ val = PSCI_RET_SUCCESS;
++ break;
++ case PSCI_0_2_FN_CPU_ON:
++ case PSCI_0_2_FN64_CPU_ON:
++ val = kvm_psci_vcpu_on(vcpu);
++ break;
++ case PSCI_0_2_FN_AFFINITY_INFO:
++ case PSCI_0_2_FN64_AFFINITY_INFO:
++ val = kvm_psci_vcpu_affinity_info(vcpu);
++ break;
++ case PSCI_0_2_FN_MIGRATE:
++ case PSCI_0_2_FN64_MIGRATE:
++ val = PSCI_RET_NOT_SUPPORTED;
++ break;
++ case PSCI_0_2_FN_MIGRATE_INFO_TYPE:
++ /*
++ * Trusted OS is MP hence does not require migration
++ * or
++ * Trusted OS is not present
++ */
++ val = PSCI_0_2_TOS_MP;
++ break;
++ case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
++ case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
++ val = PSCI_RET_NOT_SUPPORTED;
++ break;
++ case PSCI_0_2_FN_SYSTEM_OFF:
++ kvm_psci_system_off(vcpu);
++ /*
++ * We should'nt be going back to guest VCPU after
++ * receiving SYSTEM_OFF request.
++ *
++ * If user space accidently/deliberately resumes
++ * guest VCPU after SYSTEM_OFF request then guest
++ * VCPU should see internal failure from PSCI return
++ * value. To achieve this, we preload r0 (or x0) with
++ * PSCI return value INTERNAL_FAILURE.
++ */
++ val = PSCI_RET_INTERNAL_FAILURE;
++ ret = 0;
++ break;
++ case PSCI_0_2_FN_SYSTEM_RESET:
++ kvm_psci_system_reset(vcpu);
++ /*
++ * Same reason as SYSTEM_OFF for preloading r0 (or x0)
++ * with PSCI return value INTERNAL_FAILURE.
++ */
++ val = PSCI_RET_INTERNAL_FAILURE;
++ ret = 0;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ *vcpu_reg(vcpu, 0) = val;
++ return ret;
++}
++
++static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
++{
++ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
++ unsigned long val;
++
++ switch (psci_fn) {
++ case KVM_PSCI_FN_CPU_OFF:
++ kvm_psci_vcpu_off(vcpu);
++ val = PSCI_RET_SUCCESS;
++ break;
++ case KVM_PSCI_FN_CPU_ON:
++ val = kvm_psci_vcpu_on(vcpu);
++ break;
++ case KVM_PSCI_FN_CPU_SUSPEND:
++ case KVM_PSCI_FN_MIGRATE:
++ val = PSCI_RET_NOT_SUPPORTED;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ *vcpu_reg(vcpu, 0) = val;
++ return 1;
++}
++
++/**
++ * kvm_psci_call - handle PSCI call if r0 value is in range
++ * @vcpu: Pointer to the VCPU struct
++ *
++ * Handle PSCI calls from guests through traps from HVC instructions.
++ * The calling convention is similar to SMC calls to the secure world
++ * where the function number is placed in r0.
++ *
++ * This function returns: > 0 (success), 0 (success but exit to user
++ * space), and < 0 (errors)
++ *
++ * Errors:
++ * -EINVAL: Unrecognized PSCI function
++ */
++int kvm_psci_call(struct kvm_vcpu *vcpu)
++{
++ switch (kvm_psci_version(vcpu)) {
++ case KVM_ARM_PSCI_0_2:
++ return kvm_psci_0_2_call(vcpu);
++ case KVM_ARM_PSCI_0_1:
++ return kvm_psci_0_1_call(vcpu);
++ default:
++ return -EINVAL;
++ };
++}
+diff -Nur linux-3.18.14.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.14-rt/arch/arm/mach-at91/at91rm9200_time.c
+--- linux-3.18.14.orig/arch/arm/mach-at91/at91rm9200_time.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-at91/at91rm9200_time.c 2015-05-31 15:32:45.673635392 -0500
@@ -135,6 +135,7 @@
break;
case CLOCK_EVT_MODE_SHUTDOWN:
@@ -298,9 +2267,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.12/
case CLOCK_EVT_MODE_RESUME:
irqmask = 0;
break;
-diff -Nur linux-3.18.12.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.12/arch/arm/mach-exynos/platsmp.c
---- linux-3.18.12.orig/arch/arm/mach-exynos/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-exynos/platsmp.c 2015-04-26 13:32:22.359684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.14-rt/arch/arm/mach-exynos/platsmp.c
+--- linux-3.18.14.orig/arch/arm/mach-exynos/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-exynos/platsmp.c 2015-05-31 15:32:45.673635392 -0500
@@ -137,7 +137,7 @@
return (void __iomem *)(S5P_VA_SCU);
}
@@ -348,9 +2317,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.12/arch/a
return pen_release != -1 ? ret : 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.12/arch/arm/mach-hisi/platmcpm.c
---- linux-3.18.12.orig/arch/arm/mach-hisi/platmcpm.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-hisi/platmcpm.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.14-rt/arch/arm/mach-hisi/platmcpm.c
+--- linux-3.18.14.orig/arch/arm/mach-hisi/platmcpm.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-hisi/platmcpm.c 2015-05-31 15:32:45.677635392 -0500
@@ -57,7 +57,7 @@
static void __iomem *sysctrl, *fabric;
@@ -453,9 +2422,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.12/arch/ar
}
static void __naked hip04_mcpm_power_up_setup(unsigned int affinity_level)
-diff -Nur linux-3.18.12.orig/arch/arm/mach-omap2/omap-smp.c linux-3.18.12/arch/arm/mach-omap2/omap-smp.c
---- linux-3.18.12.orig/arch/arm/mach-omap2/omap-smp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-omap2/omap-smp.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-omap2/omap-smp.c linux-3.18.14-rt/arch/arm/mach-omap2/omap-smp.c
+--- linux-3.18.14.orig/arch/arm/mach-omap2/omap-smp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-omap2/omap-smp.c 2015-05-31 15:32:45.697635392 -0500
@@ -43,7 +43,7 @@
/* SCU base address */
static void __iomem *scu_base;
@@ -494,9 +2463,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-omap2/omap-smp.c linux-3.18.12/arch/a
return 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-prima2/platsmp.c linux-3.18.12/arch/arm/mach-prima2/platsmp.c
---- linux-3.18.12.orig/arch/arm/mach-prima2/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-prima2/platsmp.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-prima2/platsmp.c linux-3.18.14-rt/arch/arm/mach-prima2/platsmp.c
+--- linux-3.18.14.orig/arch/arm/mach-prima2/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-prima2/platsmp.c 2015-05-31 15:32:45.721635392 -0500
@@ -23,7 +23,7 @@
static void __iomem *scu_base;
static void __iomem *rsc_base;
@@ -535,9 +2504,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-prima2/platsmp.c linux-3.18.12/arch/a
return pen_release != -1 ? -ENOSYS : 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-qcom/platsmp.c linux-3.18.12/arch/arm/mach-qcom/platsmp.c
---- linux-3.18.12.orig/arch/arm/mach-qcom/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-qcom/platsmp.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-qcom/platsmp.c linux-3.18.14-rt/arch/arm/mach-qcom/platsmp.c
+--- linux-3.18.14.orig/arch/arm/mach-qcom/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-qcom/platsmp.c 2015-05-31 15:32:45.741635391 -0500
@@ -46,7 +46,7 @@
extern void secondary_startup(void);
@@ -576,9 +2545,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-qcom/platsmp.c linux-3.18.12/arch/arm
return ret;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-spear/platsmp.c linux-3.18.12/arch/arm/mach-spear/platsmp.c
---- linux-3.18.12.orig/arch/arm/mach-spear/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-spear/platsmp.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-spear/platsmp.c linux-3.18.14-rt/arch/arm/mach-spear/platsmp.c
+--- linux-3.18.14.orig/arch/arm/mach-spear/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-spear/platsmp.c 2015-05-31 15:32:45.749635392 -0500
@@ -32,7 +32,7 @@
sync_cache_w(&pen_release);
}
@@ -617,9 +2586,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-spear/platsmp.c linux-3.18.12/arch/ar
return pen_release != -1 ? -ENOSYS : 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-sti/platsmp.c linux-3.18.12/arch/arm/mach-sti/platsmp.c
---- linux-3.18.12.orig/arch/arm/mach-sti/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-sti/platsmp.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-sti/platsmp.c linux-3.18.14-rt/arch/arm/mach-sti/platsmp.c
+--- linux-3.18.14.orig/arch/arm/mach-sti/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-sti/platsmp.c 2015-05-31 15:32:45.765635392 -0500
@@ -34,7 +34,7 @@
sync_cache_w(&pen_release);
}
@@ -658,9 +2627,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-sti/platsmp.c linux-3.18.12/arch/arm/
return pen_release != -1 ? -ENOSYS : 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mach-ux500/platsmp.c linux-3.18.12/arch/arm/mach-ux500/platsmp.c
---- linux-3.18.12.orig/arch/arm/mach-ux500/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mach-ux500/platsmp.c 2015-04-26 13:32:22.363684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mach-ux500/platsmp.c linux-3.18.14-rt/arch/arm/mach-ux500/platsmp.c
+--- linux-3.18.14.orig/arch/arm/mach-ux500/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mach-ux500/platsmp.c 2015-05-31 15:32:45.793635391 -0500
@@ -51,7 +51,7 @@
return NULL;
}
@@ -699,9 +2668,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-ux500/platsmp.c linux-3.18.12/arch/ar
return pen_release != -1 ? -ENOSYS : 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mm/fault.c linux-3.18.12/arch/arm/mm/fault.c
---- linux-3.18.12.orig/arch/arm/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mm/fault.c linux-3.18.14-rt/arch/arm/mm/fault.c
+--- linux-3.18.14.orig/arch/arm/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mm/fault.c 2015-05-31 15:32:45.797635391 -0500
@@ -277,7 +277,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -731,9 +2700,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mm/fault.c linux-3.18.12/arch/arm/mm/fault
do_bad_area(addr, fsr, regs);
return 0;
}
-diff -Nur linux-3.18.12.orig/arch/arm/mm/highmem.c linux-3.18.12/arch/arm/mm/highmem.c
---- linux-3.18.12.orig/arch/arm/mm/highmem.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/mm/highmem.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/mm/highmem.c linux-3.18.14-rt/arch/arm/mm/highmem.c
+--- linux-3.18.14.orig/arch/arm/mm/highmem.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/mm/highmem.c 2015-05-31 15:32:45.805635391 -0500
@@ -53,6 +53,7 @@
void *kmap_atomic(struct page *page)
@@ -820,9 +2789,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mm/highmem.c linux-3.18.12/arch/arm/mm/hig
+ }
+}
+#endif
-diff -Nur linux-3.18.12.orig/arch/arm/plat-versatile/platsmp.c linux-3.18.12/arch/arm/plat-versatile/platsmp.c
---- linux-3.18.12.orig/arch/arm/plat-versatile/platsmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/arm/plat-versatile/platsmp.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm/plat-versatile/platsmp.c linux-3.18.14-rt/arch/arm/plat-versatile/platsmp.c
+--- linux-3.18.14.orig/arch/arm/plat-versatile/platsmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm/plat-versatile/platsmp.c 2015-05-31 15:32:45.889635390 -0500
@@ -30,7 +30,7 @@
sync_cache_w(&pen_release);
}
@@ -861,9 +2830,112 @@ diff -Nur linux-3.18.12.orig/arch/arm/plat-versatile/platsmp.c linux-3.18.12/arc
return pen_release != -1 ? -ENOSYS : 0;
}
-diff -Nur linux-3.18.12.orig/arch/avr32/mm/fault.c linux-3.18.12/arch/avr32/mm/fault.c
---- linux-3.18.12.orig/arch/avr32/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/avr32/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/arm64/include/asm/thread_info.h linux-3.18.14-rt/arch/arm64/include/asm/thread_info.h
+--- linux-3.18.14.orig/arch/arm64/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm64/include/asm/thread_info.h 2015-05-31 15:32:45.925635390 -0500
+@@ -50,6 +50,7 @@
+ struct exec_domain *exec_domain; /* execution domain */
+ struct restart_block restart_block;
+ int preempt_count; /* 0 => preemptable, <0 => bug */
++ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
+ int cpu; /* cpu */
+ };
+
+@@ -108,6 +109,7 @@
+ #define TIF_NEED_RESCHED 1
+ #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
+ #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
++#define TIF_NEED_RESCHED_LAZY 4
+ #define TIF_NOHZ 7
+ #define TIF_SYSCALL_TRACE 8
+ #define TIF_SYSCALL_AUDIT 9
+@@ -124,6 +126,7 @@
+ #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+ #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+ #define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE)
++#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
+ #define _TIF_NOHZ (1 << TIF_NOHZ)
+ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
+ #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
+diff -Nur linux-3.18.14.orig/arch/arm64/Kconfig linux-3.18.14-rt/arch/arm64/Kconfig
+--- linux-3.18.14.orig/arch/arm64/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm64/Kconfig 2015-05-31 15:32:45.905635390 -0500
+@@ -59,8 +59,10 @@
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_RCU_TABLE_FREE
++ select HAVE_PREEMPT_LAZY
+ select HAVE_SYSCALL_TRACEPOINTS
+ select IRQ_DOMAIN
++ select IRQ_FORCED_THREADING
+ select MODULES_USE_ELF_RELA
+ select NO_BOOTMEM
+ select OF
+diff -Nur linux-3.18.14.orig/arch/arm64/kernel/asm-offsets.c linux-3.18.14-rt/arch/arm64/kernel/asm-offsets.c
+--- linux-3.18.14.orig/arch/arm64/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm64/kernel/asm-offsets.c 2015-05-31 15:32:45.925635390 -0500
+@@ -36,6 +36,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_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
+diff -Nur linux-3.18.14.orig/arch/arm64/kernel/entry.S linux-3.18.14-rt/arch/arm64/kernel/entry.S
+--- linux-3.18.14.orig/arch/arm64/kernel/entry.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm64/kernel/entry.S 2015-05-31 15:32:45.925635390 -0500
+@@ -367,11 +367,16 @@
+ #ifdef CONFIG_PREEMPT
+ get_thread_info tsk
+ ldr w24, [tsk, #TI_PREEMPT] // get preempt count
+- cbnz w24, 1f // preempt count != 0
++ cbnz w24, 2f // preempt count != 0
+ ldr x0, [tsk, #TI_FLAGS] // get flags
+- tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
+- bl el1_preempt
++ tbnz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
++
++ ldr w24, [tsk, #TI_PREEMPT_LAZY] // get preempt lazy count
++ cbnz w24, 2f // preempt lazy count != 0
++ tbz x0, #TIF_NEED_RESCHED_LAZY, 2f // needs rescheduling?
+ 1:
++ bl el1_preempt
++2:
+ #endif
+ #ifdef CONFIG_TRACE_IRQFLAGS
+ bl trace_hardirqs_on
+@@ -385,6 +390,7 @@
+ 1: bl preempt_schedule_irq // irq en/disable is done inside
+ ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS
+ tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling?
++ tbnz x0, #TIF_NEED_RESCHED_LAZY, 1b // needs rescheduling?
+ ret x24
+ #endif
+
+@@ -621,6 +627,7 @@
+ str x0, [sp, #S_X0] // returned x0
+ work_pending:
+ tbnz x1, #TIF_NEED_RESCHED, work_resched
++ tbnz x1, #TIF_NEED_RESCHED_LAZY, work_resched
+ /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
+ ldr x2, [sp, #S_PSTATE]
+ mov x0, sp // 'regs'
+diff -Nur linux-3.18.14.orig/arch/arm64/kernel/perf_event.c linux-3.18.14-rt/arch/arm64/kernel/perf_event.c
+--- linux-3.18.14.orig/arch/arm64/kernel/perf_event.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/arm64/kernel/perf_event.c 2015-05-31 15:32:45.925635390 -0500
+@@ -461,7 +461,7 @@
+ }
+
+ err = request_irq(irq, armpmu->handle_irq,
+- IRQF_NOBALANCING,
++ IRQF_NOBALANCING | IRQF_NO_THREAD,
+ "arm-pmu", armpmu);
+ if (err) {
+ pr_err("unable to request IRQ%d for ARM PMU counters\n",
+diff -Nur linux-3.18.14.orig/arch/avr32/mm/fault.c linux-3.18.14-rt/arch/avr32/mm/fault.c
+--- linux-3.18.14.orig/arch/avr32/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/avr32/mm/fault.c 2015-05-31 15:32:45.933635390 -0500
@@ -81,7 +81,7 @@
* If we're in an interrupt or have no user context, we must
* not take the fault...
@@ -873,9 +2945,9 @@ diff -Nur linux-3.18.12.orig/arch/avr32/mm/fault.c linux-3.18.12/arch/avr32/mm/f
goto no_context;
local_irq_enable();
-diff -Nur linux-3.18.12.orig/arch/cris/mm/fault.c linux-3.18.12/arch/cris/mm/fault.c
---- linux-3.18.12.orig/arch/cris/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/cris/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/cris/mm/fault.c linux-3.18.14-rt/arch/cris/mm/fault.c
+--- linux-3.18.14.orig/arch/cris/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/cris/mm/fault.c 2015-05-31 15:32:45.945635390 -0500
@@ -113,7 +113,7 @@
* user context, we must not take the fault.
*/
@@ -885,9 +2957,9 @@ diff -Nur linux-3.18.12.orig/arch/cris/mm/fault.c linux-3.18.12/arch/cris/mm/fau
goto no_context;
if (user_mode(regs))
-diff -Nur linux-3.18.12.orig/arch/frv/mm/fault.c linux-3.18.12/arch/frv/mm/fault.c
---- linux-3.18.12.orig/arch/frv/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/frv/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/frv/mm/fault.c linux-3.18.14-rt/arch/frv/mm/fault.c
+--- linux-3.18.14.orig/arch/frv/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/frv/mm/fault.c 2015-05-31 15:32:45.953635390 -0500
@@ -78,7 +78,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -897,9 +2969,9 @@ diff -Nur linux-3.18.12.orig/arch/frv/mm/fault.c linux-3.18.12/arch/frv/mm/fault
goto no_context;
if (user_mode(__frame))
-diff -Nur linux-3.18.12.orig/arch/ia64/mm/fault.c linux-3.18.12/arch/ia64/mm/fault.c
---- linux-3.18.12.orig/arch/ia64/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/ia64/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/ia64/mm/fault.c linux-3.18.14-rt/arch/ia64/mm/fault.c
+--- linux-3.18.14.orig/arch/ia64/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/ia64/mm/fault.c 2015-05-31 15:32:45.961635389 -0500
@@ -96,7 +96,7 @@
/*
* If we're in an interrupt or have no user context, we must not take the fault..
@@ -909,9 +2981,9 @@ diff -Nur linux-3.18.12.orig/arch/ia64/mm/fault.c linux-3.18.12/arch/ia64/mm/fau
goto no_context;
#ifdef CONFIG_VIRTUAL_MEM_MAP
-diff -Nur linux-3.18.12.orig/arch/Kconfig linux-3.18.12/arch/Kconfig
---- linux-3.18.12.orig/arch/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/Kconfig 2015-04-26 13:32:22.351684003 -0500
+diff -Nur linux-3.18.14.orig/arch/Kconfig linux-3.18.14-rt/arch/Kconfig
+--- linux-3.18.14.orig/arch/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/Kconfig 2015-05-31 15:32:45.501635394 -0500
@@ -6,6 +6,7 @@
tristate "OProfile system profiling"
depends on PROFILING
@@ -920,9 +2992,9 @@ diff -Nur linux-3.18.12.orig/arch/Kconfig linux-3.18.12/arch/Kconfig
select RING_BUFFER
select RING_BUFFER_ALLOW_SWAP
help
-diff -Nur linux-3.18.12.orig/arch/m32r/mm/fault.c linux-3.18.12/arch/m32r/mm/fault.c
---- linux-3.18.12.orig/arch/m32r/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/m32r/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/m32r/mm/fault.c linux-3.18.14-rt/arch/m32r/mm/fault.c
+--- linux-3.18.14.orig/arch/m32r/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/m32r/mm/fault.c 2015-05-31 15:32:45.985635389 -0500
@@ -114,7 +114,7 @@
* If we're in an interrupt or have no user context or are running in an
* atomic region then we must not take the fault..
@@ -932,9 +3004,9 @@ diff -Nur linux-3.18.12.orig/arch/m32r/mm/fault.c linux-3.18.12/arch/m32r/mm/fau
goto bad_area_nosemaphore;
if (error_code & ACE_USERMODE)
-diff -Nur linux-3.18.12.orig/arch/m68k/mm/fault.c linux-3.18.12/arch/m68k/mm/fault.c
---- linux-3.18.12.orig/arch/m68k/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/m68k/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/m68k/mm/fault.c linux-3.18.14-rt/arch/m68k/mm/fault.c
+--- linux-3.18.14.orig/arch/m68k/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/m68k/mm/fault.c 2015-05-31 15:32:45.985635389 -0500
@@ -81,7 +81,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -944,9 +3016,9 @@ diff -Nur linux-3.18.12.orig/arch/m68k/mm/fault.c linux-3.18.12/arch/m68k/mm/fau
goto no_context;
if (user_mode(regs))
-diff -Nur linux-3.18.12.orig/arch/microblaze/mm/fault.c linux-3.18.12/arch/microblaze/mm/fault.c
---- linux-3.18.12.orig/arch/microblaze/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/microblaze/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/microblaze/mm/fault.c linux-3.18.14-rt/arch/microblaze/mm/fault.c
+--- linux-3.18.14.orig/arch/microblaze/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/microblaze/mm/fault.c 2015-05-31 15:32:46.005635389 -0500
@@ -107,7 +107,7 @@
if ((error_code & 0x13) == 0x13 || (error_code & 0x11) == 0x11)
is_write = 0;
@@ -956,9 +3028,9 @@ diff -Nur linux-3.18.12.orig/arch/microblaze/mm/fault.c linux-3.18.12/arch/micro
if (kernel_mode(regs))
goto bad_area_nosemaphore;
-diff -Nur linux-3.18.12.orig/arch/mips/Kconfig linux-3.18.12/arch/mips/Kconfig
---- linux-3.18.12.orig/arch/mips/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/mips/Kconfig 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/mips/Kconfig linux-3.18.14-rt/arch/mips/Kconfig
+--- linux-3.18.14.orig/arch/mips/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/mips/Kconfig 2015-05-31 15:32:46.033635389 -0500
@@ -2196,7 +2196,7 @@
#
config HIGHMEM
@@ -968,9 +3040,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/Kconfig linux-3.18.12/arch/mips/Kconfig
config CPU_SUPPORTS_HIGHMEM
bool
-diff -Nur linux-3.18.12.orig/arch/mips/kernel/signal.c linux-3.18.12/arch/mips/kernel/signal.c
---- linux-3.18.12.orig/arch/mips/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/mips/kernel/signal.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/mips/kernel/signal.c linux-3.18.14-rt/arch/mips/kernel/signal.c
+--- linux-3.18.14.orig/arch/mips/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/mips/kernel/signal.c 2015-05-31 15:32:46.057635389 -0500
@@ -613,6 +613,7 @@
__u32 thread_info_flags)
{
@@ -979,9 +3051,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/kernel/signal.c linux-3.18.12/arch/mips/k
user_exit();
-diff -Nur linux-3.18.12.orig/arch/mips/mm/fault.c linux-3.18.12/arch/mips/mm/fault.c
---- linux-3.18.12.orig/arch/mips/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/mips/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/mips/mm/fault.c linux-3.18.14-rt/arch/mips/mm/fault.c
+--- linux-3.18.14.orig/arch/mips/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/mips/mm/fault.c 2015-05-31 15:32:46.069635388 -0500
@@ -89,7 +89,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -991,9 +3063,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/mm/fault.c linux-3.18.12/arch/mips/mm/fau
goto bad_area_nosemaphore;
if (user_mode(regs))
-diff -Nur linux-3.18.12.orig/arch/mips/mm/init.c linux-3.18.12/arch/mips/mm/init.c
---- linux-3.18.12.orig/arch/mips/mm/init.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/mips/mm/init.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/mips/mm/init.c linux-3.18.14-rt/arch/mips/mm/init.c
+--- linux-3.18.14.orig/arch/mips/mm/init.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/mips/mm/init.c 2015-05-31 15:32:46.069635388 -0500
@@ -90,7 +90,7 @@
BUG_ON(Page_dcache_dirty(page));
@@ -1012,9 +3084,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/mm/init.c linux-3.18.12/arch/mips/mm/init
}
void copy_user_highpage(struct page *to, struct page *from,
-diff -Nur linux-3.18.12.orig/arch/mn10300/mm/fault.c linux-3.18.12/arch/mn10300/mm/fault.c
---- linux-3.18.12.orig/arch/mn10300/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/mn10300/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/mn10300/mm/fault.c linux-3.18.14-rt/arch/mn10300/mm/fault.c
+--- linux-3.18.14.orig/arch/mn10300/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/mn10300/mm/fault.c 2015-05-31 15:32:46.113635388 -0500
@@ -168,7 +168,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -1024,9 +3096,9 @@ diff -Nur linux-3.18.12.orig/arch/mn10300/mm/fault.c linux-3.18.12/arch/mn10300/
goto no_context;
if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
-diff -Nur linux-3.18.12.orig/arch/parisc/mm/fault.c linux-3.18.12/arch/parisc/mm/fault.c
---- linux-3.18.12.orig/arch/parisc/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/parisc/mm/fault.c 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/parisc/mm/fault.c linux-3.18.14-rt/arch/parisc/mm/fault.c
+--- linux-3.18.14.orig/arch/parisc/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/parisc/mm/fault.c 2015-05-31 15:32:46.113635388 -0500
@@ -207,7 +207,7 @@
int fault;
unsigned int flags;
@@ -1036,9 +3108,9 @@ diff -Nur linux-3.18.12.orig/arch/parisc/mm/fault.c linux-3.18.12/arch/parisc/mm
goto no_context;
tsk = current;
-diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/kvm_host.h linux-3.18.12/arch/powerpc/include/asm/kvm_host.h
---- linux-3.18.12.orig/arch/powerpc/include/asm/kvm_host.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/include/asm/kvm_host.h 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/include/asm/kvm_host.h linux-3.18.14-rt/arch/powerpc/include/asm/kvm_host.h
+--- linux-3.18.14.orig/arch/powerpc/include/asm/kvm_host.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/include/asm/kvm_host.h 2015-05-31 15:32:46.145635388 -0500
@@ -296,7 +296,7 @@
u8 in_guest;
struct list_head runnable_threads;
@@ -1057,9 +3129,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/kvm_host.h linux-3.18.12/a
struct kvmppc_vcore *vcore;
int ret;
int trap;
-diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/thread_info.h linux-3.18.12/arch/powerpc/include/asm/thread_info.h
---- linux-3.18.12.orig/arch/powerpc/include/asm/thread_info.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/include/asm/thread_info.h 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/include/asm/thread_info.h linux-3.18.14-rt/arch/powerpc/include/asm/thread_info.h
+--- linux-3.18.14.orig/arch/powerpc/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/include/asm/thread_info.h 2015-05-31 15:32:46.165635388 -0500
@@ -43,6 +43,8 @@
int cpu; /* cpu we're on */
int preempt_count; /* 0 => preemptable,
@@ -1106,9 +3178,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/thread_info.h linux-3.18.1
/* Bits in local_flags */
/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
-diff -Nur linux-3.18.12.orig/arch/powerpc/Kconfig linux-3.18.12/arch/powerpc/Kconfig
---- linux-3.18.12.orig/arch/powerpc/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/Kconfig 2015-04-26 13:32:22.367684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/Kconfig linux-3.18.14-rt/arch/powerpc/Kconfig
+--- linux-3.18.14.orig/arch/powerpc/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/Kconfig 2015-05-31 15:32:46.141635388 -0500
@@ -60,10 +60,11 @@
config RWSEM_GENERIC_SPINLOCK
@@ -1139,9 +3211,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/Kconfig linux-3.18.12/arch/powerpc/Kco
source kernel/Kconfig.hz
source kernel/Kconfig.preempt
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/asm-offsets.c linux-3.18.12/arch/powerpc/kernel/asm-offsets.c
---- linux-3.18.12.orig/arch/powerpc/kernel/asm-offsets.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/asm-offsets.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/asm-offsets.c linux-3.18.14-rt/arch/powerpc/kernel/asm-offsets.c
+--- linux-3.18.14.orig/arch/powerpc/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/asm-offsets.c 2015-05-31 15:32:46.205635388 -0500
@@ -159,6 +159,7 @@
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
@@ -1150,9 +3222,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/asm-offsets.c linux-3.18.12/arc
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_32.S linux-3.18.12/arch/powerpc/kernel/entry_32.S
---- linux-3.18.12.orig/arch/powerpc/kernel/entry_32.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/entry_32.S 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/entry_32.S linux-3.18.14-rt/arch/powerpc/kernel/entry_32.S
+--- linux-3.18.14.orig/arch/powerpc/kernel/entry_32.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/entry_32.S 2015-05-31 15:32:46.217635387 -0500
@@ -890,7 +890,14 @@
cmpwi 0,r0,0 /* if non-zero, just restore regs and return */
bne restore
@@ -1201,9 +3273,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_32.S linux-3.18.12/arch/p
bne- do_resched
andi. r0,r9,_TIF_USER_WORK_MASK
beq restore_user
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_64.S linux-3.18.12/arch/powerpc/kernel/entry_64.S
---- linux-3.18.12.orig/arch/powerpc/kernel/entry_64.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/entry_64.S 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/entry_64.S linux-3.18.14-rt/arch/powerpc/kernel/entry_64.S
+--- linux-3.18.14.orig/arch/powerpc/kernel/entry_64.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/entry_64.S 2015-05-31 15:32:46.241635387 -0500
@@ -644,7 +644,7 @@
#else
beq restore
@@ -1242,9 +3314,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_64.S linux-3.18.12/arch/p
bne 1b
/*
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/irq.c linux-3.18.12/arch/powerpc/kernel/irq.c
---- linux-3.18.12.orig/arch/powerpc/kernel/irq.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/irq.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/irq.c linux-3.18.14-rt/arch/powerpc/kernel/irq.c
+--- linux-3.18.14.orig/arch/powerpc/kernel/irq.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/irq.c 2015-05-31 15:32:46.245635387 -0500
@@ -615,6 +615,7 @@
}
}
@@ -1261,9 +3333,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/irq.c linux-3.18.12/arch/powerp
irq_hw_number_t virq_to_hw(unsigned int virq)
{
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_32.S linux-3.18.12/arch/powerpc/kernel/misc_32.S
---- linux-3.18.12.orig/arch/powerpc/kernel/misc_32.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/misc_32.S 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/misc_32.S linux-3.18.14-rt/arch/powerpc/kernel/misc_32.S
+--- linux-3.18.14.orig/arch/powerpc/kernel/misc_32.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/misc_32.S 2015-05-31 15:32:46.261635387 -0500
@@ -40,6 +40,7 @@
* We store the saved ksp_limit in the unused part
* of the STACK_FRAME_OVERHEAD
@@ -1280,9 +3352,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_32.S linux-3.18.12/arch/po
/*
* void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_64.S linux-3.18.12/arch/powerpc/kernel/misc_64.S
---- linux-3.18.12.orig/arch/powerpc/kernel/misc_64.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/misc_64.S 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/misc_64.S linux-3.18.14-rt/arch/powerpc/kernel/misc_64.S
+--- linux-3.18.14.orig/arch/powerpc/kernel/misc_64.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/misc_64.S 2015-05-31 15:32:46.261635387 -0500
@@ -29,6 +29,7 @@
.text
@@ -1299,9 +3371,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_64.S linux-3.18.12/arch/po
_GLOBAL(call_do_irq)
mflr r0
-diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/time.c linux-3.18.12/arch/powerpc/kernel/time.c
---- linux-3.18.12.orig/arch/powerpc/kernel/time.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kernel/time.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/time.c linux-3.18.14-rt/arch/powerpc/kernel/time.c
+--- linux-3.18.14.orig/arch/powerpc/kernel/time.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kernel/time.c 2015-05-31 15:32:46.261635387 -0500
@@ -424,7 +424,7 @@
EXPORT_SYMBOL(profile_pc);
#endif
@@ -1311,9 +3383,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/time.c linux-3.18.12/arch/power
/*
* 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
-diff -Nur linux-3.18.12.orig/arch/powerpc/kvm/book3s_hv.c linux-3.18.12/arch/powerpc/kvm/book3s_hv.c
---- linux-3.18.12.orig/arch/powerpc/kvm/book3s_hv.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/kvm/book3s_hv.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kvm/book3s_hv.c linux-3.18.14-rt/arch/powerpc/kvm/book3s_hv.c
+--- linux-3.18.14.orig/arch/powerpc/kvm/book3s_hv.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kvm/book3s_hv.c 2015-05-31 15:32:46.301635387 -0500
@@ -84,11 +84,11 @@
{
int me;
@@ -1375,9 +3447,20 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kvm/book3s_hv.c linux-3.18.12/arch/pow
}
}
-diff -Nur linux-3.18.12.orig/arch/powerpc/mm/fault.c linux-3.18.12/arch/powerpc/mm/fault.c
---- linux-3.18.12.orig/arch/powerpc/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/powerpc/mm/fault.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/powerpc/kvm/Kconfig linux-3.18.14-rt/arch/powerpc/kvm/Kconfig
+--- linux-3.18.14.orig/arch/powerpc/kvm/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/kvm/Kconfig 2015-05-31 15:32:46.281635387 -0500
+@@ -157,6 +157,7 @@
+ config KVM_MPIC
+ bool "KVM in-kernel MPIC emulation"
+ depends on KVM && E500
++ depends on !PREEMPT_RT_FULL
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
+ select HAVE_KVM_IRQ_ROUTING
+diff -Nur linux-3.18.14.orig/arch/powerpc/mm/fault.c linux-3.18.14-rt/arch/powerpc/mm/fault.c
+--- linux-3.18.14.orig/arch/powerpc/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/powerpc/mm/fault.c 2015-05-31 15:32:46.325635386 -0500
@@ -273,7 +273,7 @@
if (!arch_irq_disabled_regs(regs))
local_irq_enable();
@@ -1387,9 +3470,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/mm/fault.c linux-3.18.12/arch/powerpc/
if (!user_mode(regs)) {
rc = SIGSEGV;
goto bail;
-diff -Nur linux-3.18.12.orig/arch/s390/include/asm/kvm_host.h linux-3.18.12/arch/s390/include/asm/kvm_host.h
---- linux-3.18.12.orig/arch/s390/include/asm/kvm_host.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/s390/include/asm/kvm_host.h 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/s390/include/asm/kvm_host.h linux-3.18.14-rt/arch/s390/include/asm/kvm_host.h
+--- linux-3.18.14.orig/arch/s390/include/asm/kvm_host.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/s390/include/asm/kvm_host.h 2015-05-31 15:32:46.369635386 -0500
@@ -311,7 +311,7 @@
struct list_head list;
atomic_t active;
@@ -1399,10 +3482,10 @@ diff -Nur linux-3.18.12.orig/arch/s390/include/asm/kvm_host.h linux-3.18.12/arch
atomic_t *cpuflags;
unsigned int action_bits;
};
-diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/kvm/interrupt.c
---- linux-3.18.12.orig/arch/s390/kvm/interrupt.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/s390/kvm/interrupt.c 2015-04-26 13:32:22.371684003 -0500
-@@ -619,13 +619,13 @@
+diff -Nur linux-3.18.14.orig/arch/s390/kvm/interrupt.c linux-3.18.14-rt/arch/s390/kvm/interrupt.c
+--- linux-3.18.14.orig/arch/s390/kvm/interrupt.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/s390/kvm/interrupt.c 2015-05-31 15:32:46.385635386 -0500
+@@ -620,13 +620,13 @@
void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
{
@@ -1418,7 +3501,7 @@ diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/k
vcpu->stat.halt_wakeup++;
}
}
-@@ -746,7 +746,7 @@
+@@ -747,7 +747,7 @@
spin_lock(&li->lock);
list_add(&inti->list, &li->list);
atomic_set(&li->active, 1);
@@ -1427,7 +3510,7 @@ diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/k
spin_unlock(&li->lock);
return 0;
}
-@@ -771,7 +771,7 @@
+@@ -772,7 +772,7 @@
spin_lock(&li->lock);
list_add(&inti->list, &li->list);
atomic_set(&li->active, 1);
@@ -1436,9 +3519,1554 @@ diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/k
spin_unlock(&li->lock);
return 0;
}
-diff -Nur linux-3.18.12.orig/arch/s390/mm/fault.c linux-3.18.12/arch/s390/mm/fault.c
---- linux-3.18.12.orig/arch/s390/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/s390/mm/fault.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/s390/kvm/interrupt.c.orig linux-3.18.14-rt/arch/s390/kvm/interrupt.c.orig
+--- linux-3.18.14.orig/arch/s390/kvm/interrupt.c.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/arch/s390/kvm/interrupt.c.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,1541 @@
++/*
++ * handling kvm guest interrupts
++ *
++ * Copyright IBM Corp. 2008,2014
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License (version 2 only)
++ * as published by the Free Software Foundation.
++ *
++ * Author(s): Carsten Otte <cotte@de.ibm.com>
++ */
++
++#include <linux/interrupt.h>
++#include <linux/kvm_host.h>
++#include <linux/hrtimer.h>
++#include <linux/mmu_context.h>
++#include <linux/signal.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <asm/asm-offsets.h>
++#include <asm/uaccess.h>
++#include "kvm-s390.h"
++#include "gaccess.h"
++#include "trace-s390.h"
++
++#define IOINT_SCHID_MASK 0x0000ffff
++#define IOINT_SSID_MASK 0x00030000
++#define IOINT_CSSID_MASK 0x03fc0000
++#define IOINT_AI_MASK 0x04000000
++#define PFAULT_INIT 0x0600
++
++static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu);
++
++static int is_ioint(u64 type)
++{
++ return ((type & 0xfffe0000u) != 0xfffe0000u);
++}
++
++int psw_extint_disabled(struct kvm_vcpu *vcpu)
++{
++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT);
++}
++
++static int psw_ioint_disabled(struct kvm_vcpu *vcpu)
++{
++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO);
++}
++
++static int psw_mchk_disabled(struct kvm_vcpu *vcpu)
++{
++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_MCHECK);
++}
++
++static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
++{
++ if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) ||
++ (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO) ||
++ (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT))
++ return 0;
++ return 1;
++}
++
++static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu)
++{
++ if (psw_extint_disabled(vcpu) ||
++ !(vcpu->arch.sie_block->gcr[0] & 0x800ul))
++ return 0;
++ if (guestdbg_enabled(vcpu) && guestdbg_sstep_enabled(vcpu))
++ /* No timer interrupts when single stepping */
++ return 0;
++ return 1;
++}
++
++static u64 int_word_to_isc_bits(u32 int_word)
++{
++ u8 isc = (int_word & 0x38000000) >> 27;
++
++ return (0x80 >> isc) << 24;
++}
++
++static int __must_check __interrupt_is_deliverable(struct kvm_vcpu *vcpu,
++ struct kvm_s390_interrupt_info *inti)
++{
++ switch (inti->type) {
++ case KVM_S390_INT_EXTERNAL_CALL:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x2000ul)
++ return 1;
++ return 0;
++ case KVM_S390_INT_EMERGENCY:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x4000ul)
++ return 1;
++ return 0;
++ case KVM_S390_INT_CLOCK_COMP:
++ return ckc_interrupts_enabled(vcpu);
++ case KVM_S390_INT_CPU_TIMER:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x400ul)
++ return 1;
++ return 0;
++ case KVM_S390_INT_SERVICE:
++ case KVM_S390_INT_PFAULT_INIT:
++ case KVM_S390_INT_PFAULT_DONE:
++ case KVM_S390_INT_VIRTIO:
++ if (psw_extint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[0] & 0x200ul)
++ return 1;
++ return 0;
++ case KVM_S390_PROGRAM_INT:
++ case KVM_S390_SIGP_STOP:
++ case KVM_S390_SIGP_SET_PREFIX:
++ case KVM_S390_RESTART:
++ return 1;
++ case KVM_S390_MCHK:
++ if (psw_mchk_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14)
++ return 1;
++ return 0;
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ if (psw_ioint_disabled(vcpu))
++ return 0;
++ if (vcpu->arch.sie_block->gcr[6] &
++ int_word_to_isc_bits(inti->io.io_int_word))
++ return 1;
++ return 0;
++ default:
++ printk(KERN_WARNING "illegal interrupt type %llx\n",
++ inti->type);
++ BUG();
++ }
++ return 0;
++}
++
++static void __set_cpu_idle(struct kvm_vcpu *vcpu)
++{
++ atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
++ set_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
++}
++
++static void __unset_cpu_idle(struct kvm_vcpu *vcpu)
++{
++ atomic_clear_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
++ clear_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
++}
++
++static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
++{
++ atomic_clear_mask(CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT,
++ &vcpu->arch.sie_block->cpuflags);
++ vcpu->arch.sie_block->lctl = 0x0000;
++ vcpu->arch.sie_block->ictl &= ~(ICTL_LPSW | ICTL_STCTL | ICTL_PINT);
++
++ if (guestdbg_enabled(vcpu)) {
++ vcpu->arch.sie_block->lctl |= (LCTL_CR0 | LCTL_CR9 |
++ LCTL_CR10 | LCTL_CR11);
++ vcpu->arch.sie_block->ictl |= (ICTL_STCTL | ICTL_PINT);
++ }
++
++ if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP)
++ atomic_set_mask(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags);
++}
++
++static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
++{
++ atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags);
++}
++
++static void __set_intercept_indicator(struct kvm_vcpu *vcpu,
++ struct kvm_s390_interrupt_info *inti)
++{
++ switch (inti->type) {
++ case KVM_S390_INT_EXTERNAL_CALL:
++ case KVM_S390_INT_EMERGENCY:
++ case KVM_S390_INT_SERVICE:
++ case KVM_S390_INT_PFAULT_INIT:
++ case KVM_S390_INT_PFAULT_DONE:
++ case KVM_S390_INT_VIRTIO:
++ case KVM_S390_INT_CLOCK_COMP:
++ case KVM_S390_INT_CPU_TIMER:
++ if (psw_extint_disabled(vcpu))
++ __set_cpuflag(vcpu, CPUSTAT_EXT_INT);
++ else
++ vcpu->arch.sie_block->lctl |= LCTL_CR0;
++ break;
++ case KVM_S390_SIGP_STOP:
++ __set_cpuflag(vcpu, CPUSTAT_STOP_INT);
++ break;
++ case KVM_S390_MCHK:
++ if (psw_mchk_disabled(vcpu))
++ vcpu->arch.sie_block->ictl |= ICTL_LPSW;
++ else
++ vcpu->arch.sie_block->lctl |= LCTL_CR14;
++ break;
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ if (psw_ioint_disabled(vcpu))
++ __set_cpuflag(vcpu, CPUSTAT_IO_INT);
++ else
++ vcpu->arch.sie_block->lctl |= LCTL_CR6;
++ break;
++ default:
++ BUG();
++ }
++}
++
++static u16 get_ilc(struct kvm_vcpu *vcpu)
++{
++ const unsigned short table[] = { 2, 4, 4, 6 };
++
++ switch (vcpu->arch.sie_block->icptcode) {
++ case ICPT_INST:
++ case ICPT_INSTPROGI:
++ case ICPT_OPEREXC:
++ case ICPT_PARTEXEC:
++ case ICPT_IOINST:
++ /* last instruction only stored for these icptcodes */
++ return table[vcpu->arch.sie_block->ipa >> 14];
++ case ICPT_PROGI:
++ return vcpu->arch.sie_block->pgmilc;
++ default:
++ return 0;
++ }
++}
++
++static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu,
++ struct kvm_s390_pgm_info *pgm_info)
++{
++ int rc = 0;
++ u16 ilc = get_ilc(vcpu);
++
++ switch (pgm_info->code & ~PGM_PER) {
++ case PGM_AFX_TRANSLATION:
++ case PGM_ASX_TRANSLATION:
++ case PGM_EX_TRANSLATION:
++ case PGM_LFX_TRANSLATION:
++ case PGM_LSTE_SEQUENCE:
++ case PGM_LSX_TRANSLATION:
++ case PGM_LX_TRANSLATION:
++ case PGM_PRIMARY_AUTHORITY:
++ case PGM_SECONDARY_AUTHORITY:
++ case PGM_SPACE_SWITCH:
++ rc = put_guest_lc(vcpu, pgm_info->trans_exc_code,
++ (u64 *)__LC_TRANS_EXC_CODE);
++ break;
++ case PGM_ALEN_TRANSLATION:
++ case PGM_ALE_SEQUENCE:
++ case PGM_ASTE_INSTANCE:
++ case PGM_ASTE_SEQUENCE:
++ case PGM_ASTE_VALIDITY:
++ case PGM_EXTENDED_AUTHORITY:
++ rc = put_guest_lc(vcpu, pgm_info->exc_access_id,
++ (u8 *)__LC_EXC_ACCESS_ID);
++ break;
++ case PGM_ASCE_TYPE:
++ case PGM_PAGE_TRANSLATION:
++ case PGM_REGION_FIRST_TRANS:
++ case PGM_REGION_SECOND_TRANS:
++ case PGM_REGION_THIRD_TRANS:
++ case PGM_SEGMENT_TRANSLATION:
++ rc = put_guest_lc(vcpu, pgm_info->trans_exc_code,
++ (u64 *)__LC_TRANS_EXC_CODE);
++ rc |= put_guest_lc(vcpu, pgm_info->exc_access_id,
++ (u8 *)__LC_EXC_ACCESS_ID);
++ rc |= put_guest_lc(vcpu, pgm_info->op_access_id,
++ (u8 *)__LC_OP_ACCESS_ID);
++ break;
++ case PGM_MONITOR:
++ rc = put_guest_lc(vcpu, pgm_info->mon_class_nr,
++ (u16 *)__LC_MON_CLASS_NR);
++ rc |= put_guest_lc(vcpu, pgm_info->mon_code,
++ (u64 *)__LC_MON_CODE);
++ break;
++ case PGM_DATA:
++ rc = put_guest_lc(vcpu, pgm_info->data_exc_code,
++ (u32 *)__LC_DATA_EXC_CODE);
++ break;
++ case PGM_PROTECTION:
++ rc = put_guest_lc(vcpu, pgm_info->trans_exc_code,
++ (u64 *)__LC_TRANS_EXC_CODE);
++ rc |= put_guest_lc(vcpu, pgm_info->exc_access_id,
++ (u8 *)__LC_EXC_ACCESS_ID);
++ break;
++ }
++
++ if (pgm_info->code & PGM_PER) {
++ rc |= put_guest_lc(vcpu, pgm_info->per_code,
++ (u8 *) __LC_PER_CODE);
++ rc |= put_guest_lc(vcpu, pgm_info->per_atmid,
++ (u8 *)__LC_PER_ATMID);
++ rc |= put_guest_lc(vcpu, pgm_info->per_address,
++ (u64 *) __LC_PER_ADDRESS);
++ rc |= put_guest_lc(vcpu, pgm_info->per_access_id,
++ (u8 *) __LC_PER_ACCESS_ID);
++ }
++
++ rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC);
++ rc |= put_guest_lc(vcpu, pgm_info->code,
++ (u16 *)__LC_PGM_INT_CODE);
++ rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++
++ return rc;
++}
++
++static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu,
++ struct kvm_s390_interrupt_info *inti)
++{
++ const unsigned short table[] = { 2, 4, 4, 6 };
++ int rc = 0;
++
++ switch (inti->type) {
++ case KVM_S390_INT_EMERGENCY:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
++ vcpu->stat.deliver_emergency_signal++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->emerg.code, 0);
++ rc = put_guest_lc(vcpu, 0x1201, (u16 *)__LC_EXT_INT_CODE);
++ rc |= put_guest_lc(vcpu, inti->emerg.code,
++ (u16 *)__LC_EXT_CPU_ADDR);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ break;
++ case KVM_S390_INT_EXTERNAL_CALL:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
++ vcpu->stat.deliver_external_call++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->extcall.code, 0);
++ rc = put_guest_lc(vcpu, 0x1202, (u16 *)__LC_EXT_INT_CODE);
++ rc |= put_guest_lc(vcpu, inti->extcall.code,
++ (u16 *)__LC_EXT_CPU_ADDR);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ break;
++ case KVM_S390_INT_CLOCK_COMP:
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->ext.ext_params, 0);
++ rc = deliver_ckc_interrupt(vcpu);
++ break;
++ case KVM_S390_INT_CPU_TIMER:
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->ext.ext_params, 0);
++ rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER,
++ (u16 *)__LC_EXT_INT_CODE);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= put_guest_lc(vcpu, inti->ext.ext_params,
++ (u32 *)__LC_EXT_PARAMS);
++ break;
++ case KVM_S390_INT_SERVICE:
++ VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
++ inti->ext.ext_params);
++ vcpu->stat.deliver_service_signal++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->ext.ext_params, 0);
++ rc = put_guest_lc(vcpu, 0x2401, (u16 *)__LC_EXT_INT_CODE);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= put_guest_lc(vcpu, inti->ext.ext_params,
++ (u32 *)__LC_EXT_PARAMS);
++ break;
++ case KVM_S390_INT_PFAULT_INIT:
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0,
++ inti->ext.ext_params2);
++ rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE,
++ (u16 *) __LC_EXT_INT_CODE);
++ rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
++ (u64 *) __LC_EXT_PARAMS2);
++ break;
++ case KVM_S390_INT_PFAULT_DONE:
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0,
++ inti->ext.ext_params2);
++ rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE);
++ rc |= put_guest_lc(vcpu, 0x0680, (u16 *)__LC_EXT_CPU_ADDR);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
++ (u64 *)__LC_EXT_PARAMS2);
++ break;
++ case KVM_S390_INT_VIRTIO:
++ VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
++ inti->ext.ext_params, inti->ext.ext_params2);
++ vcpu->stat.deliver_virtio_interrupt++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->ext.ext_params,
++ inti->ext.ext_params2);
++ rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE);
++ rc |= put_guest_lc(vcpu, 0x0d00, (u16 *)__LC_EXT_CPU_ADDR);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= put_guest_lc(vcpu, inti->ext.ext_params,
++ (u32 *)__LC_EXT_PARAMS);
++ rc |= put_guest_lc(vcpu, inti->ext.ext_params2,
++ (u64 *)__LC_EXT_PARAMS2);
++ break;
++ case KVM_S390_SIGP_STOP:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
++ vcpu->stat.deliver_stop_signal++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ 0, 0);
++ __set_intercept_indicator(vcpu, inti);
++ break;
++
++ case KVM_S390_SIGP_SET_PREFIX:
++ VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
++ inti->prefix.address);
++ vcpu->stat.deliver_prefix_signal++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->prefix.address, 0);
++ kvm_s390_set_prefix(vcpu, inti->prefix.address);
++ break;
++
++ case KVM_S390_RESTART:
++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
++ vcpu->stat.deliver_restart_signal++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ 0, 0);
++ rc = write_guest_lc(vcpu,
++ offsetof(struct _lowcore, restart_old_psw),
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw),
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ break;
++ case KVM_S390_PROGRAM_INT:
++ VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
++ inti->pgm.code,
++ table[vcpu->arch.sie_block->ipa >> 14]);
++ vcpu->stat.deliver_program_int++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->pgm.code, 0);
++ rc = __deliver_prog_irq(vcpu, &inti->pgm);
++ break;
++
++ case KVM_S390_MCHK:
++ VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
++ inti->mchk.mcic);
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ inti->mchk.cr14,
++ inti->mchk.mcic);
++ rc = kvm_s390_vcpu_store_status(vcpu,
++ KVM_S390_STORE_STATUS_PREFIXED);
++ rc |= put_guest_lc(vcpu, inti->mchk.mcic, (u64 *)__LC_MCCK_CODE);
++ rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ break;
++
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ {
++ __u32 param0 = ((__u32)inti->io.subchannel_id << 16) |
++ inti->io.subchannel_nr;
++ __u64 param1 = ((__u64)inti->io.io_int_parm << 32) |
++ inti->io.io_int_word;
++ VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
++ vcpu->stat.deliver_io_int++;
++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
++ param0, param1);
++ rc = put_guest_lc(vcpu, inti->io.subchannel_id,
++ (u16 *)__LC_SUBCHANNEL_ID);
++ rc |= put_guest_lc(vcpu, inti->io.subchannel_nr,
++ (u16 *)__LC_SUBCHANNEL_NR);
++ rc |= put_guest_lc(vcpu, inti->io.io_int_parm,
++ (u32 *)__LC_IO_INT_PARM);
++ rc |= put_guest_lc(vcpu, inti->io.io_int_word,
++ (u32 *)__LC_IO_INT_WORD);
++ rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ break;
++ }
++ default:
++ BUG();
++ }
++
++ return rc;
++}
++
++static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu)
++{
++ int rc;
++
++ rc = put_guest_lc(vcpu, 0x1004, (u16 __user *)__LC_EXT_INT_CODE);
++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
++ &vcpu->arch.sie_block->gpsw,
++ sizeof(psw_t));
++ return rc;
++}
++
++/* Check whether SIGP interpretation facility has an external call pending */
++int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu)
++{
++ atomic_t *sigp_ctrl = &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl;
++
++ if (!psw_extint_disabled(vcpu) &&
++ (vcpu->arch.sie_block->gcr[0] & 0x2000ul) &&
++ (atomic_read(sigp_ctrl) & SIGP_CTRL_C) &&
++ (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_ECALL_PEND))
++ return 1;
++
++ return 0;
++}
++
++int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
++{
++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
++ struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
++ struct kvm_s390_interrupt_info *inti;
++ int rc = 0;
++
++ if (atomic_read(&li->active)) {
++ spin_lock(&li->lock);
++ list_for_each_entry(inti, &li->list, list)
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ rc = 1;
++ break;
++ }
++ spin_unlock(&li->lock);
++ }
++
++ if ((!rc) && atomic_read(&fi->active)) {
++ spin_lock(&fi->lock);
++ list_for_each_entry(inti, &fi->list, list)
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ rc = 1;
++ break;
++ }
++ spin_unlock(&fi->lock);
++ }
++
++ if (!rc && kvm_cpu_has_pending_timer(vcpu))
++ rc = 1;
++
++ if (!rc && kvm_s390_si_ext_call_pending(vcpu))
++ rc = 1;
++
++ return rc;
++}
++
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
++{
++ if (!(vcpu->arch.sie_block->ckc <
++ get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
++ return 0;
++ if (!ckc_interrupts_enabled(vcpu))
++ return 0;
++ return 1;
++}
++
++int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
++{
++ u64 now, sltime;
++
++ vcpu->stat.exit_wait_state++;
++
++ /* fast path */
++ if (kvm_cpu_has_pending_timer(vcpu) || kvm_arch_vcpu_runnable(vcpu))
++ return 0;
++
++ if (psw_interrupts_disabled(vcpu)) {
++ VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
++ return -EOPNOTSUPP; /* disabled wait */
++ }
++
++ __set_cpu_idle(vcpu);
++ if (!ckc_interrupts_enabled(vcpu)) {
++ VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer");
++ goto no_timer;
++ }
++
++ now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
++ sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
++ hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
++ VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
++no_timer:
++ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
++ kvm_vcpu_block(vcpu);
++ __unset_cpu_idle(vcpu);
++ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
++
++ hrtimer_cancel(&vcpu->arch.ckc_timer);
++ return 0;
++}
++
++void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
++{
++ if (waitqueue_active(&vcpu->wq)) {
++ /*
++ * The vcpu gave up the cpu voluntarily, mark it as a good
++ * yield-candidate.
++ */
++ vcpu->preempted = true;
++ wake_up_interruptible(&vcpu->wq);
++ vcpu->stat.halt_wakeup++;
++ }
++}
++
++enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
++{
++ struct kvm_vcpu *vcpu;
++ u64 now, sltime;
++
++ vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
++ now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
++ sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
++
++ /*
++ * If the monotonic clock runs faster than the tod clock we might be
++ * woken up too early and have to go back to sleep to avoid deadlocks.
++ */
++ if (vcpu->arch.sie_block->ckc > now &&
++ hrtimer_forward_now(timer, ns_to_ktime(sltime)))
++ return HRTIMER_RESTART;
++ kvm_s390_vcpu_wakeup(vcpu);
++ return HRTIMER_NORESTART;
++}
++
++void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
++{
++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
++ struct kvm_s390_interrupt_info *n, *inti = NULL;
++
++ spin_lock(&li->lock);
++ list_for_each_entry_safe(inti, n, &li->list, list) {
++ list_del(&inti->list);
++ kfree(inti);
++ }
++ atomic_set(&li->active, 0);
++ spin_unlock(&li->lock);
++
++ /* clear pending external calls set by sigp interpretation facility */
++ atomic_clear_mask(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags);
++ atomic_clear_mask(SIGP_CTRL_C,
++ &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl);
++}
++
++int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
++{
++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
++ struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int;
++ struct kvm_s390_interrupt_info *n, *inti = NULL;
++ int deliver;
++ int rc = 0;
++
++ __reset_intercept_indicators(vcpu);
++ if (atomic_read(&li->active)) {
++ do {
++ deliver = 0;
++ spin_lock(&li->lock);
++ list_for_each_entry_safe(inti, n, &li->list, list) {
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ list_del(&inti->list);
++ deliver = 1;
++ break;
++ }
++ __set_intercept_indicator(vcpu, inti);
++ }
++ if (list_empty(&li->list))
++ atomic_set(&li->active, 0);
++ spin_unlock(&li->lock);
++ if (deliver) {
++ rc = __do_deliver_interrupt(vcpu, inti);
++ kfree(inti);
++ }
++ } while (!rc && deliver);
++ }
++
++ if (!rc && kvm_cpu_has_pending_timer(vcpu))
++ rc = deliver_ckc_interrupt(vcpu);
++
++ if (!rc && atomic_read(&fi->active)) {
++ do {
++ deliver = 0;
++ spin_lock(&fi->lock);
++ list_for_each_entry_safe(inti, n, &fi->list, list) {
++ if (__interrupt_is_deliverable(vcpu, inti)) {
++ list_del(&inti->list);
++ fi->irq_count--;
++ deliver = 1;
++ break;
++ }
++ __set_intercept_indicator(vcpu, inti);
++ }
++ if (list_empty(&fi->list))
++ atomic_set(&fi->active, 0);
++ spin_unlock(&fi->lock);
++ if (deliver) {
++ rc = __do_deliver_interrupt(vcpu, inti);
++ kfree(inti);
++ }
++ } while (!rc && deliver);
++ }
++
++ return rc;
++}
++
++int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
++{
++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
++ struct kvm_s390_interrupt_info *inti;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ inti->type = KVM_S390_PROGRAM_INT;
++ inti->pgm.code = code;
++
++ VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
++ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1);
++ spin_lock(&li->lock);
++ list_add(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ BUG_ON(waitqueue_active(li->wq));
++ spin_unlock(&li->lock);
++ return 0;
++}
++
++int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu,
++ struct kvm_s390_pgm_info *pgm_info)
++{
++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
++ struct kvm_s390_interrupt_info *inti;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ VCPU_EVENT(vcpu, 3, "inject: prog irq %d (from kernel)",
++ pgm_info->code);
++ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
++ pgm_info->code, 0, 1);
++
++ inti->type = KVM_S390_PROGRAM_INT;
++ memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm));
++ spin_lock(&li->lock);
++ list_add(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ BUG_ON(waitqueue_active(li->wq));
++ spin_unlock(&li->lock);
++ return 0;
++}
++
++struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
++ u64 cr6, u64 schid)
++{
++ struct kvm_s390_float_interrupt *fi;
++ struct kvm_s390_interrupt_info *inti, *iter;
++
++ if ((!schid && !cr6) || (schid && cr6))
++ return NULL;
++ fi = &kvm->arch.float_int;
++ spin_lock(&fi->lock);
++ inti = NULL;
++ list_for_each_entry(iter, &fi->list, list) {
++ if (!is_ioint(iter->type))
++ continue;
++ if (cr6 &&
++ ((cr6 & int_word_to_isc_bits(iter->io.io_int_word)) == 0))
++ continue;
++ if (schid) {
++ if (((schid & 0x00000000ffff0000) >> 16) !=
++ iter->io.subchannel_id)
++ continue;
++ if ((schid & 0x000000000000ffff) !=
++ iter->io.subchannel_nr)
++ continue;
++ }
++ inti = iter;
++ break;
++ }
++ if (inti) {
++ list_del_init(&inti->list);
++ fi->irq_count--;
++ }
++ if (list_empty(&fi->list))
++ atomic_set(&fi->active, 0);
++ spin_unlock(&fi->lock);
++ return inti;
++}
++
++static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
++{
++ struct kvm_s390_local_interrupt *li;
++ struct kvm_s390_float_interrupt *fi;
++ struct kvm_s390_interrupt_info *iter;
++ struct kvm_vcpu *dst_vcpu = NULL;
++ int sigcpu;
++ int rc = 0;
++
++ fi = &kvm->arch.float_int;
++ spin_lock(&fi->lock);
++ if (fi->irq_count >= KVM_S390_MAX_FLOAT_IRQS) {
++ rc = -EINVAL;
++ goto unlock_fi;
++ }
++ fi->irq_count++;
++ if (!is_ioint(inti->type)) {
++ list_add_tail(&inti->list, &fi->list);
++ } else {
++ u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word);
++
++ /* Keep I/O interrupts sorted in isc order. */
++ list_for_each_entry(iter, &fi->list, list) {
++ if (!is_ioint(iter->type))
++ continue;
++ if (int_word_to_isc_bits(iter->io.io_int_word)
++ <= isc_bits)
++ continue;
++ break;
++ }
++ list_add_tail(&inti->list, &iter->list);
++ }
++ atomic_set(&fi->active, 1);
++ if (atomic_read(&kvm->online_vcpus) == 0)
++ goto unlock_fi;
++ sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS);
++ if (sigcpu == KVM_MAX_VCPUS) {
++ do {
++ sigcpu = fi->next_rr_cpu++;
++ if (sigcpu == KVM_MAX_VCPUS)
++ sigcpu = fi->next_rr_cpu = 0;
++ } while (kvm_get_vcpu(kvm, sigcpu) == NULL);
++ }
++ dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
++ li = &dst_vcpu->arch.local_int;
++ spin_lock(&li->lock);
++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
++ spin_unlock(&li->lock);
++ kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu));
++unlock_fi:
++ spin_unlock(&fi->lock);
++ return rc;
++}
++
++int kvm_s390_inject_vm(struct kvm *kvm,
++ struct kvm_s390_interrupt *s390int)
++{
++ struct kvm_s390_interrupt_info *inti;
++ int rc;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ inti->type = s390int->type;
++ switch (inti->type) {
++ case KVM_S390_INT_VIRTIO:
++ VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx",
++ s390int->parm, s390int->parm64);
++ inti->ext.ext_params = s390int->parm;
++ inti->ext.ext_params2 = s390int->parm64;
++ break;
++ case KVM_S390_INT_SERVICE:
++ VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
++ inti->ext.ext_params = s390int->parm;
++ break;
++ case KVM_S390_INT_PFAULT_DONE:
++ inti->type = s390int->type;
++ inti->ext.ext_params2 = s390int->parm64;
++ break;
++ case KVM_S390_MCHK:
++ VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
++ s390int->parm64);
++ inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
++ inti->mchk.mcic = s390int->parm64;
++ break;
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ if (inti->type & IOINT_AI_MASK)
++ VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
++ else
++ VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
++ s390int->type & IOINT_CSSID_MASK,
++ s390int->type & IOINT_SSID_MASK,
++ s390int->type & IOINT_SCHID_MASK);
++ inti->io.subchannel_id = s390int->parm >> 16;
++ inti->io.subchannel_nr = s390int->parm & 0x0000ffffu;
++ inti->io.io_int_parm = s390int->parm64 >> 32;
++ inti->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull;
++ break;
++ default:
++ kfree(inti);
++ return -EINVAL;
++ }
++ trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64,
++ 2);
++
++ rc = __inject_vm(kvm, inti);
++ if (rc)
++ kfree(inti);
++ return rc;
++}
++
++int kvm_s390_reinject_io_int(struct kvm *kvm,
++ struct kvm_s390_interrupt_info *inti)
++{
++ return __inject_vm(kvm, inti);
++}
++
++int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
++ struct kvm_s390_interrupt *s390int)
++{
++ struct kvm_s390_local_interrupt *li;
++ struct kvm_s390_interrupt_info *inti;
++
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ switch (s390int->type) {
++ case KVM_S390_PROGRAM_INT:
++ if (s390int->parm & 0xffff0000) {
++ kfree(inti);
++ return -EINVAL;
++ }
++ inti->type = s390int->type;
++ inti->pgm.code = s390int->parm;
++ VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
++ s390int->parm);
++ break;
++ case KVM_S390_SIGP_SET_PREFIX:
++ inti->prefix.address = s390int->parm;
++ inti->type = s390int->type;
++ VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)",
++ s390int->parm);
++ break;
++ case KVM_S390_SIGP_STOP:
++ case KVM_S390_RESTART:
++ case KVM_S390_INT_CLOCK_COMP:
++ case KVM_S390_INT_CPU_TIMER:
++ VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
++ inti->type = s390int->type;
++ break;
++ case KVM_S390_INT_EXTERNAL_CALL:
++ if (s390int->parm & 0xffff0000) {
++ kfree(inti);
++ return -EINVAL;
++ }
++ VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
++ s390int->parm);
++ inti->type = s390int->type;
++ inti->extcall.code = s390int->parm;
++ break;
++ case KVM_S390_INT_EMERGENCY:
++ if (s390int->parm & 0xffff0000) {
++ kfree(inti);
++ return -EINVAL;
++ }
++ VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
++ inti->type = s390int->type;
++ inti->emerg.code = s390int->parm;
++ break;
++ case KVM_S390_MCHK:
++ VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx",
++ s390int->parm64);
++ inti->type = s390int->type;
++ inti->mchk.mcic = s390int->parm64;
++ break;
++ case KVM_S390_INT_PFAULT_INIT:
++ inti->type = s390int->type;
++ inti->ext.ext_params2 = s390int->parm64;
++ break;
++ case KVM_S390_INT_VIRTIO:
++ case KVM_S390_INT_SERVICE:
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ default:
++ kfree(inti);
++ return -EINVAL;
++ }
++ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, s390int->type, s390int->parm,
++ s390int->parm64, 2);
++
++ li = &vcpu->arch.local_int;
++ spin_lock(&li->lock);
++ if (inti->type == KVM_S390_PROGRAM_INT)
++ list_add(&inti->list, &li->list);
++ else
++ list_add_tail(&inti->list, &li->list);
++ atomic_set(&li->active, 1);
++ if (inti->type == KVM_S390_SIGP_STOP)
++ li->action_bits |= ACTION_STOP_ON_STOP;
++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
++ spin_unlock(&li->lock);
++ kvm_s390_vcpu_wakeup(vcpu);
++ return 0;
++}
++
++void kvm_s390_clear_float_irqs(struct kvm *kvm)
++{
++ struct kvm_s390_float_interrupt *fi;
++ struct kvm_s390_interrupt_info *n, *inti = NULL;
++
++ fi = &kvm->arch.float_int;
++ spin_lock(&fi->lock);
++ list_for_each_entry_safe(inti, n, &fi->list, list) {
++ list_del(&inti->list);
++ kfree(inti);
++ }
++ fi->irq_count = 0;
++ atomic_set(&fi->active, 0);
++ spin_unlock(&fi->lock);
++}
++
++static void inti_to_irq(struct kvm_s390_interrupt_info *inti,
++ struct kvm_s390_irq *irq)
++{
++ irq->type = inti->type;
++ switch (inti->type) {
++ case KVM_S390_INT_PFAULT_INIT:
++ case KVM_S390_INT_PFAULT_DONE:
++ case KVM_S390_INT_VIRTIO:
++ case KVM_S390_INT_SERVICE:
++ irq->u.ext = inti->ext;
++ break;
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ irq->u.io = inti->io;
++ break;
++ case KVM_S390_MCHK:
++ irq->u.mchk = inti->mchk;
++ break;
++ }
++}
++
++static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len)
++{
++ struct kvm_s390_interrupt_info *inti;
++ struct kvm_s390_float_interrupt *fi;
++ struct kvm_s390_irq *buf;
++ int max_irqs;
++ int ret = 0;
++ int n = 0;
++
++ if (len > KVM_S390_FLIC_MAX_BUFFER || len == 0)
++ return -EINVAL;
++
++ /*
++ * We are already using -ENOMEM to signal
++ * userspace it may retry with a bigger buffer,
++ * so we need to use something else for this case
++ */
++ buf = vzalloc(len);
++ if (!buf)
++ return -ENOBUFS;
++
++ max_irqs = len / sizeof(struct kvm_s390_irq);
++
++ fi = &kvm->arch.float_int;
++ spin_lock(&fi->lock);
++ list_for_each_entry(inti, &fi->list, list) {
++ if (n == max_irqs) {
++ /* signal userspace to try again */
++ ret = -ENOMEM;
++ break;
++ }
++ inti_to_irq(inti, &buf[n]);
++ n++;
++ }
++ spin_unlock(&fi->lock);
++ if (!ret && n > 0) {
++ if (copy_to_user(usrbuf, buf, sizeof(struct kvm_s390_irq) * n))
++ ret = -EFAULT;
++ }
++ vfree(buf);
++
++ return ret < 0 ? ret : n;
++}
++
++static int flic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
++{
++ int r;
++
++ switch (attr->group) {
++ case KVM_DEV_FLIC_GET_ALL_IRQS:
++ r = get_all_floating_irqs(dev->kvm, (u8 __user *) attr->addr,
++ attr->attr);
++ break;
++ default:
++ r = -EINVAL;
++ }
++
++ return r;
++}
++
++static inline int copy_irq_from_user(struct kvm_s390_interrupt_info *inti,
++ u64 addr)
++{
++ struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr;
++ void *target = NULL;
++ void __user *source;
++ u64 size;
++
++ if (get_user(inti->type, (u64 __user *)addr))
++ return -EFAULT;
++
++ switch (inti->type) {
++ case KVM_S390_INT_PFAULT_INIT:
++ case KVM_S390_INT_PFAULT_DONE:
++ case KVM_S390_INT_VIRTIO:
++ case KVM_S390_INT_SERVICE:
++ target = (void *) &inti->ext;
++ source = &uptr->u.ext;
++ size = sizeof(inti->ext);
++ break;
++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
++ target = (void *) &inti->io;
++ source = &uptr->u.io;
++ size = sizeof(inti->io);
++ break;
++ case KVM_S390_MCHK:
++ target = (void *) &inti->mchk;
++ source = &uptr->u.mchk;
++ size = sizeof(inti->mchk);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ if (copy_from_user(target, source, size))
++ return -EFAULT;
++
++ return 0;
++}
++
++static int enqueue_floating_irq(struct kvm_device *dev,
++ struct kvm_device_attr *attr)
++{
++ struct kvm_s390_interrupt_info *inti = NULL;
++ int r = 0;
++ int len = attr->attr;
++
++ if (len % sizeof(struct kvm_s390_irq) != 0)
++ return -EINVAL;
++ else if (len > KVM_S390_FLIC_MAX_BUFFER)
++ return -EINVAL;
++
++ while (len >= sizeof(struct kvm_s390_irq)) {
++ inti = kzalloc(sizeof(*inti), GFP_KERNEL);
++ if (!inti)
++ return -ENOMEM;
++
++ r = copy_irq_from_user(inti, attr->addr);
++ if (r) {
++ kfree(inti);
++ return r;
++ }
++ r = __inject_vm(dev->kvm, inti);
++ if (r) {
++ kfree(inti);
++ return r;
++ }
++ len -= sizeof(struct kvm_s390_irq);
++ attr->addr += sizeof(struct kvm_s390_irq);
++ }
++
++ return r;
++}
++
++static struct s390_io_adapter *get_io_adapter(struct kvm *kvm, unsigned int id)
++{
++ if (id >= MAX_S390_IO_ADAPTERS)
++ return NULL;
++ return kvm->arch.adapters[id];
++}
++
++static int register_io_adapter(struct kvm_device *dev,
++ struct kvm_device_attr *attr)
++{
++ struct s390_io_adapter *adapter;
++ struct kvm_s390_io_adapter adapter_info;
++
++ if (copy_from_user(&adapter_info,
++ (void __user *)attr->addr, sizeof(adapter_info)))
++ return -EFAULT;
++
++ if ((adapter_info.id >= MAX_S390_IO_ADAPTERS) ||
++ (dev->kvm->arch.adapters[adapter_info.id] != NULL))
++ return -EINVAL;
++
++ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
++ if (!adapter)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&adapter->maps);
++ init_rwsem(&adapter->maps_lock);
++ atomic_set(&adapter->nr_maps, 0);
++ adapter->id = adapter_info.id;
++ adapter->isc = adapter_info.isc;
++ adapter->maskable = adapter_info.maskable;
++ adapter->masked = false;
++ adapter->swap = adapter_info.swap;
++ dev->kvm->arch.adapters[adapter->id] = adapter;
++
++ return 0;
++}
++
++int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked)
++{
++ int ret;
++ struct s390_io_adapter *adapter = get_io_adapter(kvm, id);
++
++ if (!adapter || !adapter->maskable)
++ return -EINVAL;
++ ret = adapter->masked;
++ adapter->masked = masked;
++ return ret;
++}
++
++static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
++{
++ struct s390_io_adapter *adapter = get_io_adapter(kvm, id);
++ struct s390_map_info *map;
++ int ret;
++
++ if (!adapter || !addr)
++ return -EINVAL;
++
++ map = kzalloc(sizeof(*map), GFP_KERNEL);
++ if (!map) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ INIT_LIST_HEAD(&map->list);
++ map->guest_addr = addr;
++ map->addr = gmap_translate(kvm->arch.gmap, addr);
++ if (map->addr == -EFAULT) {
++ ret = -EFAULT;
++ goto out;
++ }
++ ret = get_user_pages_fast(map->addr, 1, 1, &map->page);
++ if (ret < 0)
++ goto out;
++ BUG_ON(ret != 1);
++ down_write(&adapter->maps_lock);
++ if (atomic_inc_return(&adapter->nr_maps) < MAX_S390_ADAPTER_MAPS) {
++ list_add_tail(&map->list, &adapter->maps);
++ ret = 0;
++ } else {
++ put_page(map->page);
++ ret = -EINVAL;
++ }
++ up_write(&adapter->maps_lock);
++out:
++ if (ret)
++ kfree(map);
++ return ret;
++}
++
++static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
++{
++ struct s390_io_adapter *adapter = get_io_adapter(kvm, id);
++ struct s390_map_info *map, *tmp;
++ int found = 0;
++
++ if (!adapter || !addr)
++ return -EINVAL;
++
++ down_write(&adapter->maps_lock);
++ list_for_each_entry_safe(map, tmp, &adapter->maps, list) {
++ if (map->guest_addr == addr) {
++ found = 1;
++ atomic_dec(&adapter->nr_maps);
++ list_del(&map->list);
++ put_page(map->page);
++ kfree(map);
++ break;
++ }
++ }
++ up_write(&adapter->maps_lock);
++
++ return found ? 0 : -EINVAL;
++}
++
++void kvm_s390_destroy_adapters(struct kvm *kvm)
++{
++ int i;
++ struct s390_map_info *map, *tmp;
++
++ for (i = 0; i < MAX_S390_IO_ADAPTERS; i++) {
++ if (!kvm->arch.adapters[i])
++ continue;
++ list_for_each_entry_safe(map, tmp,
++ &kvm->arch.adapters[i]->maps, list) {
++ list_del(&map->list);
++ put_page(map->page);
++ kfree(map);
++ }
++ kfree(kvm->arch.adapters[i]);
++ }
++}
++
++static int modify_io_adapter(struct kvm_device *dev,
++ struct kvm_device_attr *attr)
++{
++ struct kvm_s390_io_adapter_req req;
++ struct s390_io_adapter *adapter;
++ int ret;
++
++ if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
++ return -EFAULT;
++
++ adapter = get_io_adapter(dev->kvm, req.id);
++ if (!adapter)
++ return -EINVAL;
++ switch (req.type) {
++ case KVM_S390_IO_ADAPTER_MASK:
++ ret = kvm_s390_mask_adapter(dev->kvm, req.id, req.mask);
++ if (ret > 0)
++ ret = 0;
++ break;
++ case KVM_S390_IO_ADAPTER_MAP:
++ ret = kvm_s390_adapter_map(dev->kvm, req.id, req.addr);
++ break;
++ case KVM_S390_IO_ADAPTER_UNMAP:
++ ret = kvm_s390_adapter_unmap(dev->kvm, req.id, req.addr);
++ break;
++ default:
++ ret = -EINVAL;
++ }
++
++ return ret;
++}
++
++static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
++{
++ int r = 0;
++ unsigned int i;
++ struct kvm_vcpu *vcpu;
++
++ switch (attr->group) {
++ case KVM_DEV_FLIC_ENQUEUE:
++ r = enqueue_floating_irq(dev, attr);
++ break;
++ case KVM_DEV_FLIC_CLEAR_IRQS:
++ kvm_s390_clear_float_irqs(dev->kvm);
++ break;
++ case KVM_DEV_FLIC_APF_ENABLE:
++ dev->kvm->arch.gmap->pfault_enabled = 1;
++ break;
++ case KVM_DEV_FLIC_APF_DISABLE_WAIT:
++ dev->kvm->arch.gmap->pfault_enabled = 0;
++ /*
++ * Make sure no async faults are in transition when
++ * clearing the queues. So we don't need to worry
++ * about late coming workers.
++ */
++ synchronize_srcu(&dev->kvm->srcu);
++ kvm_for_each_vcpu(i, vcpu, dev->kvm)
++ kvm_clear_async_pf_completion_queue(vcpu);
++ break;
++ case KVM_DEV_FLIC_ADAPTER_REGISTER:
++ r = register_io_adapter(dev, attr);
++ break;
++ case KVM_DEV_FLIC_ADAPTER_MODIFY:
++ r = modify_io_adapter(dev, attr);
++ break;
++ default:
++ r = -EINVAL;
++ }
++
++ return r;
++}
++
++static int flic_create(struct kvm_device *dev, u32 type)
++{
++ if (!dev)
++ return -EINVAL;
++ if (dev->kvm->arch.flic)
++ return -EINVAL;
++ dev->kvm->arch.flic = dev;
++ return 0;
++}
++
++static void flic_destroy(struct kvm_device *dev)
++{
++ dev->kvm->arch.flic = NULL;
++ kfree(dev);
++}
++
++/* s390 floating irq controller (flic) */
++struct kvm_device_ops kvm_flic_ops = {
++ .name = "kvm-flic",
++ .get_attr = flic_get_attr,
++ .set_attr = flic_set_attr,
++ .create = flic_create,
++ .destroy = flic_destroy,
++};
++
++static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap)
++{
++ unsigned long bit;
++
++ bit = bit_nr + (addr % PAGE_SIZE) * 8;
++
++ return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit;
++}
++
++static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter,
++ u64 addr)
++{
++ struct s390_map_info *map;
++
++ if (!adapter)
++ return NULL;
++
++ list_for_each_entry(map, &adapter->maps, list) {
++ if (map->guest_addr == addr)
++ return map;
++ }
++ return NULL;
++}
++
++static int adapter_indicators_set(struct kvm *kvm,
++ struct s390_io_adapter *adapter,
++ struct kvm_s390_adapter_int *adapter_int)
++{
++ unsigned long bit;
++ int summary_set, idx;
++ struct s390_map_info *info;
++ void *map;
++
++ info = get_map_info(adapter, adapter_int->ind_addr);
++ if (!info)
++ return -1;
++ map = page_address(info->page);
++ bit = get_ind_bit(info->addr, adapter_int->ind_offset, adapter->swap);
++ set_bit(bit, map);
++ idx = srcu_read_lock(&kvm->srcu);
++ mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
++ set_page_dirty_lock(info->page);
++ info = get_map_info(adapter, adapter_int->summary_addr);
++ if (!info) {
++ srcu_read_unlock(&kvm->srcu, idx);
++ return -1;
++ }
++ map = page_address(info->page);
++ bit = get_ind_bit(info->addr, adapter_int->summary_offset,
++ adapter->swap);
++ summary_set = test_and_set_bit(bit, map);
++ mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
++ set_page_dirty_lock(info->page);
++ srcu_read_unlock(&kvm->srcu, idx);
++ return summary_set ? 0 : 1;
++}
++
++/*
++ * < 0 - not injected due to error
++ * = 0 - coalesced, summary indicator already active
++ * > 0 - injected interrupt
++ */
++static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
++ struct kvm *kvm, int irq_source_id, int level,
++ bool line_status)
++{
++ int ret;
++ struct s390_io_adapter *adapter;
++
++ /* We're only interested in the 0->1 transition. */
++ if (!level)
++ return 0;
++ adapter = get_io_adapter(kvm, e->adapter.adapter_id);
++ if (!adapter)
++ return -1;
++ down_read(&adapter->maps_lock);
++ ret = adapter_indicators_set(kvm, adapter, &e->adapter);
++ up_read(&adapter->maps_lock);
++ if ((ret > 0) && !adapter->masked) {
++ struct kvm_s390_interrupt s390int = {
++ .type = KVM_S390_INT_IO(1, 0, 0, 0),
++ .parm = 0,
++ .parm64 = (adapter->isc << 27) | 0x80000000,
++ };
++ ret = kvm_s390_inject_vm(kvm, &s390int);
++ if (ret == 0)
++ ret = 1;
++ }
++ return ret;
++}
++
++int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
++ const struct kvm_irq_routing_entry *ue)
++{
++ int ret;
++
++ switch (ue->type) {
++ case KVM_IRQ_ROUTING_S390_ADAPTER:
++ e->set = set_adapter_int;
++ e->adapter.summary_addr = ue->u.adapter.summary_addr;
++ e->adapter.ind_addr = ue->u.adapter.ind_addr;
++ e->adapter.summary_offset = ue->u.adapter.summary_offset;
++ e->adapter.ind_offset = ue->u.adapter.ind_offset;
++ e->adapter.adapter_id = ue->u.adapter.adapter_id;
++ ret = 0;
++ break;
++ default:
++ ret = -EINVAL;
++ }
++
++ return ret;
++}
++
++int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
++ int irq_source_id, int level, bool line_status)
++{
++ return -EINVAL;
++}
+diff -Nur linux-3.18.14.orig/arch/s390/mm/fault.c linux-3.18.14-rt/arch/s390/mm/fault.c
+--- linux-3.18.14.orig/arch/s390/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/s390/mm/fault.c 2015-05-31 15:32:46.401635385 -0500
@@ -435,7 +435,8 @@
* user context.
*/
@@ -1449,9 +5077,9 @@ diff -Nur linux-3.18.12.orig/arch/s390/mm/fault.c linux-3.18.12/arch/s390/mm/fau
goto out;
address = trans_exc_code & __FAIL_ADDR_MASK;
-diff -Nur linux-3.18.12.orig/arch/score/mm/fault.c linux-3.18.12/arch/score/mm/fault.c
---- linux-3.18.12.orig/arch/score/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/score/mm/fault.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/score/mm/fault.c linux-3.18.14-rt/arch/score/mm/fault.c
+--- linux-3.18.14.orig/arch/score/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/score/mm/fault.c 2015-05-31 15:32:46.413635385 -0500
@@ -73,7 +73,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -1461,9 +5089,9 @@ diff -Nur linux-3.18.12.orig/arch/score/mm/fault.c linux-3.18.12/arch/score/mm/f
goto bad_area_nosemaphore;
if (user_mode(regs))
-diff -Nur linux-3.18.12.orig/arch/sh/kernel/irq.c linux-3.18.12/arch/sh/kernel/irq.c
---- linux-3.18.12.orig/arch/sh/kernel/irq.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sh/kernel/irq.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sh/kernel/irq.c linux-3.18.14-rt/arch/sh/kernel/irq.c
+--- linux-3.18.14.orig/arch/sh/kernel/irq.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sh/kernel/irq.c 2015-05-31 15:32:46.429635385 -0500
@@ -149,6 +149,7 @@
hardirq_ctx[cpu] = NULL;
}
@@ -1480,9 +5108,9 @@ diff -Nur linux-3.18.12.orig/arch/sh/kernel/irq.c linux-3.18.12/arch/sh/kernel/i
#else
static inline void handle_one_irq(unsigned int irq)
{
-diff -Nur linux-3.18.12.orig/arch/sh/mm/fault.c linux-3.18.12/arch/sh/mm/fault.c
---- linux-3.18.12.orig/arch/sh/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sh/mm/fault.c 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sh/mm/fault.c linux-3.18.14-rt/arch/sh/mm/fault.c
+--- linux-3.18.14.orig/arch/sh/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sh/mm/fault.c 2015-05-31 15:32:46.469635385 -0500
@@ -440,7 +440,7 @@
* If we're in an interrupt, have no user context or are running
* in an atomic region then we must not take the fault:
@@ -1492,9 +5120,9 @@ diff -Nur linux-3.18.12.orig/arch/sh/mm/fault.c linux-3.18.12/arch/sh/mm/fault.c
bad_area_nosemaphore(regs, error_code, address);
return;
}
-diff -Nur linux-3.18.12.orig/arch/sparc/Kconfig linux-3.18.12/arch/sparc/Kconfig
---- linux-3.18.12.orig/arch/sparc/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sparc/Kconfig 2015-04-26 13:32:22.371684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sparc/Kconfig linux-3.18.14-rt/arch/sparc/Kconfig
+--- linux-3.18.14.orig/arch/sparc/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sparc/Kconfig 2015-05-31 15:32:46.469635385 -0500
@@ -182,12 +182,10 @@
source kernel/Kconfig.hz
@@ -1521,9 +5149,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/Kconfig linux-3.18.12/arch/sparc/Kconfig
config COMPAT
bool
depends on SPARC64
-diff -Nur linux-3.18.12.orig/arch/sparc/kernel/irq_64.c linux-3.18.12/arch/sparc/kernel/irq_64.c
---- linux-3.18.12.orig/arch/sparc/kernel/irq_64.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sparc/kernel/irq_64.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sparc/kernel/irq_64.c linux-3.18.14-rt/arch/sparc/kernel/irq_64.c
+--- linux-3.18.14.orig/arch/sparc/kernel/irq_64.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sparc/kernel/irq_64.c 2015-05-31 15:32:46.477635385 -0500
@@ -849,6 +849,7 @@
set_irq_regs(old_regs);
}
@@ -1540,9 +5168,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/kernel/irq_64.c linux-3.18.12/arch/sparc
#ifdef CONFIG_HOTPLUG_CPU
void fixup_irqs(void)
-diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_32.c linux-3.18.12/arch/sparc/kernel/setup_32.c
---- linux-3.18.12.orig/arch/sparc/kernel/setup_32.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sparc/kernel/setup_32.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sparc/kernel/setup_32.c linux-3.18.14-rt/arch/sparc/kernel/setup_32.c
+--- linux-3.18.14.orig/arch/sparc/kernel/setup_32.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sparc/kernel/setup_32.c 2015-05-31 15:32:46.489635385 -0500
@@ -309,6 +309,7 @@
boot_flags_init(*cmdline_p);
@@ -1551,9 +5179,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_32.c linux-3.18.12/arch/spa
register_console(&prom_early_console);
printk("ARCH: ");
-diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_64.c linux-3.18.12/arch/sparc/kernel/setup_64.c
---- linux-3.18.12.orig/arch/sparc/kernel/setup_64.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sparc/kernel/setup_64.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sparc/kernel/setup_64.c linux-3.18.14-rt/arch/sparc/kernel/setup_64.c
+--- linux-3.18.14.orig/arch/sparc/kernel/setup_64.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sparc/kernel/setup_64.c 2015-05-31 15:32:46.509635384 -0500
@@ -563,6 +563,12 @@
pause_patch();
}
@@ -1576,9 +5204,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_64.c linux-3.18.12/arch/spa
if (tlb_type == hypervisor)
printk("ARCH: SUN4V\n");
-diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_32.c linux-3.18.12/arch/sparc/mm/fault_32.c
---- linux-3.18.12.orig/arch/sparc/mm/fault_32.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sparc/mm/fault_32.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sparc/mm/fault_32.c linux-3.18.14-rt/arch/sparc/mm/fault_32.c
+--- linux-3.18.14.orig/arch/sparc/mm/fault_32.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sparc/mm/fault_32.c 2015-05-31 15:32:46.529635385 -0500
@@ -196,7 +196,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -1588,9 +5216,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_32.c linux-3.18.12/arch/sparc/m
goto no_context;
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
-diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_64.c linux-3.18.12/arch/sparc/mm/fault_64.c
---- linux-3.18.12.orig/arch/sparc/mm/fault_64.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/sparc/mm/fault_64.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/sparc/mm/fault_64.c linux-3.18.14-rt/arch/sparc/mm/fault_64.c
+--- linux-3.18.14.orig/arch/sparc/mm/fault_64.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/sparc/mm/fault_64.c 2015-05-31 15:32:46.529635385 -0500
@@ -330,7 +330,7 @@
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -1600,9 +5228,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_64.c linux-3.18.12/arch/sparc/m
goto intr_or_no_mm;
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
-diff -Nur linux-3.18.12.orig/arch/tile/mm/fault.c linux-3.18.12/arch/tile/mm/fault.c
---- linux-3.18.12.orig/arch/tile/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/tile/mm/fault.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/tile/mm/fault.c linux-3.18.14-rt/arch/tile/mm/fault.c
+--- linux-3.18.14.orig/arch/tile/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/tile/mm/fault.c 2015-05-31 15:32:46.533635385 -0500
@@ -357,7 +357,7 @@
* If we're in an interrupt, have no user context or are running in an
* atomic region then we must not take the fault.
@@ -1612,9 +5240,9 @@ diff -Nur linux-3.18.12.orig/arch/tile/mm/fault.c linux-3.18.12/arch/tile/mm/fau
vma = NULL; /* happy compiler */
goto bad_area_nosemaphore;
}
-diff -Nur linux-3.18.12.orig/arch/um/kernel/trap.c linux-3.18.12/arch/um/kernel/trap.c
---- linux-3.18.12.orig/arch/um/kernel/trap.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/um/kernel/trap.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/um/kernel/trap.c linux-3.18.14-rt/arch/um/kernel/trap.c
+--- linux-3.18.14.orig/arch/um/kernel/trap.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/um/kernel/trap.c 2015-05-31 15:32:46.537635384 -0500
@@ -38,7 +38,7 @@
* If the fault was during atomic operation, don't take the fault, just
* fail.
@@ -1624,9 +5252,9 @@ diff -Nur linux-3.18.12.orig/arch/um/kernel/trap.c linux-3.18.12/arch/um/kernel/
goto out_nosemaphore;
if (is_user)
-diff -Nur linux-3.18.12.orig/arch/x86/crypto/aesni-intel_glue.c linux-3.18.12/arch/x86/crypto/aesni-intel_glue.c
---- linux-3.18.12.orig/arch/x86/crypto/aesni-intel_glue.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/crypto/aesni-intel_glue.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/crypto/aesni-intel_glue.c linux-3.18.14-rt/arch/x86/crypto/aesni-intel_glue.c
+--- linux-3.18.14.orig/arch/x86/crypto/aesni-intel_glue.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/crypto/aesni-intel_glue.c 2015-05-31 15:32:46.569635384 -0500
@@ -381,14 +381,14 @@
err = blkcipher_walk_virt(desc, &walk);
desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -1719,9 +5347,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/crypto/aesni-intel_glue.c linux-3.18.12/ar
return err;
}
-diff -Nur linux-3.18.12.orig/arch/x86/crypto/cast5_avx_glue.c linux-3.18.12/arch/x86/crypto/cast5_avx_glue.c
---- linux-3.18.12.orig/arch/x86/crypto/cast5_avx_glue.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/crypto/cast5_avx_glue.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/crypto/cast5_avx_glue.c linux-3.18.14-rt/arch/x86/crypto/cast5_avx_glue.c
+--- linux-3.18.14.orig/arch/x86/crypto/cast5_avx_glue.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/crypto/cast5_avx_glue.c 2015-05-31 15:32:46.585635384 -0500
@@ -60,7 +60,7 @@
static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
bool enc)
@@ -1801,9 +5429,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/crypto/cast5_avx_glue.c linux-3.18.12/arch
if (walk.nbytes) {
ctr_crypt_final(desc, &walk);
err = blkcipher_walk_done(desc, &walk, 0);
-diff -Nur linux-3.18.12.orig/arch/x86/crypto/glue_helper.c linux-3.18.12/arch/x86/crypto/glue_helper.c
---- linux-3.18.12.orig/arch/x86/crypto/glue_helper.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/crypto/glue_helper.c 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/crypto/glue_helper.c linux-3.18.14-rt/arch/x86/crypto/glue_helper.c
+--- linux-3.18.14.orig/arch/x86/crypto/glue_helper.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/crypto/glue_helper.c 2015-05-31 15:32:46.589635384 -0500
@@ -39,7 +39,7 @@
void *ctx = crypto_blkcipher_ctx(desc->tfm);
const unsigned int bsize = 128 / 8;
@@ -1919,9 +5547,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/crypto/glue_helper.c linux-3.18.12/arch/x8
return err;
}
EXPORT_SYMBOL_GPL(glue_xts_crypt_128bit);
-diff -Nur linux-3.18.12.orig/arch/x86/include/asm/preempt.h linux-3.18.12/arch/x86/include/asm/preempt.h
---- linux-3.18.12.orig/arch/x86/include/asm/preempt.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/include/asm/preempt.h 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/include/asm/preempt.h linux-3.18.14-rt/arch/x86/include/asm/preempt.h
+--- linux-3.18.14.orig/arch/x86/include/asm/preempt.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/include/asm/preempt.h 2015-05-31 15:32:46.597635384 -0500
@@ -85,17 +85,33 @@
* a decrement which hits zero means we have no preempt_count and should
* reschedule.
@@ -1957,9 +5585,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/preempt.h linux-3.18.12/arch/x
}
#ifdef CONFIG_PREEMPT
-diff -Nur linux-3.18.12.orig/arch/x86/include/asm/signal.h linux-3.18.12/arch/x86/include/asm/signal.h
---- linux-3.18.12.orig/arch/x86/include/asm/signal.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/include/asm/signal.h 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/include/asm/signal.h linux-3.18.14-rt/arch/x86/include/asm/signal.h
+--- linux-3.18.14.orig/arch/x86/include/asm/signal.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/include/asm/signal.h 2015-05-31 15:32:46.597635384 -0500
@@ -23,6 +23,19 @@
unsigned long sig[_NSIG_WORDS];
} sigset_t;
@@ -1980,9 +5608,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/signal.h linux-3.18.12/arch/x8
#ifndef CONFIG_COMPAT
typedef sigset_t compat_sigset_t;
#endif
-diff -Nur linux-3.18.12.orig/arch/x86/include/asm/stackprotector.h linux-3.18.12/arch/x86/include/asm/stackprotector.h
---- linux-3.18.12.orig/arch/x86/include/asm/stackprotector.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/include/asm/stackprotector.h 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/include/asm/stackprotector.h linux-3.18.14-rt/arch/x86/include/asm/stackprotector.h
+--- linux-3.18.14.orig/arch/x86/include/asm/stackprotector.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/include/asm/stackprotector.h 2015-05-31 15:32:46.613635384 -0500
@@ -57,7 +57,7 @@
*/
static __always_inline void boot_init_stack_canary(void)
@@ -2009,9 +5637,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/stackprotector.h linux-3.18.12
tsc = __native_read_tsc();
canary += tsc + (tsc << 32UL);
-diff -Nur linux-3.18.12.orig/arch/x86/include/asm/thread_info.h linux-3.18.12/arch/x86/include/asm/thread_info.h
---- linux-3.18.12.orig/arch/x86/include/asm/thread_info.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/include/asm/thread_info.h 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/include/asm/thread_info.h linux-3.18.14-rt/arch/x86/include/asm/thread_info.h
+--- linux-3.18.14.orig/arch/x86/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/include/asm/thread_info.h 2015-05-31 15:32:46.621635383 -0500
@@ -30,6 +30,8 @@
__u32 status; /* thread synchronous flags */
__u32 cpu; /* current CPU */
@@ -2046,9 +5674,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/thread_info.h linux-3.18.12/ar
#define STACK_WARN (THREAD_SIZE/8)
#define KERNEL_STACK_OFFSET (5*(BITS_PER_LONG/8))
-diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_bau.h linux-3.18.12/arch/x86/include/asm/uv/uv_bau.h
---- linux-3.18.12.orig/arch/x86/include/asm/uv/uv_bau.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/include/asm/uv/uv_bau.h 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/include/asm/uv/uv_bau.h linux-3.18.14-rt/arch/x86/include/asm/uv/uv_bau.h
+--- linux-3.18.14.orig/arch/x86/include/asm/uv/uv_bau.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/include/asm/uv/uv_bau.h 2015-05-31 15:32:46.621635383 -0500
@@ -615,9 +615,9 @@
cycles_t send_message;
cycles_t period_end;
@@ -2082,9 +5710,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_bau.h linux-3.18.12/arch
return 1;
}
-diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_hub.h linux-3.18.12/arch/x86/include/asm/uv/uv_hub.h
---- linux-3.18.12.orig/arch/x86/include/asm/uv/uv_hub.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/include/asm/uv/uv_hub.h 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/include/asm/uv/uv_hub.h linux-3.18.14-rt/arch/x86/include/asm/uv/uv_hub.h
+--- linux-3.18.14.orig/arch/x86/include/asm/uv/uv_hub.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/include/asm/uv/uv_hub.h 2015-05-31 15:32:46.621635383 -0500
@@ -492,7 +492,7 @@
unsigned short nr_online_cpus;
unsigned short pnode;
@@ -2094,9 +5722,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_hub.h linux-3.18.12/arch
unsigned long nmi_count; /* obsolete, see uv_hub_nmi */
};
extern struct uv_blade_info *uv_blade_info;
-diff -Nur linux-3.18.12.orig/arch/x86/Kconfig linux-3.18.12/arch/x86/Kconfig
---- linux-3.18.12.orig/arch/x86/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/Kconfig 2015-04-26 13:32:22.375684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/Kconfig linux-3.18.14-rt/arch/x86/Kconfig
+--- linux-3.18.14.orig/arch/x86/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/Kconfig 2015-05-31 15:32:46.561635384 -0500
@@ -21,6 +21,7 @@
### Arch settings
config X86
@@ -2127,9 +5755,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/Kconfig linux-3.18.12/arch/x86/Kconfig
---help---
Enable maximum number of CPUS and NUMA Nodes for this architecture.
If unsure, say N.
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/io_apic.c linux-3.18.12/arch/x86/kernel/apic/io_apic.c
---- linux-3.18.12.orig/arch/x86/kernel/apic/io_apic.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/apic/io_apic.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/apic/io_apic.c linux-3.18.14-rt/arch/x86/kernel/apic/io_apic.c
+--- linux-3.18.14.orig/arch/x86/kernel/apic/io_apic.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/apic/io_apic.c 2015-05-31 15:32:46.629635384 -0500
@@ -2494,7 +2494,8 @@
static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)
{
@@ -2140,9 +5768,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/io_apic.c linux-3.18.12/arch/x
mask_ioapic(cfg);
return true;
}
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/x2apic_uv_x.c linux-3.18.12/arch/x86/kernel/apic/x2apic_uv_x.c
---- linux-3.18.12.orig/arch/x86/kernel/apic/x2apic_uv_x.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/apic/x2apic_uv_x.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/apic/x2apic_uv_x.c linux-3.18.14-rt/arch/x86/kernel/apic/x2apic_uv_x.c
+--- linux-3.18.14.orig/arch/x86/kernel/apic/x2apic_uv_x.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/apic/x2apic_uv_x.c 2015-05-31 15:32:46.629635384 -0500
@@ -918,7 +918,7 @@
uv_blade_info[blade].pnode = pnode;
uv_blade_info[blade].nr_possible_cpus = 0;
@@ -2152,9 +5780,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/x2apic_uv_x.c linux-3.18.12/ar
min_pnode = min(pnode, min_pnode);
max_pnode = max(pnode, max_pnode);
blade++;
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/asm-offsets.c linux-3.18.12/arch/x86/kernel/asm-offsets.c
---- linux-3.18.12.orig/arch/x86/kernel/asm-offsets.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/asm-offsets.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/asm-offsets.c linux-3.18.14-rt/arch/x86/kernel/asm-offsets.c
+--- linux-3.18.14.orig/arch/x86/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/asm-offsets.c 2015-05-31 15:32:46.633635383 -0500
@@ -32,6 +32,7 @@
OFFSET(TI_flags, thread_info, flags);
OFFSET(TI_status, thread_info, status);
@@ -2169,9 +5797,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/asm-offsets.c linux-3.18.12/arch/x8
DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
+ DEFINE(_PREEMPT_ENABLED, PREEMPT_ENABLED);
}
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/cpu/mcheck/mce.c linux-3.18.12/arch/x86/kernel/cpu/mcheck/mce.c
---- linux-3.18.12.orig/arch/x86/kernel/cpu/mcheck/mce.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/cpu/mcheck/mce.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/cpu/mcheck/mce.c linux-3.18.14-rt/arch/x86/kernel/cpu/mcheck/mce.c
+--- linux-3.18.14.orig/arch/x86/kernel/cpu/mcheck/mce.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/cpu/mcheck/mce.c 2015-05-31 15:32:46.641635383 -0500
@@ -41,6 +41,8 @@
#include <linux/debugfs.h>
#include <linux/irq_work.h>
@@ -2424,9 +6052,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/cpu/mcheck/mce.c linux-3.18.12/arch
if (!zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL)) {
err = -ENOMEM;
goto err_out;
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_32.S linux-3.18.12/arch/x86/kernel/entry_32.S
---- linux-3.18.12.orig/arch/x86/kernel/entry_32.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/entry_32.S 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/entry_32.S linux-3.18.14-rt/arch/x86/kernel/entry_32.S
+--- linux-3.18.14.orig/arch/x86/kernel/entry_32.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/entry_32.S 2015-05-31 15:32:46.641635383 -0500
@@ -359,8 +359,24 @@
ENTRY(resume_kernel)
DISABLE_INTERRUPTS(CLBR_ANY)
@@ -2470,9 +6098,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_32.S linux-3.18.12/arch/x86/k
jnz work_resched
work_notifysig: # deal with pending signals and
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_64.S linux-3.18.12/arch/x86/kernel/entry_64.S
---- linux-3.18.12.orig/arch/x86/kernel/entry_64.S 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/entry_64.S 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/entry_64.S linux-3.18.14-rt/arch/x86/kernel/entry_64.S
+--- linux-3.18.14.orig/arch/x86/kernel/entry_64.S 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/entry_64.S 2015-05-31 15:32:46.649635383 -0500
@@ -454,8 +454,8 @@
/* Handle reschedules */
/* edx: work, edi: workmask */
@@ -2554,9 +6182,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_64.S linux-3.18.12/arch/x86/k
jnz paranoid_schedule
movl %ebx,%edx /* arg3: thread flags */
TRACE_IRQS_ON
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/irq_32.c linux-3.18.12/arch/x86/kernel/irq_32.c
---- linux-3.18.12.orig/arch/x86/kernel/irq_32.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/irq_32.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/irq_32.c linux-3.18.14-rt/arch/x86/kernel/irq_32.c
+--- linux-3.18.14.orig/arch/x86/kernel/irq_32.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/irq_32.c 2015-05-31 15:32:46.653635383 -0500
@@ -142,6 +142,7 @@
cpu, per_cpu(hardirq_stack, cpu), per_cpu(softirq_stack, cpu));
}
@@ -2573,9 +6201,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/irq_32.c linux-3.18.12/arch/x86/ker
bool handle_irq(unsigned irq, struct pt_regs *regs)
{
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/process_32.c linux-3.18.12/arch/x86/kernel/process_32.c
---- linux-3.18.12.orig/arch/x86/kernel/process_32.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/process_32.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/process_32.c linux-3.18.14-rt/arch/x86/kernel/process_32.c
+--- linux-3.18.14.orig/arch/x86/kernel/process_32.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/process_32.c 2015-05-31 15:32:46.653635383 -0500
@@ -35,6 +35,7 @@
#include <linux/uaccess.h>
#include <linux/io.h>
@@ -2629,9 +6257,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/process_32.c linux-3.18.12/arch/x86
/*
* Leave lazy mode, flushing any hypercalls made here.
* This must be done before restoring TLS segments so
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/signal.c linux-3.18.12/arch/x86/kernel/signal.c
---- linux-3.18.12.orig/arch/x86/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/signal.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/signal.c linux-3.18.14-rt/arch/x86/kernel/signal.c
+--- linux-3.18.14.orig/arch/x86/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/signal.c 2015-05-31 15:32:46.653635383 -0500
@@ -746,6 +746,14 @@
mce_notify_process();
#endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
@@ -2647,9 +6275,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/signal.c linux-3.18.12/arch/x86/ker
if (thread_info_flags & _TIF_UPROBE)
uprobe_notify_resume(regs);
-diff -Nur linux-3.18.12.orig/arch/x86/kernel/traps.c linux-3.18.12/arch/x86/kernel/traps.c
---- linux-3.18.12.orig/arch/x86/kernel/traps.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kernel/traps.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kernel/traps.c linux-3.18.14-rt/arch/x86/kernel/traps.c
+--- linux-3.18.14.orig/arch/x86/kernel/traps.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kernel/traps.c 2015-05-31 15:32:46.657635383 -0500
@@ -87,9 +87,21 @@
local_irq_enable();
}
@@ -2724,9 +6352,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/traps.c linux-3.18.12/arch/x86/kern
debug_stack_usage_dec();
exit:
-diff -Nur linux-3.18.12.orig/arch/x86/kvm/lapic.c linux-3.18.12/arch/x86/kvm/lapic.c
---- linux-3.18.12.orig/arch/x86/kvm/lapic.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kvm/lapic.c 2015-04-26 13:32:22.379684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kvm/lapic.c linux-3.18.14-rt/arch/x86/kvm/lapic.c
+--- linux-3.18.14.orig/arch/x86/kvm/lapic.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kvm/lapic.c 2015-05-31 15:32:46.693635383 -0500
@@ -1034,8 +1034,38 @@
apic->divide_count);
}
@@ -2829,9 +6457,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kvm/lapic.c linux-3.18.12/arch/x86/kvm/lap
}
/*
-diff -Nur linux-3.18.12.orig/arch/x86/kvm/x86.c linux-3.18.12/arch/x86/kvm/x86.c
---- linux-3.18.12.orig/arch/x86/kvm/x86.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/kvm/x86.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/kvm/x86.c linux-3.18.14-rt/arch/x86/kvm/x86.c
+--- linux-3.18.14.orig/arch/x86/kvm/x86.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/kvm/x86.c 2015-05-31 15:32:46.697635383 -0500
@@ -5772,6 +5772,13 @@
goto out;
}
@@ -2846,9 +6474,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kvm/x86.c linux-3.18.12/arch/x86/kvm/x86.c
r = kvm_mmu_module_init();
if (r)
goto out_free_percpu;
-diff -Nur linux-3.18.12.orig/arch/x86/mm/fault.c linux-3.18.12/arch/x86/mm/fault.c
---- linux-3.18.12.orig/arch/x86/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/mm/fault.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/mm/fault.c linux-3.18.14-rt/arch/x86/mm/fault.c
+--- linux-3.18.14.orig/arch/x86/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/mm/fault.c 2015-05-31 15:32:46.729635382 -0500
@@ -1128,7 +1128,7 @@
* If we're in an interrupt, have no user context or are running
* in an atomic region then we must not take the fault:
@@ -2858,9 +6486,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/mm/fault.c linux-3.18.12/arch/x86/mm/fault
bad_area_nosemaphore(regs, error_code, address);
return;
}
-diff -Nur linux-3.18.12.orig/arch/x86/mm/highmem_32.c linux-3.18.12/arch/x86/mm/highmem_32.c
---- linux-3.18.12.orig/arch/x86/mm/highmem_32.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/mm/highmem_32.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/mm/highmem_32.c linux-3.18.14-rt/arch/x86/mm/highmem_32.c
+--- linux-3.18.14.orig/arch/x86/mm/highmem_32.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/mm/highmem_32.c 2015-05-31 15:32:46.729635382 -0500
@@ -32,6 +32,7 @@
*/
void *kmap_atomic_prot(struct page *page, pgprot_t prot)
@@ -2891,9 +6519,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/mm/highmem_32.c linux-3.18.12/arch/x86/mm/
kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
arch_flush_lazy_mmu_mode();
-diff -Nur linux-3.18.12.orig/arch/x86/mm/iomap_32.c linux-3.18.12/arch/x86/mm/iomap_32.c
---- linux-3.18.12.orig/arch/x86/mm/iomap_32.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/mm/iomap_32.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/mm/iomap_32.c linux-3.18.14-rt/arch/x86/mm/iomap_32.c
+--- linux-3.18.14.orig/arch/x86/mm/iomap_32.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/mm/iomap_32.c 2015-05-31 15:32:46.733635383 -0500
@@ -56,6 +56,7 @@
void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
@@ -2926,9 +6554,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/mm/iomap_32.c linux-3.18.12/arch/x86/mm/io
kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
}
-diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/tlb_uv.c linux-3.18.12/arch/x86/platform/uv/tlb_uv.c
---- linux-3.18.12.orig/arch/x86/platform/uv/tlb_uv.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/platform/uv/tlb_uv.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/platform/uv/tlb_uv.c linux-3.18.14-rt/arch/x86/platform/uv/tlb_uv.c
+--- linux-3.18.14.orig/arch/x86/platform/uv/tlb_uv.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/platform/uv/tlb_uv.c 2015-05-31 15:32:46.733635383 -0500
@@ -714,9 +714,9 @@
quiesce_local_uvhub(hmaster);
@@ -3015,9 +6643,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/tlb_uv.c linux-3.18.12/arch/x8
}
}
-diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/uv_time.c linux-3.18.12/arch/x86/platform/uv/uv_time.c
---- linux-3.18.12.orig/arch/x86/platform/uv/uv_time.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/x86/platform/uv/uv_time.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/x86/platform/uv/uv_time.c linux-3.18.14-rt/arch/x86/platform/uv/uv_time.c
+--- linux-3.18.14.orig/arch/x86/platform/uv/uv_time.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/x86/platform/uv/uv_time.c 2015-05-31 15:32:46.737635383 -0500
@@ -58,7 +58,7 @@
/* There is one of these allocated per node */
@@ -3098,9 +6726,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/uv_time.c linux-3.18.12/arch/x
}
/*
-diff -Nur linux-3.18.12.orig/arch/xtensa/mm/fault.c linux-3.18.12/arch/xtensa/mm/fault.c
---- linux-3.18.12.orig/arch/xtensa/mm/fault.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/arch/xtensa/mm/fault.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/arch/xtensa/mm/fault.c linux-3.18.14-rt/arch/xtensa/mm/fault.c
+--- linux-3.18.14.orig/arch/xtensa/mm/fault.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/arch/xtensa/mm/fault.c 2015-05-31 15:32:46.741635382 -0500
@@ -57,7 +57,7 @@
/* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -3110,9 +6738,9 @@ diff -Nur linux-3.18.12.orig/arch/xtensa/mm/fault.c linux-3.18.12/arch/xtensa/mm
bad_page_fault(regs, address, SIGSEGV);
return;
}
-diff -Nur linux-3.18.12.orig/block/blk-core.c linux-3.18.12/block/blk-core.c
---- linux-3.18.12.orig/block/blk-core.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-core.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-core.c linux-3.18.14-rt/block/blk-core.c
+--- linux-3.18.14.orig/block/blk-core.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-core.c 2015-05-31 15:32:46.757635382 -0500
@@ -100,6 +100,9 @@
INIT_LIST_HEAD(&rq->queuelist);
@@ -3188,9 +6816,9 @@ diff -Nur linux-3.18.12.orig/block/blk-core.c linux-3.18.12/block/blk-core.c
}
void blk_finish_plug(struct blk_plug *plug)
-diff -Nur linux-3.18.12.orig/block/blk-ioc.c linux-3.18.12/block/blk-ioc.c
---- linux-3.18.12.orig/block/blk-ioc.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-ioc.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-ioc.c linux-3.18.14-rt/block/blk-ioc.c
+--- linux-3.18.14.orig/block/blk-ioc.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-ioc.c 2015-05-31 15:32:46.761635382 -0500
@@ -7,6 +7,7 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
@@ -3217,9 +6845,9 @@ diff -Nur linux-3.18.12.orig/block/blk-ioc.c linux-3.18.12/block/blk-ioc.c
goto retry;
}
}
-diff -Nur linux-3.18.12.orig/block/blk-iopoll.c linux-3.18.12/block/blk-iopoll.c
---- linux-3.18.12.orig/block/blk-iopoll.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-iopoll.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-iopoll.c linux-3.18.14-rt/block/blk-iopoll.c
+--- linux-3.18.14.orig/block/blk-iopoll.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-iopoll.c 2015-05-31 15:32:46.761635382 -0500
@@ -35,6 +35,7 @@
list_add_tail(&iop->list, this_cpu_ptr(&blk_cpu_iopoll));
__raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ);
@@ -3244,9 +6872,9 @@ diff -Nur linux-3.18.12.orig/block/blk-iopoll.c linux-3.18.12/block/blk-iopoll.c
}
return NOTIFY_OK;
-diff -Nur linux-3.18.12.orig/block/blk-mq.c linux-3.18.12/block/blk-mq.c
---- linux-3.18.12.orig/block/blk-mq.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-mq.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-mq.c linux-3.18.14-rt/block/blk-mq.c
+--- linux-3.18.14.orig/block/blk-mq.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-mq.c 2015-05-31 15:32:46.789635382 -0500
@@ -85,7 +85,7 @@
if (percpu_ref_tryget_live(&q->mq_usage_counter))
return 0;
@@ -3391,9 +7019,9 @@ diff -Nur linux-3.18.12.orig/block/blk-mq.c linux-3.18.12/block/blk-mq.c
return blk_mq_hctx_cpu_offline(hctx, cpu);
else if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
return blk_mq_hctx_cpu_online(hctx, cpu);
-diff -Nur linux-3.18.12.orig/block/blk-mq-cpu.c linux-3.18.12/block/blk-mq-cpu.c
---- linux-3.18.12.orig/block/blk-mq-cpu.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-mq-cpu.c 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-mq-cpu.c linux-3.18.14-rt/block/blk-mq-cpu.c
+--- linux-3.18.14.orig/block/blk-mq-cpu.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-mq-cpu.c 2015-05-31 15:32:46.773635382 -0500
@@ -16,7 +16,7 @@
#include "blk-mq.h"
@@ -3445,9 +7073,9 @@ diff -Nur linux-3.18.12.orig/block/blk-mq-cpu.c linux-3.18.12/block/blk-mq-cpu.c
}
void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier,
-diff -Nur linux-3.18.12.orig/block/blk-mq.h linux-3.18.12/block/blk-mq.h
---- linux-3.18.12.orig/block/blk-mq.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-mq.h 2015-04-26 13:32:22.383684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-mq.h linux-3.18.14-rt/block/blk-mq.h
+--- linux-3.18.14.orig/block/blk-mq.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-mq.h 2015-05-31 15:32:46.789635382 -0500
@@ -73,7 +73,10 @@
static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q,
unsigned int cpu)
@@ -3475,9 +7103,9 @@ diff -Nur linux-3.18.12.orig/block/blk-mq.h linux-3.18.12/block/blk-mq.h
}
struct blk_mq_alloc_data {
-diff -Nur linux-3.18.12.orig/block/blk-softirq.c linux-3.18.12/block/blk-softirq.c
---- linux-3.18.12.orig/block/blk-softirq.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/blk-softirq.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/block/blk-softirq.c linux-3.18.14-rt/block/blk-softirq.c
+--- linux-3.18.14.orig/block/blk-softirq.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/blk-softirq.c 2015-05-31 15:32:46.789635382 -0500
@@ -51,6 +51,7 @@
raise_softirq_irqoff(BLOCK_SOFTIRQ);
@@ -3502,9 +7130,9 @@ diff -Nur linux-3.18.12.orig/block/blk-softirq.c linux-3.18.12/block/blk-softirq
}
/**
-diff -Nur linux-3.18.12.orig/block/bounce.c linux-3.18.12/block/bounce.c
---- linux-3.18.12.orig/block/bounce.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/block/bounce.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/block/bounce.c linux-3.18.14-rt/block/bounce.c
+--- linux-3.18.14.orig/block/bounce.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/block/bounce.c 2015-05-31 15:32:46.793635382 -0500
@@ -54,11 +54,11 @@
unsigned long flags;
unsigned char *vto;
@@ -3519,9 +7147,9 @@ diff -Nur linux-3.18.12.orig/block/bounce.c linux-3.18.12/block/bounce.c
}
#else /* CONFIG_HIGHMEM */
-diff -Nur linux-3.18.12.orig/crypto/algapi.c linux-3.18.12/crypto/algapi.c
---- linux-3.18.12.orig/crypto/algapi.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/crypto/algapi.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/crypto/algapi.c linux-3.18.14-rt/crypto/algapi.c
+--- linux-3.18.14.orig/crypto/algapi.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/crypto/algapi.c 2015-05-31 15:32:46.809635382 -0500
@@ -698,13 +698,13 @@
int crypto_register_notifier(struct notifier_block *nb)
@@ -3538,9 +7166,9 @@ diff -Nur linux-3.18.12.orig/crypto/algapi.c linux-3.18.12/crypto/algapi.c
}
EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
-diff -Nur linux-3.18.12.orig/crypto/api.c linux-3.18.12/crypto/api.c
---- linux-3.18.12.orig/crypto/api.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/crypto/api.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/crypto/api.c linux-3.18.14-rt/crypto/api.c
+--- linux-3.18.14.orig/crypto/api.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/crypto/api.c 2015-05-31 15:32:46.861635382 -0500
@@ -31,7 +31,7 @@
DECLARE_RWSEM(crypto_alg_sem);
EXPORT_SYMBOL_GPL(crypto_alg_sem);
@@ -3563,9 +7191,9 @@ diff -Nur linux-3.18.12.orig/crypto/api.c linux-3.18.12/crypto/api.c
}
return ok;
-diff -Nur linux-3.18.12.orig/crypto/internal.h linux-3.18.12/crypto/internal.h
---- linux-3.18.12.orig/crypto/internal.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/crypto/internal.h 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/crypto/internal.h linux-3.18.14-rt/crypto/internal.h
+--- linux-3.18.14.orig/crypto/internal.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/crypto/internal.h 2015-05-31 15:32:46.865635381 -0500
@@ -48,7 +48,7 @@
extern struct list_head crypto_alg_list;
@@ -3584,9 +7212,9 @@ diff -Nur linux-3.18.12.orig/crypto/internal.h linux-3.18.12/crypto/internal.h
}
#endif /* _CRYPTO_INTERNAL_H */
-diff -Nur linux-3.18.12.orig/Documentation/hwlat_detector.txt linux-3.18.12/Documentation/hwlat_detector.txt
---- linux-3.18.12.orig/Documentation/hwlat_detector.txt 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/Documentation/hwlat_detector.txt 2015-04-26 13:32:22.347684003 -0500
+diff -Nur linux-3.18.14.orig/Documentation/hwlat_detector.txt linux-3.18.14-rt/Documentation/hwlat_detector.txt
+--- linux-3.18.14.orig/Documentation/hwlat_detector.txt 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/Documentation/hwlat_detector.txt 2015-05-31 15:32:45.457635394 -0500
@@ -0,0 +1,64 @@
+Introduction:
+-------------
@@ -3652,9 +7280,9 @@ diff -Nur linux-3.18.12.orig/Documentation/hwlat_detector.txt linux-3.18.12/Docu
+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 -Nur linux-3.18.12.orig/Documentation/sysrq.txt linux-3.18.12/Documentation/sysrq.txt
---- linux-3.18.12.orig/Documentation/sysrq.txt 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/Documentation/sysrq.txt 2015-04-26 13:32:22.347684003 -0500
+diff -Nur linux-3.18.14.orig/Documentation/sysrq.txt linux-3.18.14-rt/Documentation/sysrq.txt
+--- linux-3.18.14.orig/Documentation/sysrq.txt 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/Documentation/sysrq.txt 2015-05-31 15:32:45.461635394 -0500
@@ -59,10 +59,17 @@
On other - If you know of the key combos for other architectures, please
let me know so I can add them to this section.
@@ -3675,9 +7303,9 @@ diff -Nur linux-3.18.12.orig/Documentation/sysrq.txt linux-3.18.12/Documentation
* What are the 'command' keys?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'b' - Will immediately reboot the system without syncing or unmounting
-diff -Nur linux-3.18.12.orig/Documentation/trace/histograms.txt linux-3.18.12/Documentation/trace/histograms.txt
---- linux-3.18.12.orig/Documentation/trace/histograms.txt 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/Documentation/trace/histograms.txt 2015-04-26 13:32:22.351684003 -0500
+diff -Nur linux-3.18.14.orig/Documentation/trace/histograms.txt linux-3.18.14-rt/Documentation/trace/histograms.txt
+--- linux-3.18.14.orig/Documentation/trace/histograms.txt 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/Documentation/trace/histograms.txt 2015-05-31 15:32:45.461635394 -0500
@@ -0,0 +1,186 @@
+ Using the Linux Kernel Latency Histograms
+
@@ -3865,9 +7493,9 @@ diff -Nur linux-3.18.12.orig/Documentation/trace/histograms.txt linux-3.18.12/Do
+is provided.
+
+These data are also reset when the wakeup histogram is reset.
-diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/acglobal.h linux-3.18.12/drivers/acpi/acpica/acglobal.h
---- linux-3.18.12.orig/drivers/acpi/acpica/acglobal.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/acpi/acpica/acglobal.h 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/acglobal.h linux-3.18.14-rt/drivers/acpi/acpica/acglobal.h
+--- linux-3.18.14.orig/drivers/acpi/acpica/acglobal.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/acpi/acpica/acglobal.h 2015-05-31 15:32:46.885635381 -0500
@@ -112,7 +112,7 @@
* interrupt level
*/
@@ -3877,9 +7505,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/acglobal.h linux-3.18.12/driver
ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock);
/* Mutex for _OSI support */
-diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwregs.c linux-3.18.12/drivers/acpi/acpica/hwregs.c
---- linux-3.18.12.orig/drivers/acpi/acpica/hwregs.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/acpi/acpica/hwregs.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/hwregs.c linux-3.18.14-rt/drivers/acpi/acpica/hwregs.c
+--- linux-3.18.14.orig/drivers/acpi/acpica/hwregs.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/acpi/acpica/hwregs.c 2015-05-31 15:32:46.929635381 -0500
@@ -269,14 +269,14 @@
ACPI_BITMASK_ALL_FIXED_STATUS,
ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
@@ -3897,9 +7525,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwregs.c linux-3.18.12/drivers/
if (ACPI_FAILURE(status)) {
goto exit;
-diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwxface.c linux-3.18.12/drivers/acpi/acpica/hwxface.c
---- linux-3.18.12.orig/drivers/acpi/acpica/hwxface.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/acpi/acpica/hwxface.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/hwxface.c linux-3.18.14-rt/drivers/acpi/acpica/hwxface.c
+--- linux-3.18.14.orig/drivers/acpi/acpica/hwxface.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/acpi/acpica/hwxface.c 2015-05-31 15:32:46.973635380 -0500
@@ -374,7 +374,7 @@
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
@@ -3918,9 +7546,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwxface.c linux-3.18.12/drivers
return_ACPI_STATUS(status);
}
-diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/utmutex.c linux-3.18.12/drivers/acpi/acpica/utmutex.c
---- linux-3.18.12.orig/drivers/acpi/acpica/utmutex.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/acpi/acpica/utmutex.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/utmutex.c linux-3.18.14-rt/drivers/acpi/acpica/utmutex.c
+--- linux-3.18.14.orig/drivers/acpi/acpica/utmutex.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/acpi/acpica/utmutex.c 2015-05-31 15:32:46.973635380 -0500
@@ -88,7 +88,7 @@
return_ACPI_STATUS (status);
}
@@ -3939,9 +7567,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/utmutex.c linux-3.18.12/drivers
acpi_os_delete_lock(acpi_gbl_reference_count_lock);
/* Delete the reader/writer lock */
-diff -Nur linux-3.18.12.orig/drivers/ata/libata-sff.c linux-3.18.12/drivers/ata/libata-sff.c
---- linux-3.18.12.orig/drivers/ata/libata-sff.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ata/libata-sff.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ata/libata-sff.c linux-3.18.14-rt/drivers/ata/libata-sff.c
+--- linux-3.18.14.orig/drivers/ata/libata-sff.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ata/libata-sff.c 2015-05-31 15:32:46.993635380 -0500
@@ -678,9 +678,9 @@
unsigned long flags;
unsigned int consumed;
@@ -3990,9 +7618,9 @@ diff -Nur linux-3.18.12.orig/drivers/ata/libata-sff.c linux-3.18.12/drivers/ata/
} else {
buf = page_address(page);
consumed = ap->ops->sff_data_xfer(dev, buf + offset,
-diff -Nur linux-3.18.12.orig/drivers/char/random.c linux-3.18.12/drivers/char/random.c
---- linux-3.18.12.orig/drivers/char/random.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/char/random.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/char/random.c linux-3.18.14-rt/drivers/char/random.c
+--- linux-3.18.14.orig/drivers/char/random.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/char/random.c 2015-05-31 15:32:47.013635380 -0500
@@ -776,8 +776,6 @@
} sample;
long delta, delta2, delta3;
@@ -4044,9 +7672,9 @@ diff -Nur linux-3.18.12.orig/drivers/char/random.c linux-3.18.12/drivers/char/ra
fast_mix(fast_pool);
add_interrupt_bench(cycles);
-diff -Nur linux-3.18.12.orig/drivers/clocksource/tcb_clksrc.c linux-3.18.12/drivers/clocksource/tcb_clksrc.c
---- linux-3.18.12.orig/drivers/clocksource/tcb_clksrc.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/clocksource/tcb_clksrc.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/clocksource/tcb_clksrc.c linux-3.18.14-rt/drivers/clocksource/tcb_clksrc.c
+--- linux-3.18.14.orig/drivers/clocksource/tcb_clksrc.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/clocksource/tcb_clksrc.c 2015-05-31 15:32:47.025635380 -0500
@@ -23,8 +23,7 @@
* this 32 bit free-running counter. the second channel is not used.
*
@@ -4161,9 +7789,9 @@ diff -Nur linux-3.18.12.orig/drivers/clocksource/tcb_clksrc.c linux-3.18.12/driv
if (ret)
goto err_unregister_clksrc;
-diff -Nur linux-3.18.12.orig/drivers/clocksource/timer-atmel-pit.c linux-3.18.12/drivers/clocksource/timer-atmel-pit.c
---- linux-3.18.12.orig/drivers/clocksource/timer-atmel-pit.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/clocksource/timer-atmel-pit.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/clocksource/timer-atmel-pit.c linux-3.18.14-rt/drivers/clocksource/timer-atmel-pit.c
+--- linux-3.18.14.orig/drivers/clocksource/timer-atmel-pit.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/clocksource/timer-atmel-pit.c 2015-05-31 15:32:47.025635380 -0500
@@ -90,6 +90,7 @@
return elapsed;
}
@@ -4189,9 +7817,9 @@ diff -Nur linux-3.18.12.orig/drivers/clocksource/timer-atmel-pit.c linux-3.18.12
break;
case CLOCK_EVT_MODE_RESUME:
break;
-diff -Nur linux-3.18.12.orig/drivers/cpufreq/Kconfig.x86 linux-3.18.12/drivers/cpufreq/Kconfig.x86
---- linux-3.18.12.orig/drivers/cpufreq/Kconfig.x86 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/cpufreq/Kconfig.x86 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/cpufreq/Kconfig.x86 linux-3.18.14-rt/drivers/cpufreq/Kconfig.x86
+--- linux-3.18.14.orig/drivers/cpufreq/Kconfig.x86 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/cpufreq/Kconfig.x86 2015-05-31 15:32:47.065635380 -0500
@@ -113,7 +113,7 @@
config X86_POWERNOW_K8
@@ -4201,9 +7829,9 @@ diff -Nur linux-3.18.12.orig/drivers/cpufreq/Kconfig.x86 linux-3.18.12/drivers/c
help
This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
Support for K10 and newer processors is now in acpi-cpufreq.
-diff -Nur linux-3.18.12.orig/drivers/gpio/gpio-omap.c linux-3.18.12/drivers/gpio/gpio-omap.c
---- linux-3.18.12.orig/drivers/gpio/gpio-omap.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/gpio/gpio-omap.c 2015-04-26 13:32:22.387684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/gpio/gpio-omap.c linux-3.18.14-rt/drivers/gpio/gpio-omap.c
+--- linux-3.18.14.orig/drivers/gpio/gpio-omap.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/gpio/gpio-omap.c 2015-05-31 15:32:47.073635379 -0500
@@ -57,7 +57,7 @@
u32 saved_datain;
u32 level_mask;
@@ -4478,9 +8106,9 @@ diff -Nur linux-3.18.12.orig/drivers/gpio/gpio-omap.c linux-3.18.12/drivers/gpio
return 0;
}
-diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem.c linux-3.18.12/drivers/gpu/drm/i915/i915_gem.c
---- linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/gpu/drm/i915/i915_gem.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem.c linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem.c
+--- linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem.c 2015-05-31 15:32:47.081635379 -0500
@@ -5144,7 +5144,7 @@
if (!mutex_is_locked(mutex))
return false;
@@ -4490,9 +8118,9 @@ diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem.c linux-3.18.12/drive
return mutex->owner == task;
#else
/* Since UP may be pre-empted, we cannot assume that we own the lock */
-diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-3.18.12/drivers/gpu/drm/i915/i915_gem_execbuffer.c
---- linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+--- linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-05-31 15:32:47.121635379 -0500
@@ -1170,7 +1170,9 @@
return ret;
}
@@ -4503,9 +8131,9 @@ diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-3.
i915_gem_execbuffer_move_to_active(vmas, ring);
i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
-diff -Nur linux-3.18.12.orig/drivers/i2c/busses/i2c-omap.c linux-3.18.12/drivers/i2c/busses/i2c-omap.c
---- linux-3.18.12.orig/drivers/i2c/busses/i2c-omap.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/i2c/busses/i2c-omap.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/i2c/busses/i2c-omap.c linux-3.18.14-rt/drivers/i2c/busses/i2c-omap.c
+--- linux-3.18.14.orig/drivers/i2c/busses/i2c-omap.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/i2c/busses/i2c-omap.c 2015-05-31 15:32:47.125635379 -0500
@@ -875,15 +875,12 @@
u16 mask;
u16 stat;
@@ -4523,9 +8151,9 @@ diff -Nur linux-3.18.12.orig/drivers/i2c/busses/i2c-omap.c linux-3.18.12/drivers
return ret;
}
-diff -Nur linux-3.18.12.orig/drivers/ide/alim15x3.c linux-3.18.12/drivers/ide/alim15x3.c
---- linux-3.18.12.orig/drivers/ide/alim15x3.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/alim15x3.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/alim15x3.c linux-3.18.14-rt/drivers/ide/alim15x3.c
+--- linux-3.18.14.orig/drivers/ide/alim15x3.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/alim15x3.c 2015-05-31 15:32:47.137635379 -0500
@@ -234,7 +234,7 @@
isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
@@ -4544,9 +8172,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/alim15x3.c linux-3.18.12/drivers/ide/al
return 0;
}
-diff -Nur linux-3.18.12.orig/drivers/ide/hpt366.c linux-3.18.12/drivers/ide/hpt366.c
---- linux-3.18.12.orig/drivers/ide/hpt366.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/hpt366.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/hpt366.c linux-3.18.14-rt/drivers/ide/hpt366.c
+--- linux-3.18.14.orig/drivers/ide/hpt366.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/hpt366.c 2015-05-31 15:32:47.169635379 -0500
@@ -1241,7 +1241,7 @@
dma_old = inb(base + 2);
@@ -4565,9 +8193,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/hpt366.c linux-3.18.12/drivers/ide/hpt3
printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n",
hwif->name, base, base + 7);
-diff -Nur linux-3.18.12.orig/drivers/ide/ide-io.c linux-3.18.12/drivers/ide/ide-io.c
---- linux-3.18.12.orig/drivers/ide/ide-io.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/ide-io.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/ide-io.c linux-3.18.14-rt/drivers/ide/ide-io.c
+--- linux-3.18.14.orig/drivers/ide/ide-io.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/ide-io.c 2015-05-31 15:32:47.169635379 -0500
@@ -659,7 +659,7 @@
/* disable_irq_nosync ?? */
disable_irq(hwif->irq);
@@ -4577,9 +8205,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-io.c linux-3.18.12/drivers/ide/ide-
if (hwif->polling) {
startstop = handler(drive);
} else if (drive_is_ready(drive)) {
-diff -Nur linux-3.18.12.orig/drivers/ide/ide-iops.c linux-3.18.12/drivers/ide/ide-iops.c
---- linux-3.18.12.orig/drivers/ide/ide-iops.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/ide-iops.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/ide-iops.c linux-3.18.14-rt/drivers/ide/ide-iops.c
+--- linux-3.18.14.orig/drivers/ide/ide-iops.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/ide-iops.c 2015-05-31 15:32:47.185635379 -0500
@@ -129,12 +129,12 @@
if ((stat & ATA_BUSY) == 0)
break;
@@ -4595,9 +8223,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-iops.c linux-3.18.12/drivers/ide/id
}
/*
* Allow status to settle, then read it again.
-diff -Nur linux-3.18.12.orig/drivers/ide/ide-io-std.c linux-3.18.12/drivers/ide/ide-io-std.c
---- linux-3.18.12.orig/drivers/ide/ide-io-std.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/ide-io-std.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/ide-io-std.c linux-3.18.14-rt/drivers/ide/ide-io-std.c
+--- linux-3.18.14.orig/drivers/ide/ide-io-std.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/ide-io-std.c 2015-05-31 15:32:47.169635379 -0500
@@ -175,7 +175,7 @@
unsigned long uninitialized_var(flags);
@@ -4634,9 +8262,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-io-std.c linux-3.18.12/drivers/ide/
if (((len + 1) & 3) < 2)
return;
-diff -Nur linux-3.18.12.orig/drivers/ide/ide-probe.c linux-3.18.12/drivers/ide/ide-probe.c
---- linux-3.18.12.orig/drivers/ide/ide-probe.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/ide-probe.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/ide-probe.c linux-3.18.14-rt/drivers/ide/ide-probe.c
+--- linux-3.18.14.orig/drivers/ide/ide-probe.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/ide-probe.c 2015-05-31 15:32:47.185635379 -0500
@@ -196,10 +196,10 @@
int bswap = 1;
@@ -4650,9 +8278,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-probe.c linux-3.18.12/drivers/ide/i
drive->dev_flags |= IDE_DFLAG_ID_READ;
#ifdef DEBUG
-diff -Nur linux-3.18.12.orig/drivers/ide/ide-taskfile.c linux-3.18.12/drivers/ide/ide-taskfile.c
---- linux-3.18.12.orig/drivers/ide/ide-taskfile.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/ide/ide-taskfile.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/ide/ide-taskfile.c linux-3.18.14-rt/drivers/ide/ide-taskfile.c
+--- linux-3.18.14.orig/drivers/ide/ide-taskfile.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/ide/ide-taskfile.c 2015-05-31 15:32:47.185635379 -0500
@@ -250,7 +250,7 @@
page_is_high = PageHighMem(page);
@@ -4680,9 +8308,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-taskfile.c linux-3.18.12/drivers/id
ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
-diff -Nur linux-3.18.12.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-3.18.12/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
---- linux-3.18.12.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-3.18.14-rt/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+--- linux-3.18.14.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-05-31 15:32:47.205635378 -0500
@@ -796,7 +796,7 @@
ipoib_mcast_stop_thread(dev, 0);
@@ -4701,9 +8329,9 @@ diff -Nur linux-3.18.12.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linu
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
-diff -Nur linux-3.18.12.orig/drivers/input/gameport/gameport.c linux-3.18.12/drivers/input/gameport/gameport.c
---- linux-3.18.12.orig/drivers/input/gameport/gameport.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/input/gameport/gameport.c 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/input/gameport/gameport.c linux-3.18.14-rt/drivers/input/gameport/gameport.c
+--- linux-3.18.14.orig/drivers/input/gameport/gameport.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/input/gameport/gameport.c 2015-05-31 15:32:47.225635378 -0500
@@ -124,12 +124,12 @@
tx = 1 << 30;
@@ -4733,9 +8361,9 @@ diff -Nur linux-3.18.12.orig/drivers/input/gameport/gameport.c linux-3.18.12/dri
udelay(i * 10);
if (t2 - t1 < tx) tx = t2 - t1;
}
-diff -Nur linux-3.18.12.orig/drivers/leds/trigger/Kconfig linux-3.18.12/drivers/leds/trigger/Kconfig
---- linux-3.18.12.orig/drivers/leds/trigger/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/leds/trigger/Kconfig 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/leds/trigger/Kconfig linux-3.18.14-rt/drivers/leds/trigger/Kconfig
+--- linux-3.18.14.orig/drivers/leds/trigger/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/leds/trigger/Kconfig 2015-05-31 15:32:47.229635378 -0500
@@ -61,7 +61,7 @@
config LEDS_TRIGGER_CPU
@@ -4745,9 +8373,9 @@ diff -Nur linux-3.18.12.orig/drivers/leds/trigger/Kconfig linux-3.18.12/drivers/
help
This allows LEDs to be controlled by active CPUs. This shows
the active CPUs across an array of LEDs so you can see which
-diff -Nur linux-3.18.12.orig/drivers/md/bcache/Kconfig linux-3.18.12/drivers/md/bcache/Kconfig
---- linux-3.18.12.orig/drivers/md/bcache/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/md/bcache/Kconfig 2015-04-26 13:32:22.391684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/md/bcache/Kconfig linux-3.18.14-rt/drivers/md/bcache/Kconfig
+--- linux-3.18.14.orig/drivers/md/bcache/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/md/bcache/Kconfig 2015-05-31 15:32:47.245635378 -0500
@@ -1,6 +1,7 @@
config BCACHE
@@ -4756,9 +8384,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/bcache/Kconfig linux-3.18.12/drivers/md/
---help---
Allows a block device to be used as cache for other devices; uses
a btree for indexing and the layout is optimized for SSDs.
-diff -Nur linux-3.18.12.orig/drivers/md/dm.c linux-3.18.12/drivers/md/dm.c
---- linux-3.18.12.orig/drivers/md/dm.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/md/dm.c 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/md/dm.c linux-3.18.14-rt/drivers/md/dm.c
+--- linux-3.18.14.orig/drivers/md/dm.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/md/dm.c 2015-05-31 15:32:47.261635378 -0500
@@ -1898,14 +1898,14 @@
if (map_request(ti, clone, md))
goto requeued;
@@ -4776,9 +8404,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/dm.c linux-3.18.12/drivers/md/dm.c
spin_lock(q->queue_lock);
delay_and_out:
-diff -Nur linux-3.18.12.orig/drivers/md/raid5.c linux-3.18.12/drivers/md/raid5.c
---- linux-3.18.12.orig/drivers/md/raid5.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/md/raid5.c 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/md/raid5.c linux-3.18.14-rt/drivers/md/raid5.c
+--- linux-3.18.14.orig/drivers/md/raid5.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/md/raid5.c 2015-05-31 15:32:47.265635378 -0500
@@ -1649,8 +1649,9 @@
struct raid5_percpu *percpu;
unsigned long cpu;
@@ -4808,9 +8436,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/raid5.c linux-3.18.12/drivers/md/raid5.c
}
put_online_cpus();
-diff -Nur linux-3.18.12.orig/drivers/md/raid5.h linux-3.18.12/drivers/md/raid5.h
---- linux-3.18.12.orig/drivers/md/raid5.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/md/raid5.h 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/md/raid5.h linux-3.18.14-rt/drivers/md/raid5.h
+--- linux-3.18.14.orig/drivers/md/raid5.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/md/raid5.h 2015-05-31 15:32:47.293635378 -0500
@@ -457,6 +457,7 @@
int recovery_disabled;
/* per cpu variables */
@@ -4819,9 +8447,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/raid5.h linux-3.18.12/drivers/md/raid5.h
struct page *spare_page; /* Used when checking P/Q in raid6 */
void *scribble; /* space for constructing buffer
* lists and performing address
-diff -Nur linux-3.18.12.orig/drivers/misc/hwlat_detector.c linux-3.18.12/drivers/misc/hwlat_detector.c
---- linux-3.18.12.orig/drivers/misc/hwlat_detector.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/drivers/misc/hwlat_detector.c 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/misc/hwlat_detector.c linux-3.18.14-rt/drivers/misc/hwlat_detector.c
+--- linux-3.18.14.orig/drivers/misc/hwlat_detector.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/drivers/misc/hwlat_detector.c 2015-05-31 15:32:47.377635377 -0500
@@ -0,0 +1,1240 @@
+/*
+ * hwlat_detector.c - A simple Hardware Latency detector.
@@ -6063,9 +9691,9 @@ diff -Nur linux-3.18.12.orig/drivers/misc/hwlat_detector.c linux-3.18.12/drivers
+
+module_init(detector_init);
+module_exit(detector_exit);
-diff -Nur linux-3.18.12.orig/drivers/misc/Kconfig linux-3.18.12/drivers/misc/Kconfig
---- linux-3.18.12.orig/drivers/misc/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/misc/Kconfig 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/misc/Kconfig linux-3.18.14-rt/drivers/misc/Kconfig
+--- linux-3.18.14.orig/drivers/misc/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/misc/Kconfig 2015-05-31 15:32:47.297635378 -0500
@@ -54,6 +54,7 @@
config ATMEL_TCLIB
bool "Atmel AT32/AT91 Timer/Counter Library"
@@ -6136,9 +9764,9 @@ diff -Nur linux-3.18.12.orig/drivers/misc/Kconfig linux-3.18.12/drivers/misc/Kco
config PHANTOM
tristate "Sensable PHANToM (PCI)"
depends on PCI
-diff -Nur linux-3.18.12.orig/drivers/misc/Makefile linux-3.18.12/drivers/misc/Makefile
---- linux-3.18.12.orig/drivers/misc/Makefile 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/misc/Makefile 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/misc/Makefile linux-3.18.14-rt/drivers/misc/Makefile
+--- linux-3.18.14.orig/drivers/misc/Makefile 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/misc/Makefile 2015-05-31 15:32:47.349635377 -0500
@@ -38,6 +38,7 @@
obj-$(CONFIG_HMC6352) += hmc6352.o
obj-y += eeprom/
@@ -6147,9 +9775,9 @@ diff -Nur linux-3.18.12.orig/drivers/misc/Makefile linux-3.18.12/drivers/misc/Ma
obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
-diff -Nur linux-3.18.12.orig/drivers/mmc/host/mmci.c linux-3.18.12/drivers/mmc/host/mmci.c
---- linux-3.18.12.orig/drivers/mmc/host/mmci.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/mmc/host/mmci.c 2015-04-26 13:32:22.395684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/mmc/host/mmci.c linux-3.18.14-rt/drivers/mmc/host/mmci.c
+--- linux-3.18.14.orig/drivers/mmc/host/mmci.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/mmc/host/mmci.c 2015-05-31 15:32:47.393635377 -0500
@@ -1153,15 +1153,12 @@
struct sg_mapping_iter *sg_miter = &host->sg_miter;
struct variant_data *variant = host->variant;
@@ -6175,9 +9803,9 @@ diff -Nur linux-3.18.12.orig/drivers/mmc/host/mmci.c linux-3.18.12/drivers/mmc/h
/*
* If we have less than the fifo 'half-full' threshold to transfer,
* trigger a PIO interrupt as soon as any data is available.
-diff -Nur linux-3.18.12.orig/drivers/mmc/host/sdhci.c linux-3.18.12/drivers/mmc/host/sdhci.c
---- linux-3.18.12.orig/drivers/mmc/host/sdhci.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/mmc/host/sdhci.c 2015-04-26 13:32:22.399684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/mmc/host/sdhci.c linux-3.18.14-rt/drivers/mmc/host/sdhci.c
+--- linux-3.18.14.orig/drivers/mmc/host/sdhci.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/mmc/host/sdhci.c 2015-05-31 15:32:47.397635376 -0500
@@ -2565,6 +2565,31 @@
return isr ? IRQ_HANDLED : IRQ_NONE;
}
@@ -6231,9 +9859,9 @@ diff -Nur linux-3.18.12.orig/drivers/mmc/host/sdhci.c linux-3.18.12/drivers/mmc/
if (ret) {
pr_err("%s: Failed to request IRQ %d: %d\n",
mmc_hostname(mmc), host->irq, ret);
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/3com/3c59x.c linux-3.18.12/drivers/net/ethernet/3com/3c59x.c
---- linux-3.18.12.orig/drivers/net/ethernet/3com/3c59x.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/3com/3c59x.c 2015-04-26 13:32:22.399684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/3com/3c59x.c linux-3.18.14-rt/drivers/net/ethernet/3com/3c59x.c
+--- linux-3.18.14.orig/drivers/net/ethernet/3com/3c59x.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/3com/3c59x.c 2015-05-31 15:32:47.425635376 -0500
@@ -842,9 +842,9 @@
{
struct vortex_private *vp = netdev_priv(dev);
@@ -6261,9 +9889,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/3com/3c59x.c linux-3.18.12/dri
}
}
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-3.18.12/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
---- linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-04-26 13:32:22.399684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+--- linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-05-31 15:32:47.437635376 -0500
@@ -2213,11 +2213,7 @@
}
@@ -6277,9 +9905,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c lin
if (atl1c_tpd_avail(adapter, type) < tpd_req) {
/* no enough descriptor, just stop queue */
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-3.18.12/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
---- linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-04-26 13:32:22.399684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+--- linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-05-31 15:32:47.445635376 -0500
@@ -1880,8 +1880,7 @@
return NETDEV_TX_OK;
}
@@ -6290,9 +9918,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c lin
if (atl1e_tpd_avail(adapter) < tpd_req) {
/* no enough descriptor, just stop queue */
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/chelsio/cxgb/sge.c linux-3.18.12/drivers/net/ethernet/chelsio/cxgb/sge.c
---- linux-3.18.12.orig/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-04-26 13:32:22.399684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/chelsio/cxgb/sge.c linux-3.18.14-rt/drivers/net/ethernet/chelsio/cxgb/sge.c
+--- linux-3.18.14.orig/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-05-31 15:32:47.493635375 -0500
@@ -1663,8 +1663,7 @@
struct cmdQ *q = &sge->cmdQ[qid];
unsigned int credits, pidx, genbit, count, use_sched_skb = 0;
@@ -6303,9 +9931,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/chelsio/cxgb/sge.c linux-3.18.
reclaim_completed_tx(sge, q);
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.18.12/drivers/net/ethernet/freescale/gianfar.c
---- linux-3.18.12.orig/drivers/net/ethernet/freescale/gianfar.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/freescale/gianfar.c 2015-04-26 13:32:22.399684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.18.14-rt/drivers/net/ethernet/freescale/gianfar.c
+--- linux-3.18.14.orig/drivers/net/ethernet/freescale/gianfar.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/freescale/gianfar.c 2015-05-31 15:32:47.525635375 -0500
@@ -1483,7 +1483,7 @@
if (netif_running(ndev)) {
@@ -6359,9 +9987,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.18
}
netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/neterion/s2io.c linux-3.18.12/drivers/net/ethernet/neterion/s2io.c
---- linux-3.18.12.orig/drivers/net/ethernet/neterion/s2io.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/neterion/s2io.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/neterion/s2io.c linux-3.18.14-rt/drivers/net/ethernet/neterion/s2io.c
+--- linux-3.18.14.orig/drivers/net/ethernet/neterion/s2io.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/neterion/s2io.c 2015-05-31 15:32:47.537635375 -0500
@@ -4084,12 +4084,7 @@
[skb->priority & (MAX_TX_FIFOS - 1)];
fifo = &mac_control->fifos[queue];
@@ -6376,9 +10004,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/neterion/s2io.c linux-3.18.12/
if (sp->config.multiq) {
if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c linux-3.18.12/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
---- linux-3.18.12.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c linux-3.18.14-rt/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+--- linux-3.18.14.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-05-31 15:32:47.549635375 -0500
@@ -2137,10 +2137,8 @@
struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
unsigned long flags;
@@ -6392,9 +10020,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.
if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) {
netif_stop_queue(netdev);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/realtek/8139too.c linux-3.18.12/drivers/net/ethernet/realtek/8139too.c
---- linux-3.18.12.orig/drivers/net/ethernet/realtek/8139too.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/realtek/8139too.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/realtek/8139too.c linux-3.18.14-rt/drivers/net/ethernet/realtek/8139too.c
+--- linux-3.18.14.orig/drivers/net/ethernet/realtek/8139too.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/realtek/8139too.c 2015-05-31 15:32:47.557635375 -0500
@@ -2215,7 +2215,7 @@
struct rtl8139_private *tp = netdev_priv(dev);
const int irq = tp->pci_dev->irq;
@@ -6404,9 +10032,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/realtek/8139too.c linux-3.18.1
rtl8139_interrupt(irq, dev);
enable_irq(irq);
}
-diff -Nur linux-3.18.12.orig/drivers/net/ethernet/tehuti/tehuti.c linux-3.18.12/drivers/net/ethernet/tehuti/tehuti.c
---- linux-3.18.12.orig/drivers/net/ethernet/tehuti/tehuti.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/ethernet/tehuti/tehuti.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/ethernet/tehuti/tehuti.c linux-3.18.14-rt/drivers/net/ethernet/tehuti/tehuti.c
+--- linux-3.18.14.orig/drivers/net/ethernet/tehuti/tehuti.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/ethernet/tehuti/tehuti.c 2015-05-31 15:32:47.581635375 -0500
@@ -1629,13 +1629,8 @@
unsigned long flags;
@@ -6423,9 +10051,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/tehuti/tehuti.c linux-3.18.12/
/* build tx descriptor */
BDX_ASSERT(f->m.wptr >= f->m.memsz); /* started with valid wptr */
-diff -Nur linux-3.18.12.orig/drivers/net/rionet.c linux-3.18.12/drivers/net/rionet.c
---- linux-3.18.12.orig/drivers/net/rionet.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/rionet.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/rionet.c linux-3.18.14-rt/drivers/net/rionet.c
+--- linux-3.18.14.orig/drivers/net/rionet.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/rionet.c 2015-05-31 15:32:47.597635374 -0500
@@ -174,11 +174,7 @@
unsigned long flags;
int add_num = 1;
@@ -6439,9 +10067,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/rionet.c linux-3.18.12/drivers/net/rion
if (is_multicast_ether_addr(eth->h_dest))
add_num = nets[rnet->mport->id].nact;
-diff -Nur linux-3.18.12.orig/drivers/net/wireless/orinoco/orinoco_usb.c linux-3.18.12/drivers/net/wireless/orinoco/orinoco_usb.c
---- linux-3.18.12.orig/drivers/net/wireless/orinoco/orinoco_usb.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/net/wireless/orinoco/orinoco_usb.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/net/wireless/orinoco/orinoco_usb.c linux-3.18.14-rt/drivers/net/wireless/orinoco/orinoco_usb.c
+--- linux-3.18.14.orig/drivers/net/wireless/orinoco/orinoco_usb.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/net/wireless/orinoco/orinoco_usb.c 2015-05-31 15:32:47.613635374 -0500
@@ -699,7 +699,7 @@
while (!ctx->done.done && msecs--)
udelay(1000);
@@ -6451,9 +10079,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/wireless/orinoco/orinoco_usb.c linux-3.
ctx->done.done);
}
break;
-diff -Nur linux-3.18.12.orig/drivers/pci/access.c linux-3.18.12/drivers/pci/access.c
---- linux-3.18.12.orig/drivers/pci/access.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/pci/access.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/pci/access.c linux-3.18.14-rt/drivers/pci/access.c
+--- linux-3.18.14.orig/drivers/pci/access.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/pci/access.c 2015-05-31 15:32:47.665635374 -0500
@@ -434,7 +434,7 @@
WARN_ON(!dev->block_cfg_access);
@@ -6463,9 +10091,9 @@ diff -Nur linux-3.18.12.orig/drivers/pci/access.c linux-3.18.12/drivers/pci/acce
raw_spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
-diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe.c linux-3.18.12/drivers/scsi/fcoe/fcoe.c
---- linux-3.18.12.orig/drivers/scsi/fcoe/fcoe.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/scsi/fcoe/fcoe.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/scsi/fcoe/fcoe.c linux-3.18.14-rt/drivers/scsi/fcoe/fcoe.c
+--- linux-3.18.14.orig/drivers/scsi/fcoe/fcoe.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/scsi/fcoe/fcoe.c 2015-05-31 15:32:47.677635374 -0500
@@ -1286,7 +1286,7 @@
struct sk_buff *skb;
#ifdef CONFIG_SMP
@@ -6529,9 +10157,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe.c linux-3.18.12/drivers/scsi
kfree_skb(skb);
}
-diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe_ctlr.c linux-3.18.12/drivers/scsi/fcoe/fcoe_ctlr.c
---- linux-3.18.12.orig/drivers/scsi/fcoe/fcoe_ctlr.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/scsi/fcoe/fcoe_ctlr.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/scsi/fcoe/fcoe_ctlr.c linux-3.18.14-rt/drivers/scsi/fcoe/fcoe_ctlr.c
+--- linux-3.18.14.orig/drivers/scsi/fcoe/fcoe_ctlr.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/scsi/fcoe/fcoe_ctlr.c 2015-05-31 15:32:47.681635374 -0500
@@ -831,7 +831,7 @@
INIT_LIST_HEAD(&del_list);
@@ -6550,9 +10178,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe_ctlr.c linux-3.18.12/drivers
list_for_each_entry_safe(fcf, next, &del_list, list) {
/* Removes fcf from current list */
-diff -Nur linux-3.18.12.orig/drivers/scsi/libfc/fc_exch.c linux-3.18.12/drivers/scsi/libfc/fc_exch.c
---- linux-3.18.12.orig/drivers/scsi/libfc/fc_exch.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/scsi/libfc/fc_exch.c 2015-04-26 13:32:22.403684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/scsi/libfc/fc_exch.c linux-3.18.14-rt/drivers/scsi/libfc/fc_exch.c
+--- linux-3.18.14.orig/drivers/scsi/libfc/fc_exch.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/scsi/libfc/fc_exch.c 2015-05-31 15:32:47.689635374 -0500
@@ -816,10 +816,10 @@
}
memset(ep, 0, sizeof(*ep));
@@ -6566,9 +10194,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/libfc/fc_exch.c linux-3.18.12/drivers/
/* peek cache of free slot */
if (pool->left != FC_XID_UNKNOWN) {
-diff -Nur linux-3.18.12.orig/drivers/scsi/libsas/sas_ata.c linux-3.18.12/drivers/scsi/libsas/sas_ata.c
---- linux-3.18.12.orig/drivers/scsi/libsas/sas_ata.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/scsi/libsas/sas_ata.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/scsi/libsas/sas_ata.c linux-3.18.14-rt/drivers/scsi/libsas/sas_ata.c
+--- linux-3.18.14.orig/drivers/scsi/libsas/sas_ata.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/scsi/libsas/sas_ata.c 2015-05-31 15:32:47.689635374 -0500
@@ -191,7 +191,7 @@
/* TODO: audit callers to ensure they are ready for qc_issue to
* unconditionally re-enable interrupts
@@ -6587,9 +10215,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/libsas/sas_ata.c linux-3.18.12/drivers
return ret;
}
-diff -Nur linux-3.18.12.orig/drivers/scsi/qla2xxx/qla_inline.h linux-3.18.12/drivers/scsi/qla2xxx/qla_inline.h
---- linux-3.18.12.orig/drivers/scsi/qla2xxx/qla_inline.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/scsi/qla2xxx/qla_inline.h 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/scsi/qla2xxx/qla_inline.h linux-3.18.14-rt/drivers/scsi/qla2xxx/qla_inline.h
+--- linux-3.18.14.orig/drivers/scsi/qla2xxx/qla_inline.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/scsi/qla2xxx/qla_inline.h 2015-05-31 15:32:47.693635374 -0500
@@ -59,12 +59,12 @@
{
unsigned long flags;
@@ -6605,9 +10233,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/qla2xxx/qla_inline.h linux-3.18.12/dri
}
static inline uint8_t *
-diff -Nur linux-3.18.12.orig/drivers/thermal/x86_pkg_temp_thermal.c linux-3.18.12/drivers/thermal/x86_pkg_temp_thermal.c
---- linux-3.18.12.orig/drivers/thermal/x86_pkg_temp_thermal.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/thermal/x86_pkg_temp_thermal.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/thermal/x86_pkg_temp_thermal.c linux-3.18.14-rt/drivers/thermal/x86_pkg_temp_thermal.c
+--- linux-3.18.14.orig/drivers/thermal/x86_pkg_temp_thermal.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/thermal/x86_pkg_temp_thermal.c 2015-05-31 15:32:47.701635374 -0500
@@ -29,6 +29,7 @@
#include <linux/pm.h>
#include <linux/thermal.h>
@@ -6710,9 +10338,9 @@ diff -Nur linux-3.18.12.orig/drivers/thermal/x86_pkg_temp_thermal.c linux-3.18.1
for_each_online_cpu(i)
cancel_delayed_work_sync(
&per_cpu(pkg_temp_thermal_threshold_work, i));
-diff -Nur linux-3.18.12.orig/drivers/tty/serial/8250/8250_core.c linux-3.18.12/drivers/tty/serial/8250/8250_core.c
---- linux-3.18.12.orig/drivers/tty/serial/8250/8250_core.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/tty/serial/8250/8250_core.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/tty/serial/8250/8250_core.c linux-3.18.14-rt/drivers/tty/serial/8250/8250_core.c
+--- linux-3.18.14.orig/drivers/tty/serial/8250/8250_core.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/tty/serial/8250/8250_core.c 2015-05-31 15:32:47.753635373 -0500
@@ -37,6 +37,7 @@
#include <linux/nmi.h>
#include <linux/mutex.h>
@@ -6748,9 +10376,9 @@ diff -Nur linux-3.18.12.orig/drivers/tty/serial/8250/8250_core.c linux-3.18.12/d
locked = spin_trylock_irqsave(&port->lock, flags);
else
spin_lock_irqsave(&port->lock, flags);
-diff -Nur linux-3.18.12.orig/drivers/tty/serial/amba-pl011.c linux-3.18.12/drivers/tty/serial/amba-pl011.c
---- linux-3.18.12.orig/drivers/tty/serial/amba-pl011.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/tty/serial/amba-pl011.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/tty/serial/amba-pl011.c linux-3.18.14-rt/drivers/tty/serial/amba-pl011.c
+--- linux-3.18.14.orig/drivers/tty/serial/amba-pl011.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/tty/serial/amba-pl011.c 2015-05-31 15:32:47.777635373 -0500
@@ -1935,13 +1935,19 @@
clk_enable(uap->clk);
@@ -6784,9 +10412,9 @@ diff -Nur linux-3.18.12.orig/drivers/tty/serial/amba-pl011.c linux-3.18.12/drive
clk_disable(uap->clk);
}
-diff -Nur linux-3.18.12.orig/drivers/tty/serial/omap-serial.c linux-3.18.12/drivers/tty/serial/omap-serial.c
---- linux-3.18.12.orig/drivers/tty/serial/omap-serial.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/tty/serial/omap-serial.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/tty/serial/omap-serial.c linux-3.18.14-rt/drivers/tty/serial/omap-serial.c
+--- linux-3.18.14.orig/drivers/tty/serial/omap-serial.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/tty/serial/omap-serial.c 2015-05-31 15:32:47.781635373 -0500
@@ -1270,13 +1270,10 @@
pm_runtime_get_sync(up->dev);
@@ -6814,9 +10442,9 @@ diff -Nur linux-3.18.12.orig/drivers/tty/serial/omap-serial.c linux-3.18.12/driv
}
static int __init
-diff -Nur linux-3.18.12.orig/drivers/usb/core/hcd.c linux-3.18.12/drivers/usb/core/hcd.c
---- linux-3.18.12.orig/drivers/usb/core/hcd.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/usb/core/hcd.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/usb/core/hcd.c linux-3.18.14-rt/drivers/usb/core/hcd.c
+--- linux-3.18.14.orig/drivers/usb/core/hcd.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/usb/core/hcd.c 2015-05-31 15:32:47.785635373 -0500
@@ -1681,9 +1681,9 @@
* and no one may trigger the above deadlock situation when
* running complete() in tasklet.
@@ -6829,9 +10457,9 @@ diff -Nur linux-3.18.12.orig/drivers/usb/core/hcd.c linux-3.18.12/drivers/usb/co
usb_anchor_resume_wakeups(anchor);
atomic_dec(&urb->use_count);
-diff -Nur linux-3.18.12.orig/drivers/usb/gadget/function/f_fs.c linux-3.18.12/drivers/usb/gadget/function/f_fs.c
---- linux-3.18.12.orig/drivers/usb/gadget/function/f_fs.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/usb/gadget/function/f_fs.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/usb/gadget/function/f_fs.c linux-3.18.14-rt/drivers/usb/gadget/function/f_fs.c
+--- linux-3.18.14.orig/drivers/usb/gadget/function/f_fs.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/usb/gadget/function/f_fs.c 2015-05-31 15:32:47.809635373 -0500
@@ -1428,7 +1428,7 @@
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
@@ -6841,9 +10469,9 @@ diff -Nur linux-3.18.12.orig/drivers/usb/gadget/function/f_fs.c linux-3.18.12/dr
kfree(ffs->dev_name);
kfree(ffs);
}
-diff -Nur linux-3.18.12.orig/drivers/usb/gadget/legacy/inode.c linux-3.18.12/drivers/usb/gadget/legacy/inode.c
---- linux-3.18.12.orig/drivers/usb/gadget/legacy/inode.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/drivers/usb/gadget/legacy/inode.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/drivers/usb/gadget/legacy/inode.c linux-3.18.14-rt/drivers/usb/gadget/legacy/inode.c
+--- linux-3.18.14.orig/drivers/usb/gadget/legacy/inode.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/drivers/usb/gadget/legacy/inode.c 2015-05-31 15:32:47.837635372 -0500
@@ -339,7 +339,7 @@
spin_unlock_irq (&epdata->dev->lock);
@@ -6862,9 +10490,9 @@ diff -Nur linux-3.18.12.orig/drivers/usb/gadget/legacy/inode.c linux-3.18.12/dri
if (epdata->status == -ECONNRESET)
epdata->status = -EINTR;
} else {
-diff -Nur linux-3.18.12.orig/fs/aio.c linux-3.18.12/fs/aio.c
---- linux-3.18.12.orig/fs/aio.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/aio.c 2015-04-26 13:32:22.407684003 -0500
+diff -Nur linux-3.18.14.orig/fs/aio.c linux-3.18.14-rt/fs/aio.c
+--- linux-3.18.14.orig/fs/aio.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/aio.c 2015-05-31 15:32:47.853635372 -0500
@@ -40,6 +40,7 @@
#include <linux/ramfs.h>
#include <linux/percpu-refcount.h>
@@ -6940,9 +10568,9 @@ diff -Nur linux-3.18.12.orig/fs/aio.c linux-3.18.12/fs/aio.c
static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
{
unsigned i, new_nr;
-diff -Nur linux-3.18.12.orig/fs/autofs4/autofs_i.h linux-3.18.12/fs/autofs4/autofs_i.h
---- linux-3.18.12.orig/fs/autofs4/autofs_i.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/autofs4/autofs_i.h 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/autofs4/autofs_i.h linux-3.18.14-rt/fs/autofs4/autofs_i.h
+--- linux-3.18.14.orig/fs/autofs4/autofs_i.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/autofs4/autofs_i.h 2015-05-31 15:32:47.865635372 -0500
@@ -34,6 +34,7 @@
#include <linux/sched.h>
#include <linux/mount.h>
@@ -6951,9 +10579,9 @@ diff -Nur linux-3.18.12.orig/fs/autofs4/autofs_i.h linux-3.18.12/fs/autofs4/auto
#include <asm/current.h>
#include <asm/uaccess.h>
-diff -Nur linux-3.18.12.orig/fs/autofs4/expire.c linux-3.18.12/fs/autofs4/expire.c
---- linux-3.18.12.orig/fs/autofs4/expire.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/autofs4/expire.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/autofs4/expire.c linux-3.18.14-rt/fs/autofs4/expire.c
+--- linux-3.18.14.orig/fs/autofs4/expire.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/autofs4/expire.c 2015-05-31 15:32:47.897635372 -0500
@@ -151,7 +151,7 @@
parent = p->d_parent;
if (!spin_trylock(&parent->d_lock)) {
@@ -6963,9 +10591,9 @@ diff -Nur linux-3.18.12.orig/fs/autofs4/expire.c linux-3.18.12/fs/autofs4/expire
goto relock;
}
spin_unlock(&p->d_lock);
-diff -Nur linux-3.18.12.orig/fs/buffer.c linux-3.18.12/fs/buffer.c
---- linux-3.18.12.orig/fs/buffer.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/buffer.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/buffer.c linux-3.18.14-rt/fs/buffer.c
+--- linux-3.18.14.orig/fs/buffer.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/buffer.c 2015-05-31 15:32:47.905635372 -0500
@@ -301,8 +301,7 @@
* decide that the page is now completely done.
*/
@@ -7033,9 +10661,9 @@ diff -Nur linux-3.18.12.orig/fs/buffer.c linux-3.18.12/fs/buffer.c
preempt_disable();
__this_cpu_inc(bh_accounting.nr);
recalc_bh_state();
-diff -Nur linux-3.18.12.orig/fs/dcache.c linux-3.18.12/fs/dcache.c
---- linux-3.18.12.orig/fs/dcache.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/dcache.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/dcache.c linux-3.18.14-rt/fs/dcache.c
+--- linux-3.18.14.orig/fs/dcache.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/dcache.c 2015-05-31 15:32:47.929635371 -0500
@@ -19,6 +19,7 @@
#include <linux/mm.h>
#include <linux/fs.h>
@@ -7062,9 +10690,9 @@ diff -Nur linux-3.18.12.orig/fs/dcache.c linux-3.18.12/fs/dcache.c
goto again;
}
dentry->d_flags &= ~DCACHE_CANT_MOUNT;
-diff -Nur linux-3.18.12.orig/fs/eventpoll.c linux-3.18.12/fs/eventpoll.c
---- linux-3.18.12.orig/fs/eventpoll.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/eventpoll.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/eventpoll.c linux-3.18.14-rt/fs/eventpoll.c
+--- linux-3.18.14.orig/fs/eventpoll.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/eventpoll.c 2015-05-31 15:32:47.945635371 -0500
@@ -505,12 +505,12 @@
*/
static void ep_poll_safewake(wait_queue_head_t *wq)
@@ -7080,9 +10708,9 @@ diff -Nur linux-3.18.12.orig/fs/eventpoll.c linux-3.18.12/fs/eventpoll.c
}
static void ep_remove_wait_queue(struct eppoll_entry *pwq)
-diff -Nur linux-3.18.12.orig/fs/exec.c linux-3.18.12/fs/exec.c
---- linux-3.18.12.orig/fs/exec.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/exec.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/exec.c linux-3.18.14-rt/fs/exec.c
+--- linux-3.18.14.orig/fs/exec.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/exec.c 2015-05-31 15:32:47.945635371 -0500
@@ -841,12 +841,14 @@
}
}
@@ -7098,9 +10726,9 @@ diff -Nur linux-3.18.12.orig/fs/exec.c linux-3.18.12/fs/exec.c
task_unlock(tsk);
if (old_mm) {
up_read(&old_mm->mmap_sem);
-diff -Nur linux-3.18.12.orig/fs/jbd/checkpoint.c linux-3.18.12/fs/jbd/checkpoint.c
---- linux-3.18.12.orig/fs/jbd/checkpoint.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/jbd/checkpoint.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/jbd/checkpoint.c linux-3.18.14-rt/fs/jbd/checkpoint.c
+--- linux-3.18.14.orig/fs/jbd/checkpoint.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/jbd/checkpoint.c 2015-05-31 15:32:47.957635371 -0500
@@ -129,6 +129,8 @@
if (journal->j_flags & JFS_ABORT)
return;
@@ -7110,9 +10738,9 @@ diff -Nur linux-3.18.12.orig/fs/jbd/checkpoint.c linux-3.18.12/fs/jbd/checkpoint
mutex_lock(&journal->j_checkpoint_mutex);
/*
-diff -Nur linux-3.18.12.orig/fs/jbd2/checkpoint.c linux-3.18.12/fs/jbd2/checkpoint.c
---- linux-3.18.12.orig/fs/jbd2/checkpoint.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/jbd2/checkpoint.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/jbd2/checkpoint.c linux-3.18.14-rt/fs/jbd2/checkpoint.c
+--- linux-3.18.14.orig/fs/jbd2/checkpoint.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/jbd2/checkpoint.c 2015-05-31 15:32:47.969635371 -0500
@@ -116,6 +116,8 @@
nblocks = jbd2_space_needed(journal);
while (jbd2_log_space_left(journal) < nblocks) {
@@ -7122,9 +10750,9 @@ diff -Nur linux-3.18.12.orig/fs/jbd2/checkpoint.c linux-3.18.12/fs/jbd2/checkpoi
mutex_lock(&journal->j_checkpoint_mutex);
/*
-diff -Nur linux-3.18.12.orig/fs/namespace.c linux-3.18.12/fs/namespace.c
---- linux-3.18.12.orig/fs/namespace.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/namespace.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/namespace.c linux-3.18.14-rt/fs/namespace.c
+--- linux-3.18.14.orig/fs/namespace.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/namespace.c 2015-05-31 15:32:47.969635371 -0500
@@ -14,6 +14,7 @@
#include <linux/mnt_namespace.h>
#include <linux/user_namespace.h>
@@ -7147,9 +10775,9 @@ diff -Nur linux-3.18.12.orig/fs/namespace.c linux-3.18.12/fs/namespace.c
/*
* After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
* be set to match its requirements. So we must not load that until
-diff -Nur linux-3.18.12.orig/fs/ntfs/aops.c linux-3.18.12/fs/ntfs/aops.c
---- linux-3.18.12.orig/fs/ntfs/aops.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/ntfs/aops.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/ntfs/aops.c linux-3.18.14-rt/fs/ntfs/aops.c
+--- linux-3.18.14.orig/fs/ntfs/aops.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/ntfs/aops.c 2015-05-31 15:32:47.969635371 -0500
@@ -107,8 +107,7 @@
"0x%llx.", (unsigned long long)bh->b_blocknr);
}
@@ -7197,9 +10825,9 @@ diff -Nur linux-3.18.12.orig/fs/ntfs/aops.c linux-3.18.12/fs/ntfs/aops.c
}
/**
-diff -Nur linux-3.18.12.orig/fs/timerfd.c linux-3.18.12/fs/timerfd.c
---- linux-3.18.12.orig/fs/timerfd.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/fs/timerfd.c 2015-04-26 13:32:22.411684003 -0500
+diff -Nur linux-3.18.14.orig/fs/timerfd.c linux-3.18.14-rt/fs/timerfd.c
+--- linux-3.18.14.orig/fs/timerfd.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/timerfd.c 2015-05-31 15:32:47.969635371 -0500
@@ -449,7 +449,10 @@
break;
}
@@ -7212,9 +10840,21 @@ diff -Nur linux-3.18.12.orig/fs/timerfd.c linux-3.18.12/fs/timerfd.c
}
/*
-diff -Nur linux-3.18.12.orig/include/acpi/platform/aclinux.h linux-3.18.12/include/acpi/platform/aclinux.h
---- linux-3.18.12.orig/include/acpi/platform/aclinux.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/acpi/platform/aclinux.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/fs/xfs/xfs_linux.h linux-3.18.14-rt/fs/xfs/xfs_linux.h
+--- linux-3.18.14.orig/fs/xfs/xfs_linux.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/fs/xfs/xfs_linux.h 2015-05-31 15:32:47.989635371 -0500
+@@ -119,7 +119,7 @@
+ /*
+ * Feature macros (disable/enable)
+ */
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT_FULL)
+ #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
+ #else
+ #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
+diff -Nur linux-3.18.14.orig/include/acpi/platform/aclinux.h linux-3.18.14-rt/include/acpi/platform/aclinux.h
+--- linux-3.18.14.orig/include/acpi/platform/aclinux.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/acpi/platform/aclinux.h 2015-05-31 15:32:48.013635371 -0500
@@ -123,6 +123,7 @@
#define acpi_cache_t struct kmem_cache
@@ -7244,9 +10884,9 @@ diff -Nur linux-3.18.12.orig/include/acpi/platform/aclinux.h linux-3.18.12/inclu
/*
* OSL interfaces used by debugger/disassembler
*/
-diff -Nur linux-3.18.12.orig/include/asm-generic/bug.h linux-3.18.12/include/asm-generic/bug.h
---- linux-3.18.12.orig/include/asm-generic/bug.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/asm-generic/bug.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/asm-generic/bug.h linux-3.18.14-rt/include/asm-generic/bug.h
+--- linux-3.18.14.orig/include/asm-generic/bug.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/asm-generic/bug.h 2015-05-31 15:32:48.037635370 -0500
@@ -206,6 +206,20 @@
# define WARN_ON_SMP(x) ({0;})
#endif
@@ -7268,9 +10908,9 @@ diff -Nur linux-3.18.12.orig/include/asm-generic/bug.h linux-3.18.12/include/asm
#endif /* __ASSEMBLY__ */
#endif
-diff -Nur linux-3.18.12.orig/include/linux/blkdev.h linux-3.18.12/include/linux/blkdev.h
---- linux-3.18.12.orig/include/linux/blkdev.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/blkdev.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/blkdev.h linux-3.18.14-rt/include/linux/blkdev.h
+--- linux-3.18.14.orig/include/linux/blkdev.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/blkdev.h 2015-05-31 15:32:48.077635370 -0500
@@ -101,6 +101,7 @@
struct list_head queuelist;
union {
@@ -7288,9 +10928,9 @@ diff -Nur linux-3.18.12.orig/include/linux/blkdev.h linux-3.18.12/include/linux/
struct percpu_ref mq_usage_counter;
struct list_head all_q_node;
-diff -Nur linux-3.18.12.orig/include/linux/blk-mq.h linux-3.18.12/include/linux/blk-mq.h
---- linux-3.18.12.orig/include/linux/blk-mq.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/blk-mq.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/blk-mq.h linux-3.18.14-rt/include/linux/blk-mq.h
+--- linux-3.18.14.orig/include/linux/blk-mq.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/blk-mq.h 2015-05-31 15:32:48.069635370 -0500
@@ -169,6 +169,7 @@
struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index);
@@ -7299,9 +10939,9 @@ diff -Nur linux-3.18.12.orig/include/linux/blk-mq.h linux-3.18.12/include/linux/
void blk_mq_start_request(struct request *rq);
void blk_mq_end_request(struct request *rq, int error);
-diff -Nur linux-3.18.12.orig/include/linux/bottom_half.h linux-3.18.12/include/linux/bottom_half.h
---- linux-3.18.12.orig/include/linux/bottom_half.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/bottom_half.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/bottom_half.h linux-3.18.14-rt/include/linux/bottom_half.h
+--- linux-3.18.14.orig/include/linux/bottom_half.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/bottom_half.h 2015-05-31 15:32:48.081635370 -0500
@@ -4,6 +4,17 @@
#include <linux/preempt.h>
#include <linux/preempt_mask.h>
@@ -7327,9 +10967,9 @@ diff -Nur linux-3.18.12.orig/include/linux/bottom_half.h linux-3.18.12/include/l
+#endif
#endif /* _LINUX_BH_H */
-diff -Nur linux-3.18.12.orig/include/linux/buffer_head.h linux-3.18.12/include/linux/buffer_head.h
---- linux-3.18.12.orig/include/linux/buffer_head.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/buffer_head.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/buffer_head.h linux-3.18.14-rt/include/linux/buffer_head.h
+--- linux-3.18.14.orig/include/linux/buffer_head.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/buffer_head.h 2015-05-31 15:32:48.109635370 -0500
@@ -75,8 +75,52 @@
struct address_space *b_assoc_map; /* mapping this buffer is
associated with */
@@ -7383,9 +11023,9 @@ diff -Nur linux-3.18.12.orig/include/linux/buffer_head.h linux-3.18.12/include/l
/*
* macro tricks to expand the set_buffer_foo(), clear_buffer_foo()
* and buffer_foo() functions.
-diff -Nur linux-3.18.12.orig/include/linux/cgroup.h linux-3.18.12/include/linux/cgroup.h
---- linux-3.18.12.orig/include/linux/cgroup.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/cgroup.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/cgroup.h linux-3.18.14-rt/include/linux/cgroup.h
+--- linux-3.18.14.orig/include/linux/cgroup.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/cgroup.h 2015-05-31 15:32:48.117635370 -0500
@@ -22,6 +22,7 @@
#include <linux/seq_file.h>
#include <linux/kernfs.h>
@@ -7402,9 +11042,9 @@ diff -Nur linux-3.18.12.orig/include/linux/cgroup.h linux-3.18.12/include/linux/
};
/* bits in struct cgroup_subsys_state flags field */
-diff -Nur linux-3.18.12.orig/include/linux/completion.h linux-3.18.12/include/linux/completion.h
---- linux-3.18.12.orig/include/linux/completion.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/completion.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/completion.h linux-3.18.14-rt/include/linux/completion.h
+--- linux-3.18.14.orig/include/linux/completion.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/completion.h 2015-05-31 15:32:48.117635370 -0500
@@ -7,8 +7,7 @@
* Atomic wait-for-completion handler data structures.
* See kernel/sched/completion.c for details.
@@ -7438,9 +11078,9 @@ diff -Nur linux-3.18.12.orig/include/linux/completion.h linux-3.18.12/include/li
}
/**
-diff -Nur linux-3.18.12.orig/include/linux/cpu.h linux-3.18.12/include/linux/cpu.h
---- linux-3.18.12.orig/include/linux/cpu.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/cpu.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/cpu.h linux-3.18.14-rt/include/linux/cpu.h
+--- linux-3.18.14.orig/include/linux/cpu.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/cpu.h 2015-05-31 15:32:48.129635370 -0500
@@ -217,6 +217,8 @@
extern void put_online_cpus(void);
extern void cpu_hotplug_disable(void);
@@ -7459,9 +11099,9 @@ diff -Nur linux-3.18.12.orig/include/linux/cpu.h linux-3.18.12/include/linux/cpu
#define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
#define __hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
/* These aren't inline functions due to a GCC bug. */
-diff -Nur linux-3.18.12.orig/include/linux/delay.h linux-3.18.12/include/linux/delay.h
---- linux-3.18.12.orig/include/linux/delay.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/delay.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/delay.h linux-3.18.14-rt/include/linux/delay.h
+--- linux-3.18.14.orig/include/linux/delay.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/delay.h 2015-05-31 15:32:48.129635370 -0500
@@ -52,4 +52,10 @@
msleep(seconds * 1000);
}
@@ -7473,9 +11113,9 @@ diff -Nur linux-3.18.12.orig/include/linux/delay.h linux-3.18.12/include/linux/d
+#endif
+
#endif /* defined(_LINUX_DELAY_H) */
-diff -Nur linux-3.18.12.orig/include/linux/ftrace_event.h linux-3.18.12/include/linux/ftrace_event.h
---- linux-3.18.12.orig/include/linux/ftrace_event.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/ftrace_event.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/ftrace_event.h linux-3.18.14-rt/include/linux/ftrace_event.h
+--- linux-3.18.14.orig/include/linux/ftrace_event.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/ftrace_event.h 2015-05-31 15:32:48.157635370 -0500
@@ -61,6 +61,9 @@
unsigned char flags;
unsigned char preempt_count;
@@ -7486,9 +11126,9 @@ diff -Nur linux-3.18.12.orig/include/linux/ftrace_event.h linux-3.18.12/include/
};
#define FTRACE_MAX_EVENT \
-diff -Nur linux-3.18.12.orig/include/linux/highmem.h linux-3.18.12/include/linux/highmem.h
---- linux-3.18.12.orig/include/linux/highmem.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/highmem.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/highmem.h linux-3.18.14-rt/include/linux/highmem.h
+--- linux-3.18.14.orig/include/linux/highmem.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/highmem.h 2015-05-31 15:32:48.157635370 -0500
@@ -7,6 +7,7 @@
#include <linux/mm.h>
#include <linux/uaccess.h>
@@ -7553,9 +11193,9 @@ diff -Nur linux-3.18.12.orig/include/linux/highmem.h linux-3.18.12/include/linux
#endif
}
-diff -Nur linux-3.18.12.orig/include/linux/hrtimer.h linux-3.18.12/include/linux/hrtimer.h
---- linux-3.18.12.orig/include/linux/hrtimer.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/hrtimer.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/hrtimer.h linux-3.18.14-rt/include/linux/hrtimer.h
+--- linux-3.18.14.orig/include/linux/hrtimer.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/hrtimer.h 2015-05-31 15:32:48.161635369 -0500
@@ -111,6 +111,11 @@
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
@@ -7600,9 +11240,9 @@ diff -Nur linux-3.18.12.orig/include/linux/hrtimer.h linux-3.18.12/include/linux
/* Query timers: */
extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
-diff -Nur linux-3.18.12.orig/include/linux/idr.h linux-3.18.12/include/linux/idr.h
---- linux-3.18.12.orig/include/linux/idr.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/idr.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/idr.h linux-3.18.14-rt/include/linux/idr.h
+--- linux-3.18.14.orig/include/linux/idr.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/idr.h 2015-05-31 15:32:48.161635369 -0500
@@ -95,10 +95,14 @@
* Each idr_preload() should be matched with an invocation of this
* function. See idr_preload() for details.
@@ -7618,9 +11258,9 @@ diff -Nur linux-3.18.12.orig/include/linux/idr.h linux-3.18.12/include/linux/idr
/**
* idr_find - return pointer for given id
-diff -Nur linux-3.18.12.orig/include/linux/init_task.h linux-3.18.12/include/linux/init_task.h
---- linux-3.18.12.orig/include/linux/init_task.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/init_task.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/init_task.h linux-3.18.14-rt/include/linux/init_task.h
+--- linux-3.18.14.orig/include/linux/init_task.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/init_task.h 2015-05-31 15:32:48.177635369 -0500
@@ -147,9 +147,16 @@
# define INIT_PERF_EVENTS(tsk)
#endif
@@ -7647,9 +11287,9 @@ diff -Nur linux-3.18.12.orig/include/linux/init_task.h linux-3.18.12/include/lin
.pids = { \
[PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID), \
[PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID), \
-diff -Nur linux-3.18.12.orig/include/linux/interrupt.h linux-3.18.12/include/linux/interrupt.h
---- linux-3.18.12.orig/include/linux/interrupt.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/interrupt.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/interrupt.h linux-3.18.14-rt/include/linux/interrupt.h
+--- linux-3.18.14.orig/include/linux/interrupt.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/interrupt.h 2015-05-31 15:32:48.181635369 -0500
@@ -57,6 +57,7 @@
* IRQF_NO_THREAD - Interrupt cannot be threaded
* IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
@@ -7816,9 +11456,9 @@ diff -Nur linux-3.18.12.orig/include/linux/interrupt.h linux-3.18.12/include/lin
/*
* Autoprobing for irqs:
*
-diff -Nur linux-3.18.12.orig/include/linux/irqdesc.h linux-3.18.12/include/linux/irqdesc.h
---- linux-3.18.12.orig/include/linux/irqdesc.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/irqdesc.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/irqdesc.h linux-3.18.14-rt/include/linux/irqdesc.h
+--- linux-3.18.14.orig/include/linux/irqdesc.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/irqdesc.h 2015-05-31 15:32:48.217635369 -0500
@@ -63,6 +63,7 @@
unsigned int irqs_unhandled;
atomic_t threads_handled;
@@ -7827,9 +11467,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irqdesc.h linux-3.18.12/include/linux
raw_spinlock_t lock;
struct cpumask *percpu_enabled;
#ifdef CONFIG_SMP
-diff -Nur linux-3.18.12.orig/include/linux/irqflags.h linux-3.18.12/include/linux/irqflags.h
---- linux-3.18.12.orig/include/linux/irqflags.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/irqflags.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/irqflags.h linux-3.18.14-rt/include/linux/irqflags.h
+--- linux-3.18.14.orig/include/linux/irqflags.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/irqflags.h 2015-05-31 15:32:48.233635369 -0500
@@ -25,8 +25,6 @@
# define trace_softirqs_enabled(p) ((p)->softirqs_enabled)
# define trace_hardirq_enter() do { current->hardirq_context++; } while (0)
@@ -7880,9 +11520,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irqflags.h linux-3.18.12/include/linu
+#endif
+
#endif
-diff -Nur linux-3.18.12.orig/include/linux/irq.h linux-3.18.12/include/linux/irq.h
---- linux-3.18.12.orig/include/linux/irq.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/irq.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/irq.h linux-3.18.14-rt/include/linux/irq.h
+--- linux-3.18.14.orig/include/linux/irq.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/irq.h 2015-05-31 15:32:48.185635369 -0500
@@ -73,6 +73,7 @@
* IRQ_IS_POLLED - Always polled by another interrupt. Exclude
* it from the spurious interrupt detection
@@ -7907,9 +11547,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irq.h linux-3.18.12/include/linux/irq
#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
-diff -Nur linux-3.18.12.orig/include/linux/irq_work.h linux-3.18.12/include/linux/irq_work.h
---- linux-3.18.12.orig/include/linux/irq_work.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/irq_work.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/irq_work.h linux-3.18.14-rt/include/linux/irq_work.h
+--- linux-3.18.14.orig/include/linux/irq_work.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/irq_work.h 2015-05-31 15:32:48.217635369 -0500
@@ -16,6 +16,7 @@
#define IRQ_WORK_BUSY 2UL
#define IRQ_WORK_FLAGS 3UL
@@ -7918,9 +11558,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irq_work.h linux-3.18.12/include/linu
struct irq_work {
unsigned long flags;
-diff -Nur linux-3.18.12.orig/include/linux/jbd_common.h linux-3.18.12/include/linux/jbd_common.h
---- linux-3.18.12.orig/include/linux/jbd_common.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/jbd_common.h 2015-04-26 13:32:22.415684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/jbd_common.h linux-3.18.14-rt/include/linux/jbd_common.h
+--- linux-3.18.14.orig/include/linux/jbd_common.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/jbd_common.h 2015-05-31 15:32:48.237635369 -0500
@@ -15,32 +15,56 @@
static inline void jbd_lock_bh_state(struct buffer_head *bh)
@@ -7978,9 +11618,9 @@ diff -Nur linux-3.18.12.orig/include/linux/jbd_common.h linux-3.18.12/include/li
}
#endif
-diff -Nur linux-3.18.12.orig/include/linux/jump_label.h linux-3.18.12/include/linux/jump_label.h
---- linux-3.18.12.orig/include/linux/jump_label.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/jump_label.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/jump_label.h linux-3.18.14-rt/include/linux/jump_label.h
+--- linux-3.18.14.orig/include/linux/jump_label.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/jump_label.h 2015-05-31 15:32:48.237635369 -0500
@@ -55,7 +55,8 @@
"%s used before call to jump_label_init", \
__func__)
@@ -7991,9 +11631,9 @@ diff -Nur linux-3.18.12.orig/include/linux/jump_label.h linux-3.18.12/include/li
struct static_key {
atomic_t enabled;
-diff -Nur linux-3.18.12.orig/include/linux/kdb.h linux-3.18.12/include/linux/kdb.h
---- linux-3.18.12.orig/include/linux/kdb.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/kdb.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/kdb.h linux-3.18.14-rt/include/linux/kdb.h
+--- linux-3.18.14.orig/include/linux/kdb.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/kdb.h 2015-05-31 15:32:48.245635369 -0500
@@ -116,7 +116,7 @@
extern __printf(1, 0) int vkdb_printf(const char *fmt, va_list args);
extern __printf(1, 2) int kdb_printf(const char *, ...);
@@ -8011,9 +11651,9 @@ diff -Nur linux-3.18.12.orig/include/linux/kdb.h linux-3.18.12/include/linux/kdb
static inline void kdb_init(int level) {}
static inline int kdb_register(char *cmd, kdb_func_t func, char *usage,
char *help, short minlen) { return 0; }
-diff -Nur linux-3.18.12.orig/include/linux/kernel.h linux-3.18.12/include/linux/kernel.h
---- linux-3.18.12.orig/include/linux/kernel.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/kernel.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/kernel.h linux-3.18.14-rt/include/linux/kernel.h
+--- linux-3.18.14.orig/include/linux/kernel.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/kernel.h 2015-05-31 15:32:48.245635369 -0500
@@ -451,6 +451,7 @@
SYSTEM_HALT,
SYSTEM_POWER_OFF,
@@ -8022,10 +11662,10 @@ diff -Nur linux-3.18.12.orig/include/linux/kernel.h linux-3.18.12/include/linux/
} system_state;
#define TAINT_PROPRIETARY_MODULE 0
-diff -Nur linux-3.18.12.orig/include/linux/kvm_host.h linux-3.18.12/include/linux/kvm_host.h
---- linux-3.18.12.orig/include/linux/kvm_host.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/kvm_host.h 2015-04-26 13:32:22.419684003 -0500
-@@ -244,7 +244,7 @@
+diff -Nur linux-3.18.14.orig/include/linux/kvm_host.h linux-3.18.14-rt/include/linux/kvm_host.h
+--- linux-3.18.14.orig/include/linux/kvm_host.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/kvm_host.h 2015-05-31 15:32:48.253635368 -0500
+@@ -245,7 +245,7 @@
int fpu_active;
int guest_fpu_loaded, guest_xcr0_loaded;
@@ -8034,7 +11674,7 @@ diff -Nur linux-3.18.12.orig/include/linux/kvm_host.h linux-3.18.12/include/linu
struct pid *pid;
int sigset_active;
sigset_t sigset;
-@@ -687,7 +687,7 @@
+@@ -688,7 +688,7 @@
}
#endif
@@ -8043,9 +11683,1124 @@ diff -Nur linux-3.18.12.orig/include/linux/kvm_host.h linux-3.18.12/include/linu
{
#ifdef __KVM_HAVE_ARCH_WQP
return vcpu->arch.wqp;
-diff -Nur linux-3.18.12.orig/include/linux/lglock.h linux-3.18.12/include/linux/lglock.h
---- linux-3.18.12.orig/include/linux/lglock.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/lglock.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/kvm_host.h.orig linux-3.18.14-rt/include/linux/kvm_host.h.orig
+--- linux-3.18.14.orig/include/linux/kvm_host.h.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/kvm_host.h.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,1111 @@
++#ifndef __KVM_HOST_H
++#define __KVM_HOST_H
++
++/*
++ * This work is licensed under the terms of the GNU GPL, version 2. See
++ * the COPYING file in the top-level directory.
++ */
++
++#include <linux/types.h>
++#include <linux/hardirq.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/spinlock.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/bug.h>
++#include <linux/mm.h>
++#include <linux/mmu_notifier.h>
++#include <linux/preempt.h>
++#include <linux/msi.h>
++#include <linux/slab.h>
++#include <linux/rcupdate.h>
++#include <linux/ratelimit.h>
++#include <linux/err.h>
++#include <linux/irqflags.h>
++#include <linux/context_tracking.h>
++#include <asm/signal.h>
++
++#include <linux/kvm.h>
++#include <linux/kvm_para.h>
++
++#include <linux/kvm_types.h>
++
++#include <asm/kvm_host.h>
++
++#ifndef KVM_MMIO_SIZE
++#define KVM_MMIO_SIZE 8
++#endif
++
++/*
++ * The bit 16 ~ bit 31 of kvm_memory_region::flags are internally used
++ * in kvm, other bits are visible for userspace which are defined in
++ * include/linux/kvm_h.
++ */
++#define KVM_MEMSLOT_INVALID (1UL << 16)
++#define KVM_MEMSLOT_INCOHERENT (1UL << 17)
++
++/* Two fragments for cross MMIO pages. */
++#define KVM_MAX_MMIO_FRAGMENTS 2
++
++/*
++ * For the normal pfn, the highest 12 bits should be zero,
++ * so we can mask bit 62 ~ bit 52 to indicate the error pfn,
++ * mask bit 63 to indicate the noslot pfn.
++ */
++#define KVM_PFN_ERR_MASK (0x7ffULL << 52)
++#define KVM_PFN_ERR_NOSLOT_MASK (0xfffULL << 52)
++#define KVM_PFN_NOSLOT (0x1ULL << 63)
++
++#define KVM_PFN_ERR_FAULT (KVM_PFN_ERR_MASK)
++#define KVM_PFN_ERR_HWPOISON (KVM_PFN_ERR_MASK + 1)
++#define KVM_PFN_ERR_RO_FAULT (KVM_PFN_ERR_MASK + 2)
++
++/*
++ * error pfns indicate that the gfn is in slot but faild to
++ * translate it to pfn on host.
++ */
++static inline bool is_error_pfn(pfn_t pfn)
++{
++ return !!(pfn & KVM_PFN_ERR_MASK);
++}
++
++/*
++ * error_noslot pfns indicate that the gfn can not be
++ * translated to pfn - it is not in slot or failed to
++ * translate it to pfn.
++ */
++static inline bool is_error_noslot_pfn(pfn_t pfn)
++{
++ return !!(pfn & KVM_PFN_ERR_NOSLOT_MASK);
++}
++
++/* noslot pfn indicates that the gfn is not in slot. */
++static inline bool is_noslot_pfn(pfn_t pfn)
++{
++ return pfn == KVM_PFN_NOSLOT;
++}
++
++/*
++ * architectures with KVM_HVA_ERR_BAD other than PAGE_OFFSET (e.g. s390)
++ * provide own defines and kvm_is_error_hva
++ */
++#ifndef KVM_HVA_ERR_BAD
++
++#define KVM_HVA_ERR_BAD (PAGE_OFFSET)
++#define KVM_HVA_ERR_RO_BAD (PAGE_OFFSET + PAGE_SIZE)
++
++static inline bool kvm_is_error_hva(unsigned long addr)
++{
++ return addr >= PAGE_OFFSET;
++}
++
++#endif
++
++#define KVM_ERR_PTR_BAD_PAGE (ERR_PTR(-ENOENT))
++
++static inline bool is_error_page(struct page *page)
++{
++ return IS_ERR(page);
++}
++
++/*
++ * vcpu->requests bit members
++ */
++#define KVM_REQ_TLB_FLUSH 0
++#define KVM_REQ_MIGRATE_TIMER 1
++#define KVM_REQ_REPORT_TPR_ACCESS 2
++#define KVM_REQ_MMU_RELOAD 3
++#define KVM_REQ_TRIPLE_FAULT 4
++#define KVM_REQ_PENDING_TIMER 5
++#define KVM_REQ_UNHALT 6
++#define KVM_REQ_MMU_SYNC 7
++#define KVM_REQ_CLOCK_UPDATE 8
++#define KVM_REQ_KICK 9
++#define KVM_REQ_DEACTIVATE_FPU 10
++#define KVM_REQ_EVENT 11
++#define KVM_REQ_APF_HALT 12
++#define KVM_REQ_STEAL_UPDATE 13
++#define KVM_REQ_NMI 14
++#define KVM_REQ_PMU 15
++#define KVM_REQ_PMI 16
++#define KVM_REQ_WATCHDOG 17
++#define KVM_REQ_MASTERCLOCK_UPDATE 18
++#define KVM_REQ_MCLOCK_INPROGRESS 19
++#define KVM_REQ_EPR_EXIT 20
++#define KVM_REQ_SCAN_IOAPIC 21
++#define KVM_REQ_GLOBAL_CLOCK_UPDATE 22
++#define KVM_REQ_ENABLE_IBS 23
++#define KVM_REQ_DISABLE_IBS 24
++#define KVM_REQ_APIC_PAGE_RELOAD 25
++
++#define KVM_USERSPACE_IRQ_SOURCE_ID 0
++#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
++
++extern struct kmem_cache *kvm_vcpu_cache;
++
++extern spinlock_t kvm_lock;
++extern struct list_head vm_list;
++
++struct kvm_io_range {
++ gpa_t addr;
++ int len;
++ struct kvm_io_device *dev;
++};
++
++#define NR_IOBUS_DEVS 1000
++
++struct kvm_io_bus {
++ int dev_count;
++ int ioeventfd_count;
++ struct kvm_io_range range[];
++};
++
++enum kvm_bus {
++ KVM_MMIO_BUS,
++ KVM_PIO_BUS,
++ KVM_VIRTIO_CCW_NOTIFY_BUS,
++ KVM_FAST_MMIO_BUS,
++ KVM_NR_BUSES
++};
++
++int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
++ int len, const void *val);
++int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
++ int len, const void *val, long cookie);
++int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
++ void *val);
++int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
++ int len, struct kvm_io_device *dev);
++int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
++ struct kvm_io_device *dev);
++
++#ifdef CONFIG_KVM_ASYNC_PF
++struct kvm_async_pf {
++ struct work_struct work;
++ struct list_head link;
++ struct list_head queue;
++ struct kvm_vcpu *vcpu;
++ struct mm_struct *mm;
++ gva_t gva;
++ unsigned long addr;
++ struct kvm_arch_async_pf arch;
++ bool wakeup_all;
++};
++
++void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu);
++void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu);
++int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
++ struct kvm_arch_async_pf *arch);
++int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu);
++#endif
++
++/*
++ * Carry out a gup that requires IO. Allow the mm to relinquish the mmap
++ * semaphore if the filemap/swap has to wait on a page lock. pagep == NULL
++ * controls whether we retry the gup one more time to completion in that case.
++ * Typically this is called after a FAULT_FLAG_RETRY_NOWAIT in the main tdp
++ * handler.
++ */
++int kvm_get_user_page_io(struct task_struct *tsk, struct mm_struct *mm,
++ unsigned long addr, bool write_fault,
++ struct page **pagep);
++
++enum {
++ OUTSIDE_GUEST_MODE,
++ IN_GUEST_MODE,
++ EXITING_GUEST_MODE,
++ READING_SHADOW_PAGE_TABLES,
++};
++
++/*
++ * Sometimes a large or cross-page mmio needs to be broken up into separate
++ * exits for userspace servicing.
++ */
++struct kvm_mmio_fragment {
++ gpa_t gpa;
++ void *data;
++ unsigned len;
++};
++
++struct kvm_vcpu {
++ struct kvm *kvm;
++#ifdef CONFIG_PREEMPT_NOTIFIERS
++ struct preempt_notifier preempt_notifier;
++#endif
++ int cpu;
++ int vcpu_id;
++ int srcu_idx;
++ int mode;
++ unsigned long requests;
++ unsigned long guest_debug;
++
++ struct mutex mutex;
++ struct kvm_run *run;
++
++ int fpu_active;
++ int guest_fpu_loaded, guest_xcr0_loaded;
++ wait_queue_head_t wq;
++ struct pid *pid;
++ int sigset_active;
++ sigset_t sigset;
++ struct kvm_vcpu_stat stat;
++
++#ifdef CONFIG_HAS_IOMEM
++ int mmio_needed;
++ int mmio_read_completed;
++ int mmio_is_write;
++ int mmio_cur_fragment;
++ int mmio_nr_fragments;
++ struct kvm_mmio_fragment mmio_fragments[KVM_MAX_MMIO_FRAGMENTS];
++#endif
++
++#ifdef CONFIG_KVM_ASYNC_PF
++ struct {
++ u32 queued;
++ struct list_head queue;
++ struct list_head done;
++ spinlock_t lock;
++ } async_pf;
++#endif
++
++#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
++ /*
++ * Cpu relax intercept or pause loop exit optimization
++ * in_spin_loop: set when a vcpu does a pause loop exit
++ * or cpu relax intercepted.
++ * dy_eligible: indicates whether vcpu is eligible for directed yield.
++ */
++ struct {
++ bool in_spin_loop;
++ bool dy_eligible;
++ } spin_loop;
++#endif
++ bool preempted;
++ struct kvm_vcpu_arch arch;
++};
++
++static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
++{
++ return cmpxchg(&vcpu->mode, IN_GUEST_MODE, EXITING_GUEST_MODE);
++}
++
++/*
++ * Some of the bitops functions do not support too long bitmaps.
++ * This number must be determined not to exceed such limits.
++ */
++#define KVM_MEM_MAX_NR_PAGES ((1UL << 31) - 1)
++
++struct kvm_memory_slot {
++ gfn_t base_gfn;
++ unsigned long npages;
++ unsigned long *dirty_bitmap;
++ struct kvm_arch_memory_slot arch;
++ unsigned long userspace_addr;
++ u32 flags;
++ short id;
++};
++
++static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot)
++{
++ return ALIGN(memslot->npages, BITS_PER_LONG) / 8;
++}
++
++struct kvm_s390_adapter_int {
++ u64 ind_addr;
++ u64 summary_addr;
++ u64 ind_offset;
++ u32 summary_offset;
++ u32 adapter_id;
++};
++
++struct kvm_kernel_irq_routing_entry {
++ u32 gsi;
++ u32 type;
++ int (*set)(struct kvm_kernel_irq_routing_entry *e,
++ struct kvm *kvm, int irq_source_id, int level,
++ bool line_status);
++ union {
++ struct {
++ unsigned irqchip;
++ unsigned pin;
++ } irqchip;
++ struct msi_msg msi;
++ struct kvm_s390_adapter_int adapter;
++ };
++ struct hlist_node link;
++};
++
++#ifndef KVM_PRIVATE_MEM_SLOTS
++#define KVM_PRIVATE_MEM_SLOTS 0
++#endif
++
++#ifndef KVM_MEM_SLOTS_NUM
++#define KVM_MEM_SLOTS_NUM (KVM_USER_MEM_SLOTS + KVM_PRIVATE_MEM_SLOTS)
++#endif
++
++/*
++ * Note:
++ * memslots are not sorted by id anymore, please use id_to_memslot()
++ * to get the memslot by its id.
++ */
++struct kvm_memslots {
++ u64 generation;
++ struct kvm_memory_slot memslots[KVM_MEM_SLOTS_NUM];
++ /* The mapping table from slot id to the index in memslots[]. */
++ short id_to_index[KVM_MEM_SLOTS_NUM];
++};
++
++struct kvm {
++ spinlock_t mmu_lock;
++ struct mutex slots_lock;
++ struct mm_struct *mm; /* userspace tied to this vm */
++ struct kvm_memslots *memslots;
++ struct srcu_struct srcu;
++ struct srcu_struct irq_srcu;
++#ifdef CONFIG_KVM_APIC_ARCHITECTURE
++ u32 bsp_vcpu_id;
++#endif
++ struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
++ atomic_t online_vcpus;
++ int last_boosted_vcpu;
++ struct list_head vm_list;
++ struct mutex lock;
++ struct kvm_io_bus *buses[KVM_NR_BUSES];
++#ifdef CONFIG_HAVE_KVM_EVENTFD
++ struct {
++ spinlock_t lock;
++ struct list_head items;
++ struct list_head resampler_list;
++ struct mutex resampler_lock;
++ } irqfds;
++ struct list_head ioeventfds;
++#endif
++ struct kvm_vm_stat stat;
++ struct kvm_arch arch;
++ atomic_t users_count;
++#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
++ struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
++ spinlock_t ring_lock;
++ struct list_head coalesced_zones;
++#endif
++
++ struct mutex irq_lock;
++#ifdef CONFIG_HAVE_KVM_IRQCHIP
++ /*
++ * Update side is protected by irq_lock.
++ */
++ struct kvm_irq_routing_table __rcu *irq_routing;
++ struct hlist_head mask_notifier_list;
++#endif
++#ifdef CONFIG_HAVE_KVM_IRQFD
++ struct hlist_head irq_ack_notifier_list;
++#endif
++
++#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
++ struct mmu_notifier mmu_notifier;
++ unsigned long mmu_notifier_seq;
++ long mmu_notifier_count;
++#endif
++ long tlbs_dirty;
++ struct list_head devices;
++};
++
++#define kvm_err(fmt, ...) \
++ pr_err("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__)
++#define kvm_info(fmt, ...) \
++ pr_info("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__)
++#define kvm_debug(fmt, ...) \
++ pr_debug("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__)
++#define kvm_pr_unimpl(fmt, ...) \
++ pr_err_ratelimited("kvm [%i]: " fmt, \
++ task_tgid_nr(current), ## __VA_ARGS__)
++
++/* The guest did something we don't support. */
++#define vcpu_unimpl(vcpu, fmt, ...) \
++ kvm_pr_unimpl("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
++
++static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
++{
++ smp_rmb();
++ return kvm->vcpus[i];
++}
++
++#define kvm_for_each_vcpu(idx, vcpup, kvm) \
++ for (idx = 0; \
++ idx < atomic_read(&kvm->online_vcpus) && \
++ (vcpup = kvm_get_vcpu(kvm, idx)) != NULL; \
++ idx++)
++
++#define kvm_for_each_memslot(memslot, slots) \
++ for (memslot = &slots->memslots[0]; \
++ memslot < slots->memslots + KVM_MEM_SLOTS_NUM && memslot->npages;\
++ memslot++)
++
++int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id);
++void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
++
++int __must_check vcpu_load(struct kvm_vcpu *vcpu);
++void vcpu_put(struct kvm_vcpu *vcpu);
++
++#ifdef CONFIG_HAVE_KVM_IRQFD
++int kvm_irqfd_init(void);
++void kvm_irqfd_exit(void);
++#else
++static inline int kvm_irqfd_init(void)
++{
++ return 0;
++}
++
++static inline void kvm_irqfd_exit(void)
++{
++}
++#endif
++int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
++ struct module *module);
++void kvm_exit(void);
++
++void kvm_get_kvm(struct kvm *kvm);
++void kvm_put_kvm(struct kvm *kvm);
++
++static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm)
++{
++ return rcu_dereference_check(kvm->memslots,
++ srcu_read_lock_held(&kvm->srcu)
++ || lockdep_is_held(&kvm->slots_lock));
++}
++
++static inline struct kvm_memory_slot *
++id_to_memslot(struct kvm_memslots *slots, int id)
++{
++ int index = slots->id_to_index[id];
++ struct kvm_memory_slot *slot;
++
++ slot = &slots->memslots[index];
++
++ WARN_ON(slot->id != id);
++ return slot;
++}
++
++/*
++ * KVM_SET_USER_MEMORY_REGION ioctl allows the following operations:
++ * - create a new memory slot
++ * - delete an existing memory slot
++ * - modify an existing memory slot
++ * -- move it in the guest physical memory space
++ * -- just change its flags
++ *
++ * Since flags can be changed by some of these operations, the following
++ * differentiation is the best we can do for __kvm_set_memory_region():
++ */
++enum kvm_mr_change {
++ KVM_MR_CREATE,
++ KVM_MR_DELETE,
++ KVM_MR_MOVE,
++ KVM_MR_FLAGS_ONLY,
++};
++
++int kvm_set_memory_region(struct kvm *kvm,
++ struct kvm_userspace_memory_region *mem);
++int __kvm_set_memory_region(struct kvm *kvm,
++ struct kvm_userspace_memory_region *mem);
++void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
++ struct kvm_memory_slot *dont);
++int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
++ unsigned long npages);
++void kvm_arch_memslots_updated(struct kvm *kvm);
++int kvm_arch_prepare_memory_region(struct kvm *kvm,
++ struct kvm_memory_slot *memslot,
++ struct kvm_userspace_memory_region *mem,
++ enum kvm_mr_change change);
++void kvm_arch_commit_memory_region(struct kvm *kvm,
++ struct kvm_userspace_memory_region *mem,
++ const struct kvm_memory_slot *old,
++ enum kvm_mr_change change);
++bool kvm_largepages_enabled(void);
++void kvm_disable_largepages(void);
++/* flush all memory translations */
++void kvm_arch_flush_shadow_all(struct kvm *kvm);
++/* flush memory translations pointing to 'slot' */
++void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
++ struct kvm_memory_slot *slot);
++
++int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages,
++ int nr_pages);
++
++struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
++unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn);
++unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable);
++unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn);
++unsigned long gfn_to_hva_memslot_prot(struct kvm_memory_slot *slot, gfn_t gfn,
++ bool *writable);
++void kvm_release_page_clean(struct page *page);
++void kvm_release_page_dirty(struct page *page);
++void kvm_set_page_accessed(struct page *page);
++
++pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn);
++pfn_t gfn_to_pfn_async(struct kvm *kvm, gfn_t gfn, bool *async,
++ bool write_fault, bool *writable);
++pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn);
++pfn_t gfn_to_pfn_prot(struct kvm *kvm, gfn_t gfn, bool write_fault,
++ bool *writable);
++pfn_t gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn);
++pfn_t gfn_to_pfn_memslot_atomic(struct kvm_memory_slot *slot, gfn_t gfn);
++
++void kvm_release_pfn_clean(pfn_t pfn);
++void kvm_set_pfn_dirty(pfn_t pfn);
++void kvm_set_pfn_accessed(pfn_t pfn);
++void kvm_get_pfn(pfn_t pfn);
++
++int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
++ int len);
++int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
++ unsigned long len);
++int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len);
++int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
++ void *data, unsigned long len);
++int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn, const void *data,
++ int offset, int len);
++int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
++ unsigned long len);
++int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
++ void *data, unsigned long len);
++int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
++ gpa_t gpa, unsigned long len);
++int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
++int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
++struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
++int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn);
++unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn);
++void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
++
++void kvm_vcpu_block(struct kvm_vcpu *vcpu);
++void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
++int kvm_vcpu_yield_to(struct kvm_vcpu *target);
++void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu);
++void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
++void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
++
++void kvm_flush_remote_tlbs(struct kvm *kvm);
++void kvm_reload_remote_mmus(struct kvm *kvm);
++void kvm_make_mclock_inprogress_request(struct kvm *kvm);
++void kvm_make_scan_ioapic_request(struct kvm *kvm);
++bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
++
++long kvm_arch_dev_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg);
++long kvm_arch_vcpu_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg);
++int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
++
++int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext);
++
++int kvm_get_dirty_log(struct kvm *kvm,
++ struct kvm_dirty_log *log, int *is_dirty);
++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
++ struct kvm_dirty_log *log);
++
++int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
++ bool line_status);
++long kvm_arch_vm_ioctl(struct file *filp,
++ unsigned int ioctl, unsigned long arg);
++
++int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu);
++int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu);
++
++int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
++ struct kvm_translation *tr);
++
++int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs);
++int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs);
++int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs);
++int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
++ struct kvm_sregs *sregs);
++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state);
++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
++ struct kvm_mp_state *mp_state);
++int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
++ struct kvm_guest_debug *dbg);
++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
++
++int kvm_arch_init(void *opaque);
++void kvm_arch_exit(void);
++
++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu);
++void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu);
++
++void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu);
++
++void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu);
++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu);
++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id);
++int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu);
++int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu);
++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu);
++
++int kvm_arch_hardware_enable(void);
++void kvm_arch_hardware_disable(void);
++int kvm_arch_hardware_setup(void);
++void kvm_arch_hardware_unsetup(void);
++void kvm_arch_check_processor_compat(void *rtn);
++int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
++int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
++
++void *kvm_kvzalloc(unsigned long size);
++void kvm_kvfree(const void *addr);
++
++#ifndef __KVM_HAVE_ARCH_VM_ALLOC
++static inline struct kvm *kvm_arch_alloc_vm(void)
++{
++ return kzalloc(sizeof(struct kvm), GFP_KERNEL);
++}
++
++static inline void kvm_arch_free_vm(struct kvm *kvm)
++{
++ kfree(kvm);
++}
++#endif
++
++#ifdef __KVM_HAVE_ARCH_NONCOHERENT_DMA
++void kvm_arch_register_noncoherent_dma(struct kvm *kvm);
++void kvm_arch_unregister_noncoherent_dma(struct kvm *kvm);
++bool kvm_arch_has_noncoherent_dma(struct kvm *kvm);
++#else
++static inline void kvm_arch_register_noncoherent_dma(struct kvm *kvm)
++{
++}
++
++static inline void kvm_arch_unregister_noncoherent_dma(struct kvm *kvm)
++{
++}
++
++static inline bool kvm_arch_has_noncoherent_dma(struct kvm *kvm)
++{
++ return false;
++}
++#endif
++
++static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
++{
++#ifdef __KVM_HAVE_ARCH_WQP
++ return vcpu->arch.wqp;
++#else
++ return &vcpu->wq;
++#endif
++}
++
++int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
++void kvm_arch_destroy_vm(struct kvm *kvm);
++void kvm_arch_sync_events(struct kvm *kvm);
++
++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
++void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
++
++bool kvm_is_reserved_pfn(pfn_t pfn);
++
++struct kvm_irq_ack_notifier {
++ struct hlist_node link;
++ unsigned gsi;
++ void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
++};
++
++struct kvm_assigned_dev_kernel {
++ struct kvm_irq_ack_notifier ack_notifier;
++ struct list_head list;
++ int assigned_dev_id;
++ int host_segnr;
++ int host_busnr;
++ int host_devfn;
++ unsigned int entries_nr;
++ int host_irq;
++ bool host_irq_disabled;
++ bool pci_2_3;
++ struct msix_entry *host_msix_entries;
++ int guest_irq;
++ struct msix_entry *guest_msix_entries;
++ unsigned long irq_requested_type;
++ int irq_source_id;
++ int flags;
++ struct pci_dev *dev;
++ struct kvm *kvm;
++ spinlock_t intx_lock;
++ spinlock_t intx_mask_lock;
++ char irq_name[32];
++ struct pci_saved_state *pci_saved_state;
++};
++
++struct kvm_irq_mask_notifier {
++ void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked);
++ int irq;
++ struct hlist_node link;
++};
++
++void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq,
++ struct kvm_irq_mask_notifier *kimn);
++void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
++ struct kvm_irq_mask_notifier *kimn);
++void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
++ bool mask);
++
++int kvm_irq_map_gsi(struct kvm *kvm,
++ struct kvm_kernel_irq_routing_entry *entries, int gsi);
++int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin);
++
++int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
++ bool line_status);
++int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level);
++int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm,
++ int irq_source_id, int level, bool line_status);
++bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin);
++void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin);
++void kvm_register_irq_ack_notifier(struct kvm *kvm,
++ struct kvm_irq_ack_notifier *kian);
++void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
++ struct kvm_irq_ack_notifier *kian);
++int kvm_request_irq_source_id(struct kvm *kvm);
++void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
++
++#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
++int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
++void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
++int kvm_iommu_map_guest(struct kvm *kvm);
++int kvm_iommu_unmap_guest(struct kvm *kvm);
++int kvm_assign_device(struct kvm *kvm,
++ struct kvm_assigned_dev_kernel *assigned_dev);
++int kvm_deassign_device(struct kvm *kvm,
++ struct kvm_assigned_dev_kernel *assigned_dev);
++#else
++static inline int kvm_iommu_map_pages(struct kvm *kvm,
++ struct kvm_memory_slot *slot)
++{
++ return 0;
++}
++
++static inline void kvm_iommu_unmap_pages(struct kvm *kvm,
++ struct kvm_memory_slot *slot)
++{
++}
++
++static inline int kvm_iommu_unmap_guest(struct kvm *kvm)
++{
++ return 0;
++}
++#endif
++
++static inline void kvm_guest_enter(void)
++{
++ unsigned long flags;
++
++ BUG_ON(preemptible());
++
++ local_irq_save(flags);
++ guest_enter();
++ local_irq_restore(flags);
++
++ /* KVM does not hold any references to rcu protected data when it
++ * switches CPU into a guest mode. In fact switching to a guest mode
++ * is very similar to exiting to userspace from rcu point of view. In
++ * addition CPU may stay in a guest mode for quite a long time (up to
++ * one time slice). Lets treat guest mode as quiescent state, just like
++ * we do with user-mode execution.
++ */
++ rcu_virt_note_context_switch(smp_processor_id());
++}
++
++static inline void kvm_guest_exit(void)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ guest_exit();
++ local_irq_restore(flags);
++}
++
++/*
++ * search_memslots() and __gfn_to_memslot() are here because they are
++ * used in non-modular code in arch/powerpc/kvm/book3s_hv_rm_mmu.c.
++ * gfn_to_memslot() itself isn't here as an inline because that would
++ * bloat other code too much.
++ */
++static inline struct kvm_memory_slot *
++search_memslots(struct kvm_memslots *slots, gfn_t gfn)
++{
++ struct kvm_memory_slot *memslot;
++
++ kvm_for_each_memslot(memslot, slots)
++ if (gfn >= memslot->base_gfn &&
++ gfn < memslot->base_gfn + memslot->npages)
++ return memslot;
++
++ return NULL;
++}
++
++static inline struct kvm_memory_slot *
++__gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn)
++{
++ return search_memslots(slots, gfn);
++}
++
++static inline unsigned long
++__gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn)
++{
++ return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE;
++}
++
++static inline int memslot_id(struct kvm *kvm, gfn_t gfn)
++{
++ return gfn_to_memslot(kvm, gfn)->id;
++}
++
++static inline gfn_t
++hva_to_gfn_memslot(unsigned long hva, struct kvm_memory_slot *slot)
++{
++ gfn_t gfn_offset = (hva - slot->userspace_addr) >> PAGE_SHIFT;
++
++ return slot->base_gfn + gfn_offset;
++}
++
++static inline gpa_t gfn_to_gpa(gfn_t gfn)
++{
++ return (gpa_t)gfn << PAGE_SHIFT;
++}
++
++static inline gfn_t gpa_to_gfn(gpa_t gpa)
++{
++ return (gfn_t)(gpa >> PAGE_SHIFT);
++}
++
++static inline hpa_t pfn_to_hpa(pfn_t pfn)
++{
++ return (hpa_t)pfn << PAGE_SHIFT;
++}
++
++static inline bool kvm_is_error_gpa(struct kvm *kvm, gpa_t gpa)
++{
++ unsigned long hva = gfn_to_hva(kvm, gpa_to_gfn(gpa));
++
++ return kvm_is_error_hva(hva);
++}
++
++static inline void kvm_migrate_timers(struct kvm_vcpu *vcpu)
++{
++ set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests);
++}
++
++enum kvm_stat_kind {
++ KVM_STAT_VM,
++ KVM_STAT_VCPU,
++};
++
++struct kvm_stats_debugfs_item {
++ const char *name;
++ int offset;
++ enum kvm_stat_kind kind;
++ struct dentry *dentry;
++};
++extern struct kvm_stats_debugfs_item debugfs_entries[];
++extern struct dentry *kvm_debugfs_dir;
++
++#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
++static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
++{
++ if (unlikely(kvm->mmu_notifier_count))
++ return 1;
++ /*
++ * Ensure the read of mmu_notifier_count happens before the read
++ * of mmu_notifier_seq. This interacts with the smp_wmb() in
++ * mmu_notifier_invalidate_range_end to make sure that the caller
++ * either sees the old (non-zero) value of mmu_notifier_count or
++ * the new (incremented) value of mmu_notifier_seq.
++ * PowerPC Book3s HV KVM calls this under a per-page lock
++ * rather than under kvm->mmu_lock, for scalability, so
++ * can't rely on kvm->mmu_lock to keep things ordered.
++ */
++ smp_rmb();
++ if (kvm->mmu_notifier_seq != mmu_seq)
++ return 1;
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
++
++#ifdef CONFIG_S390
++#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
++#else
++#define KVM_MAX_IRQ_ROUTES 1024
++#endif
++
++int kvm_setup_default_irq_routing(struct kvm *kvm);
++int kvm_set_irq_routing(struct kvm *kvm,
++ const struct kvm_irq_routing_entry *entries,
++ unsigned nr,
++ unsigned flags);
++int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
++ const struct kvm_irq_routing_entry *ue);
++void kvm_free_irq_routing(struct kvm *kvm);
++
++#else
++
++static inline void kvm_free_irq_routing(struct kvm *kvm) {}
++
++#endif
++
++int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
++
++#ifdef CONFIG_HAVE_KVM_EVENTFD
++
++void kvm_eventfd_init(struct kvm *kvm);
++int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
++
++#ifdef CONFIG_HAVE_KVM_IRQFD
++int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
++void kvm_irqfd_release(struct kvm *kvm);
++void kvm_irq_routing_update(struct kvm *);
++#else
++static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
++{
++ return -EINVAL;
++}
++
++static inline void kvm_irqfd_release(struct kvm *kvm) {}
++#endif
++
++#else
++
++static inline void kvm_eventfd_init(struct kvm *kvm) {}
++
++static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
++{
++ return -EINVAL;
++}
++
++static inline void kvm_irqfd_release(struct kvm *kvm) {}
++
++#ifdef CONFIG_HAVE_KVM_IRQCHIP
++static inline void kvm_irq_routing_update(struct kvm *kvm)
++{
++}
++#endif
++
++static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
++{
++ return -ENOSYS;
++}
++
++#endif /* CONFIG_HAVE_KVM_EVENTFD */
++
++#ifdef CONFIG_KVM_APIC_ARCHITECTURE
++static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
++{
++ return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
++}
++
++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
++
++#else
++
++static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
++
++#endif
++
++#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
++
++long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
++ unsigned long arg);
++
++void kvm_free_all_assigned_devices(struct kvm *kvm);
++
++#else
++
++static inline long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
++ unsigned long arg)
++{
++ return -ENOTTY;
++}
++
++static inline void kvm_free_all_assigned_devices(struct kvm *kvm) {}
++
++#endif
++
++static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
++{
++ set_bit(req, &vcpu->requests);
++}
++
++static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
++{
++ if (test_bit(req, &vcpu->requests)) {
++ clear_bit(req, &vcpu->requests);
++ return true;
++ } else {
++ return false;
++ }
++}
++
++extern bool kvm_rebooting;
++
++struct kvm_device {
++ struct kvm_device_ops *ops;
++ struct kvm *kvm;
++ void *private;
++ struct list_head vm_node;
++};
++
++/* create, destroy, and name are mandatory */
++struct kvm_device_ops {
++ const char *name;
++ int (*create)(struct kvm_device *dev, u32 type);
++
++ /*
++ * Destroy is responsible for freeing dev.
++ *
++ * Destroy may be called before or after destructors are called
++ * on emulated I/O regions, depending on whether a reference is
++ * held by a vcpu or other kvm component that gets destroyed
++ * after the emulated I/O.
++ */
++ void (*destroy)(struct kvm_device *dev);
++
++ int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
++ int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
++ int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
++ long (*ioctl)(struct kvm_device *dev, unsigned int ioctl,
++ unsigned long arg);
++};
++
++void kvm_device_get(struct kvm_device *dev);
++void kvm_device_put(struct kvm_device *dev);
++struct kvm_device *kvm_device_from_filp(struct file *filp);
++int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type);
++void kvm_unregister_device_ops(u32 type);
++
++extern struct kvm_device_ops kvm_mpic_ops;
++extern struct kvm_device_ops kvm_xics_ops;
++
++#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
++
++static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val)
++{
++ vcpu->spin_loop.in_spin_loop = val;
++}
++static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
++{
++ vcpu->spin_loop.dy_eligible = val;
++}
++
++#else /* !CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
++
++static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val)
++{
++}
++
++static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
++{
++}
++#endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
++#endif
++
+diff -Nur linux-3.18.14.orig/include/linux/lglock.h linux-3.18.14-rt/include/linux/lglock.h
+--- linux-3.18.14.orig/include/linux/lglock.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/lglock.h 2015-05-31 15:32:48.261635369 -0500
@@ -34,22 +34,39 @@
#endif
@@ -8101,9 +12856,9 @@ diff -Nur linux-3.18.12.orig/include/linux/lglock.h linux-3.18.12/include/linux/
#else
/* When !CONFIG_SMP, map lglock to spinlock */
#define lglock spinlock
-diff -Nur linux-3.18.12.orig/include/linux/list_bl.h linux-3.18.12/include/linux/list_bl.h
---- linux-3.18.12.orig/include/linux/list_bl.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/list_bl.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/list_bl.h linux-3.18.14-rt/include/linux/list_bl.h
+--- linux-3.18.14.orig/include/linux/list_bl.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/list_bl.h 2015-05-31 15:32:48.265635369 -0500
@@ -2,6 +2,7 @@
#define _LINUX_LIST_BL_H
@@ -8164,9 +12919,9 @@ diff -Nur linux-3.18.12.orig/include/linux/list_bl.h linux-3.18.12/include/linux
}
static inline bool hlist_bl_is_locked(struct hlist_bl_head *b)
-diff -Nur linux-3.18.12.orig/include/linux/locallock.h linux-3.18.12/include/linux/locallock.h
---- linux-3.18.12.orig/include/linux/locallock.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/locallock.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/locallock.h linux-3.18.14-rt/include/linux/locallock.h
+--- linux-3.18.14.orig/include/linux/locallock.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/locallock.h 2015-05-31 15:32:48.273635368 -0500
@@ -0,0 +1,270 @@
+#ifndef _LINUX_LOCALLOCK_H
+#define _LINUX_LOCALLOCK_H
@@ -8438,9 +13193,9 @@ diff -Nur linux-3.18.12.orig/include/linux/locallock.h linux-3.18.12/include/lin
+#endif
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/mm_types.h linux-3.18.12/include/linux/mm_types.h
---- linux-3.18.12.orig/include/linux/mm_types.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/mm_types.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/mm_types.h linux-3.18.14-rt/include/linux/mm_types.h
+--- linux-3.18.14.orig/include/linux/mm_types.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/mm_types.h 2015-05-31 15:32:48.273635368 -0500
@@ -11,6 +11,7 @@
#include <linux/completion.h>
#include <linux/cpumask.h>
@@ -8459,9 +13214,9 @@ diff -Nur linux-3.18.12.orig/include/linux/mm_types.h linux-3.18.12/include/linu
};
static inline void mm_init_cpumask(struct mm_struct *mm)
-diff -Nur linux-3.18.12.orig/include/linux/mutex.h linux-3.18.12/include/linux/mutex.h
---- linux-3.18.12.orig/include/linux/mutex.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/mutex.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/mutex.h linux-3.18.14-rt/include/linux/mutex.h
+--- linux-3.18.14.orig/include/linux/mutex.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/mutex.h 2015-05-31 15:32:48.273635368 -0500
@@ -19,6 +19,17 @@
#include <asm/processor.h>
#include <linux/osq_lock.h>
@@ -8503,9 +13258,9 @@ diff -Nur linux-3.18.12.orig/include/linux/mutex.h linux-3.18.12/include/linux/m
extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
#endif /* __LINUX_MUTEX_H */
-diff -Nur linux-3.18.12.orig/include/linux/mutex_rt.h linux-3.18.12/include/linux/mutex_rt.h
---- linux-3.18.12.orig/include/linux/mutex_rt.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/mutex_rt.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/mutex_rt.h linux-3.18.14-rt/include/linux/mutex_rt.h
+--- linux-3.18.14.orig/include/linux/mutex_rt.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/mutex_rt.h 2015-05-31 15:32:48.273635368 -0500
@@ -0,0 +1,84 @@
+#ifndef __LINUX_MUTEX_RT_H
+#define __LINUX_MUTEX_RT_H
@@ -8591,10 +13346,10 @@ diff -Nur linux-3.18.12.orig/include/linux/mutex_rt.h linux-3.18.12/include/linu
+} while (0)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/netdevice.h linux-3.18.12/include/linux/netdevice.h
---- linux-3.18.12.orig/include/linux/netdevice.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/netdevice.h 2015-04-26 13:32:22.419684003 -0500
-@@ -2345,6 +2345,7 @@
+diff -Nur linux-3.18.14.orig/include/linux/netdevice.h linux-3.18.14-rt/include/linux/netdevice.h
+--- linux-3.18.14.orig/include/linux/netdevice.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/netdevice.h 2015-05-31 15:32:48.305635368 -0500
+@@ -2351,6 +2351,7 @@
unsigned int dropped;
struct sk_buff_head input_pkt_queue;
struct napi_struct backlog;
@@ -8602,9 +13357,9 @@ diff -Nur linux-3.18.12.orig/include/linux/netdevice.h linux-3.18.12/include/lin
#ifdef CONFIG_NET_FLOW_LIMIT
struct sd_flow_limit __rcu *flow_limit;
-diff -Nur linux-3.18.12.orig/include/linux/netfilter/x_tables.h linux-3.18.12/include/linux/netfilter/x_tables.h
---- linux-3.18.12.orig/include/linux/netfilter/x_tables.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/netfilter/x_tables.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/netfilter/x_tables.h linux-3.18.14-rt/include/linux/netfilter/x_tables.h
+--- linux-3.18.14.orig/include/linux/netfilter/x_tables.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/netfilter/x_tables.h 2015-05-31 15:32:48.305635368 -0500
@@ -3,6 +3,7 @@
@@ -8640,9 +13395,9 @@ diff -Nur linux-3.18.12.orig/include/linux/netfilter/x_tables.h linux-3.18.12/in
}
/*
-diff -Nur linux-3.18.12.orig/include/linux/notifier.h linux-3.18.12/include/linux/notifier.h
---- linux-3.18.12.orig/include/linux/notifier.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/notifier.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/notifier.h linux-3.18.14-rt/include/linux/notifier.h
+--- linux-3.18.14.orig/include/linux/notifier.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/notifier.h 2015-05-31 15:32:48.305635368 -0500
@@ -6,7 +6,7 @@
*
* Alan Cox <Alan.Cox@linux.org>
@@ -8722,9 +13477,9 @@ diff -Nur linux-3.18.12.orig/include/linux/notifier.h linux-3.18.12/include/linu
/* CPU notfiers are defined in include/linux/cpu.h. */
/* netdevice notifiers are defined in include/linux/netdevice.h */
-diff -Nur linux-3.18.12.orig/include/linux/percpu.h linux-3.18.12/include/linux/percpu.h
---- linux-3.18.12.orig/include/linux/percpu.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/percpu.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/percpu.h linux-3.18.14-rt/include/linux/percpu.h
+--- linux-3.18.14.orig/include/linux/percpu.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/percpu.h 2015-05-31 15:32:48.305635368 -0500
@@ -23,6 +23,35 @@
PERCPU_MODULE_RESERVE)
#endif
@@ -8761,9 +13516,9 @@ diff -Nur linux-3.18.12.orig/include/linux/percpu.h linux-3.18.12/include/linux/
/* minimum unit size, also is the maximum supported allocation size */
#define PCPU_MIN_UNIT_SIZE PFN_ALIGN(32 << 10)
-diff -Nur linux-3.18.12.orig/include/linux/pid.h linux-3.18.12/include/linux/pid.h
---- linux-3.18.12.orig/include/linux/pid.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/pid.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/pid.h linux-3.18.14-rt/include/linux/pid.h
+--- linux-3.18.14.orig/include/linux/pid.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/pid.h 2015-05-31 15:32:48.341635368 -0500
@@ -2,6 +2,7 @@
#define _LINUX_PID_H
@@ -8772,9 +13527,9 @@ diff -Nur linux-3.18.12.orig/include/linux/pid.h linux-3.18.12/include/linux/pid
enum pid_type
{
-diff -Nur linux-3.18.12.orig/include/linux/preempt.h linux-3.18.12/include/linux/preempt.h
---- linux-3.18.12.orig/include/linux/preempt.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/preempt.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/preempt.h linux-3.18.14-rt/include/linux/preempt.h
+--- linux-3.18.14.orig/include/linux/preempt.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/preempt.h 2015-05-31 15:32:48.341635368 -0500
@@ -33,6 +33,20 @@
#define preempt_count_inc() preempt_count_add(1)
#define preempt_count_dec() preempt_count_sub(1)
@@ -8878,9 +13633,9 @@ diff -Nur linux-3.18.12.orig/include/linux/preempt.h linux-3.18.12/include/linux
#ifdef CONFIG_PREEMPT_NOTIFIERS
struct preempt_notifier;
-diff -Nur linux-3.18.12.orig/include/linux/preempt_mask.h linux-3.18.12/include/linux/preempt_mask.h
---- linux-3.18.12.orig/include/linux/preempt_mask.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/preempt_mask.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/preempt_mask.h linux-3.18.14-rt/include/linux/preempt_mask.h
+--- linux-3.18.14.orig/include/linux/preempt_mask.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/preempt_mask.h 2015-05-31 15:32:48.341635368 -0500
@@ -44,16 +44,26 @@
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
#define NMI_OFFSET (1UL << NMI_SHIFT)
@@ -8918,9 +13673,9 @@ diff -Nur linux-3.18.12.orig/include/linux/preempt_mask.h linux-3.18.12/include/
/*
* Are we in NMI context?
-diff -Nur linux-3.18.12.orig/include/linux/printk.h linux-3.18.12/include/linux/printk.h
---- linux-3.18.12.orig/include/linux/printk.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/printk.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/printk.h linux-3.18.14-rt/include/linux/printk.h
+--- linux-3.18.14.orig/include/linux/printk.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/printk.h 2015-05-31 15:32:48.341635368 -0500
@@ -119,9 +119,11 @@
extern asmlinkage __printf(1, 2)
void early_printk(const char *fmt, ...);
@@ -8941,9 +13696,9 @@ diff -Nur linux-3.18.12.orig/include/linux/printk.h linux-3.18.12/include/linux/
extern int printk_delay_msec;
extern int dmesg_restrict;
extern int kptr_restrict;
-diff -Nur linux-3.18.12.orig/include/linux/radix-tree.h linux-3.18.12/include/linux/radix-tree.h
---- linux-3.18.12.orig/include/linux/radix-tree.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/radix-tree.h 2015-04-26 13:32:22.419684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/radix-tree.h linux-3.18.14-rt/include/linux/radix-tree.h
+--- linux-3.18.14.orig/include/linux/radix-tree.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/radix-tree.h 2015-05-31 15:32:48.341635368 -0500
@@ -277,8 +277,13 @@
unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root,
void ***results, unsigned long *indices,
@@ -8967,9 +13722,9 @@ diff -Nur linux-3.18.12.orig/include/linux/radix-tree.h linux-3.18.12/include/li
}
/**
-diff -Nur linux-3.18.12.orig/include/linux/random.h linux-3.18.12/include/linux/random.h
---- linux-3.18.12.orig/include/linux/random.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/random.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/random.h linux-3.18.14-rt/include/linux/random.h
+--- linux-3.18.14.orig/include/linux/random.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/random.h 2015-05-31 15:32:48.341635368 -0500
@@ -11,7 +11,7 @@
extern void add_device_randomness(const void *, unsigned int);
extern void add_input_randomness(unsigned int type, unsigned int code,
@@ -8979,9 +13734,9 @@ diff -Nur linux-3.18.12.orig/include/linux/random.h linux-3.18.12/include/linux/
extern void get_random_bytes(void *buf, int nbytes);
extern void get_random_bytes_arch(void *buf, int nbytes);
-diff -Nur linux-3.18.12.orig/include/linux/rcupdate.h linux-3.18.12/include/linux/rcupdate.h
---- linux-3.18.12.orig/include/linux/rcupdate.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/rcupdate.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rcupdate.h linux-3.18.14-rt/include/linux/rcupdate.h
+--- linux-3.18.14.orig/include/linux/rcupdate.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/rcupdate.h 2015-05-31 15:32:48.341635368 -0500
@@ -147,6 +147,9 @@
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
@@ -9066,9 +13821,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rcupdate.h linux-3.18.12/include/linu
local_bh_enable();
}
-diff -Nur linux-3.18.12.orig/include/linux/rcutree.h linux-3.18.12/include/linux/rcutree.h
---- linux-3.18.12.orig/include/linux/rcutree.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/rcutree.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rcutree.h linux-3.18.14-rt/include/linux/rcutree.h
+--- linux-3.18.14.orig/include/linux/rcutree.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/rcutree.h 2015-05-31 15:32:48.361635367 -0500
@@ -46,7 +46,11 @@
rcu_note_context_switch(cpu);
}
@@ -9119,9 +13874,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rcutree.h linux-3.18.12/include/linux
+#endif
+
#endif /* __LINUX_RCUTREE_H */
-diff -Nur linux-3.18.12.orig/include/linux/rtmutex.h linux-3.18.12/include/linux/rtmutex.h
---- linux-3.18.12.orig/include/linux/rtmutex.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/rtmutex.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rtmutex.h linux-3.18.14-rt/include/linux/rtmutex.h
+--- linux-3.18.14.orig/include/linux/rtmutex.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/rtmutex.h 2015-05-31 15:32:48.377635367 -0500
@@ -14,10 +14,14 @@
#include <linux/linkage.h>
@@ -9195,9 +13950,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rtmutex.h linux-3.18.12/include/linux
extern int rt_mutex_timed_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *timeout);
-diff -Nur linux-3.18.12.orig/include/linux/rwlock_rt.h linux-3.18.12/include/linux/rwlock_rt.h
---- linux-3.18.12.orig/include/linux/rwlock_rt.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/rwlock_rt.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rwlock_rt.h linux-3.18.14-rt/include/linux/rwlock_rt.h
+--- linux-3.18.14.orig/include/linux/rwlock_rt.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/rwlock_rt.h 2015-05-31 15:32:48.377635367 -0500
@@ -0,0 +1,99 @@
+#ifndef __LINUX_RWLOCK_RT_H
+#define __LINUX_RWLOCK_RT_H
@@ -9298,9 +14053,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwlock_rt.h linux-3.18.12/include/lin
+ } while (0)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/rwlock_types.h linux-3.18.12/include/linux/rwlock_types.h
---- linux-3.18.12.orig/include/linux/rwlock_types.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/rwlock_types.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rwlock_types.h linux-3.18.14-rt/include/linux/rwlock_types.h
+--- linux-3.18.14.orig/include/linux/rwlock_types.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/rwlock_types.h 2015-05-31 15:32:48.377635367 -0500
@@ -1,6 +1,10 @@
#ifndef __LINUX_RWLOCK_TYPES_H
#define __LINUX_RWLOCK_TYPES_H
@@ -9321,9 +14076,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwlock_types.h linux-3.18.12/include/
+ rwlock_t name __cacheline_aligned_in_smp = __RW_LOCK_UNLOCKED(name)
#endif /* __LINUX_RWLOCK_TYPES_H */
-diff -Nur linux-3.18.12.orig/include/linux/rwlock_types_rt.h linux-3.18.12/include/linux/rwlock_types_rt.h
---- linux-3.18.12.orig/include/linux/rwlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/rwlock_types_rt.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rwlock_types_rt.h linux-3.18.14-rt/include/linux/rwlock_types_rt.h
+--- linux-3.18.14.orig/include/linux/rwlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/rwlock_types_rt.h 2015-05-31 15:32:48.377635367 -0500
@@ -0,0 +1,33 @@
+#ifndef __LINUX_RWLOCK_TYPES_RT_H
+#define __LINUX_RWLOCK_TYPES_RT_H
@@ -9358,9 +14113,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwlock_types_rt.h linux-3.18.12/inclu
+ rwlock_t name __cacheline_aligned_in_smp = __RW_LOCK_UNLOCKED(name)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/rwsem.h linux-3.18.12/include/linux/rwsem.h
---- linux-3.18.12.orig/include/linux/rwsem.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/rwsem.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rwsem.h linux-3.18.14-rt/include/linux/rwsem.h
+--- linux-3.18.14.orig/include/linux/rwsem.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/rwsem.h 2015-05-31 15:32:48.377635367 -0500
@@ -18,6 +18,10 @@
#include <linux/osq_lock.h>
#endif
@@ -9379,9 +14134,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwsem.h linux-3.18.12/include/linux/r
+#endif /* !PREEMPT_RT_FULL */
+
#endif /* _LINUX_RWSEM_H */
-diff -Nur linux-3.18.12.orig/include/linux/rwsem_rt.h linux-3.18.12/include/linux/rwsem_rt.h
---- linux-3.18.12.orig/include/linux/rwsem_rt.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/rwsem_rt.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/rwsem_rt.h linux-3.18.14-rt/include/linux/rwsem_rt.h
+--- linux-3.18.14.orig/include/linux/rwsem_rt.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/rwsem_rt.h 2015-05-31 15:32:48.377635367 -0500
@@ -0,0 +1,134 @@
+#ifndef _LINUX_RWSEM_RT_H
+#define _LINUX_RWSEM_RT_H
@@ -9517,9 +14272,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwsem_rt.h linux-3.18.12/include/linu
+}
+#endif
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/sched.h linux-3.18.12/include/linux/sched.h
---- linux-3.18.12.orig/include/linux/sched.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/sched.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/sched.h linux-3.18.14-rt/include/linux/sched.h
+--- linux-3.18.14.orig/include/linux/sched.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/sched.h 2015-05-31 15:32:48.381635367 -0500
@@ -26,6 +26,7 @@
#include <linux/nodemask.h>
#include <linux/mm_types.h>
@@ -9903,9 +14658,9 @@ diff -Nur linux-3.18.12.orig/include/linux/sched.h linux-3.18.12/include/linux/s
extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
-diff -Nur linux-3.18.12.orig/include/linux/seqlock.h linux-3.18.12/include/linux/seqlock.h
---- linux-3.18.12.orig/include/linux/seqlock.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/seqlock.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/seqlock.h linux-3.18.14-rt/include/linux/seqlock.h
+--- linux-3.18.14.orig/include/linux/seqlock.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/seqlock.h 2015-05-31 15:32:48.381635367 -0500
@@ -219,20 +219,30 @@
return __read_seqcount_retry(s, start);
}
@@ -10035,9 +14790,9 @@ diff -Nur linux-3.18.12.orig/include/linux/seqlock.h linux-3.18.12/include/linux
spin_unlock_irqrestore(&sl->lock, flags);
}
-diff -Nur linux-3.18.12.orig/include/linux/signal.h linux-3.18.12/include/linux/signal.h
---- linux-3.18.12.orig/include/linux/signal.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/signal.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/signal.h linux-3.18.14-rt/include/linux/signal.h
+--- linux-3.18.14.orig/include/linux/signal.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/signal.h 2015-05-31 15:32:48.381635367 -0500
@@ -218,6 +218,7 @@
}
@@ -10046,9 +14801,9 @@ diff -Nur linux-3.18.12.orig/include/linux/signal.h linux-3.18.12/include/linux/
/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */
static inline int valid_signal(unsigned long sig)
-diff -Nur linux-3.18.12.orig/include/linux/skbuff.h linux-3.18.12/include/linux/skbuff.h
---- linux-3.18.12.orig/include/linux/skbuff.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/skbuff.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/skbuff.h linux-3.18.14-rt/include/linux/skbuff.h
+--- linux-3.18.14.orig/include/linux/skbuff.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/skbuff.h 2015-05-31 15:32:48.405635367 -0500
@@ -172,6 +172,7 @@
__u32 qlen;
@@ -10057,7 +14812,7 @@ diff -Nur linux-3.18.12.orig/include/linux/skbuff.h linux-3.18.12/include/linux/
};
struct sk_buff;
-@@ -1327,6 +1328,12 @@
+@@ -1328,6 +1329,12 @@
__skb_queue_head_init(list);
}
@@ -10070,9 +14825,3377 @@ diff -Nur linux-3.18.12.orig/include/linux/skbuff.h linux-3.18.12/include/linux/
static inline void skb_queue_head_init_class(struct sk_buff_head *list,
struct lock_class_key *class)
{
-diff -Nur linux-3.18.12.orig/include/linux/smp.h linux-3.18.12/include/linux/smp.h
---- linux-3.18.12.orig/include/linux/smp.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/smp.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/skbuff.h.orig linux-3.18.14-rt/include/linux/skbuff.h.orig
+--- linux-3.18.14.orig/include/linux/skbuff.h.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/skbuff.h.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,3364 @@
++/*
++ * Definitions for the 'struct sk_buff' memory handlers.
++ *
++ * Authors:
++ * Alan Cox, <gw4pts@gw4pts.ampr.org>
++ * Florian La Roche, <rzsfl@rz.uni-sb.de>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifndef _LINUX_SKBUFF_H
++#define _LINUX_SKBUFF_H
++
++#include <linux/kernel.h>
++#include <linux/kmemcheck.h>
++#include <linux/compiler.h>
++#include <linux/time.h>
++#include <linux/bug.h>
++#include <linux/cache.h>
++
++#include <linux/atomic.h>
++#include <asm/types.h>
++#include <linux/spinlock.h>
++#include <linux/net.h>
++#include <linux/textsearch.h>
++#include <net/checksum.h>
++#include <linux/rcupdate.h>
++#include <linux/hrtimer.h>
++#include <linux/dma-mapping.h>
++#include <linux/netdev_features.h>
++#include <linux/sched.h>
++#include <net/flow_keys.h>
++
++/* A. Checksumming of received packets by device.
++ *
++ * CHECKSUM_NONE:
++ *
++ * Device failed to checksum this packet e.g. due to lack of capabilities.
++ * The packet contains full (though not verified) checksum in packet but
++ * not in skb->csum. Thus, skb->csum is undefined in this case.
++ *
++ * CHECKSUM_UNNECESSARY:
++ *
++ * The hardware you're dealing with doesn't calculate the full checksum
++ * (as in CHECKSUM_COMPLETE), but it does parse headers and verify checksums
++ * for specific protocols. For such packets it will set CHECKSUM_UNNECESSARY
++ * if their checksums are okay. skb->csum is still undefined in this case
++ * though. It is a bad option, but, unfortunately, nowadays most vendors do
++ * this. Apparently with the secret goal to sell you new devices, when you
++ * will add new protocol to your host, f.e. IPv6 8)
++ *
++ * CHECKSUM_UNNECESSARY is applicable to following protocols:
++ * TCP: IPv6 and IPv4.
++ * UDP: IPv4 and IPv6. A device may apply CHECKSUM_UNNECESSARY to a
++ * zero UDP checksum for either IPv4 or IPv6, the networking stack
++ * may perform further validation in this case.
++ * GRE: only if the checksum is present in the header.
++ * SCTP: indicates the CRC in SCTP header has been validated.
++ *
++ * skb->csum_level indicates the number of consecutive checksums found in
++ * the packet minus one that have been verified as CHECKSUM_UNNECESSARY.
++ * For instance if a device receives an IPv6->UDP->GRE->IPv4->TCP packet
++ * and a device is able to verify the checksums for UDP (possibly zero),
++ * GRE (checksum flag is set), and TCP-- skb->csum_level would be set to
++ * two. If the device were only able to verify the UDP checksum and not
++ * GRE, either because it doesn't support GRE checksum of because GRE
++ * checksum is bad, skb->csum_level would be set to zero (TCP checksum is
++ * not considered in this case).
++ *
++ * CHECKSUM_COMPLETE:
++ *
++ * This is the most generic way. The device supplied checksum of the _whole_
++ * packet as seen by netif_rx() and fills out in skb->csum. Meaning, the
++ * hardware doesn't need to parse L3/L4 headers to implement this.
++ *
++ * Note: Even if device supports only some protocols, but is able to produce
++ * skb->csum, it MUST use CHECKSUM_COMPLETE, not CHECKSUM_UNNECESSARY.
++ *
++ * CHECKSUM_PARTIAL:
++ *
++ * This is identical to the case for output below. This may occur on a packet
++ * received directly from another Linux OS, e.g., a virtualized Linux kernel
++ * on the same host. The packet can be treated in the same way as
++ * CHECKSUM_UNNECESSARY, except that on output (i.e., forwarding) the
++ * checksum must be filled in by the OS or the hardware.
++ *
++ * B. Checksumming on output.
++ *
++ * CHECKSUM_NONE:
++ *
++ * The skb was already checksummed by the protocol, or a checksum is not
++ * required.
++ *
++ * CHECKSUM_PARTIAL:
++ *
++ * The device is required to checksum the packet as seen by hard_start_xmit()
++ * from skb->csum_start up to the end, and to record/write the checksum at
++ * offset skb->csum_start + skb->csum_offset.
++ *
++ * The device must show its capabilities in dev->features, set up at device
++ * setup time, e.g. netdev_features.h:
++ *
++ * NETIF_F_HW_CSUM - It's a clever device, it's able to checksum everything.
++ * NETIF_F_IP_CSUM - Device is dumb, it's able to checksum only TCP/UDP over
++ * IPv4. Sigh. Vendors like this way for an unknown reason.
++ * Though, see comment above about CHECKSUM_UNNECESSARY. 8)
++ * NETIF_F_IPV6_CSUM - About as dumb as the last one but does IPv6 instead.
++ * NETIF_F_... - Well, you get the picture.
++ *
++ * CHECKSUM_UNNECESSARY:
++ *
++ * Normally, the device will do per protocol specific checksumming. Protocol
++ * implementations that do not want the NIC to perform the checksum
++ * calculation should use this flag in their outgoing skbs.
++ *
++ * NETIF_F_FCOE_CRC - This indicates that the device can do FCoE FC CRC
++ * offload. Correspondingly, the FCoE protocol driver
++ * stack should use CHECKSUM_UNNECESSARY.
++ *
++ * Any questions? No questions, good. --ANK
++ */
++
++/* Don't change this without changing skb_csum_unnecessary! */
++#define CHECKSUM_NONE 0
++#define CHECKSUM_UNNECESSARY 1
++#define CHECKSUM_COMPLETE 2
++#define CHECKSUM_PARTIAL 3
++
++/* Maximum value in skb->csum_level */
++#define SKB_MAX_CSUM_LEVEL 3
++
++#define SKB_DATA_ALIGN(X) ALIGN(X, SMP_CACHE_BYTES)
++#define SKB_WITH_OVERHEAD(X) \
++ ((X) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
++#define SKB_MAX_ORDER(X, ORDER) \
++ SKB_WITH_OVERHEAD((PAGE_SIZE << (ORDER)) - (X))
++#define SKB_MAX_HEAD(X) (SKB_MAX_ORDER((X), 0))
++#define SKB_MAX_ALLOC (SKB_MAX_ORDER(0, 2))
++
++/* return minimum truesize of one skb containing X bytes of data */
++#define SKB_TRUESIZE(X) ((X) + \
++ SKB_DATA_ALIGN(sizeof(struct sk_buff)) + \
++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
++
++struct net_device;
++struct scatterlist;
++struct pipe_inode_info;
++
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++struct nf_conntrack {
++ atomic_t use;
++};
++#endif
++
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++struct nf_bridge_info {
++ atomic_t use;
++ unsigned int mask;
++ struct net_device *physindev;
++ struct net_device *physoutdev;
++ unsigned long data[32 / sizeof(unsigned long)];
++};
++#endif
++
++struct sk_buff_head {
++ /* These two members must be first. */
++ struct sk_buff *next;
++ struct sk_buff *prev;
++
++ __u32 qlen;
++ spinlock_t lock;
++};
++
++struct sk_buff;
++
++/* To allow 64K frame to be packed as single skb without frag_list we
++ * require 64K/PAGE_SIZE pages plus 1 additional page to allow for
++ * buffers which do not start on a page boundary.
++ *
++ * Since GRO uses frags we allocate at least 16 regardless of page
++ * size.
++ */
++#if (65536/PAGE_SIZE + 1) < 16
++#define MAX_SKB_FRAGS 16UL
++#else
++#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1)
++#endif
++
++typedef struct skb_frag_struct skb_frag_t;
++
++struct skb_frag_struct {
++ struct {
++ struct page *p;
++ } page;
++#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
++ __u32 page_offset;
++ __u32 size;
++#else
++ __u16 page_offset;
++ __u16 size;
++#endif
++};
++
++static inline unsigned int skb_frag_size(const skb_frag_t *frag)
++{
++ return frag->size;
++}
++
++static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size)
++{
++ frag->size = size;
++}
++
++static inline void skb_frag_size_add(skb_frag_t *frag, int delta)
++{
++ frag->size += delta;
++}
++
++static inline void skb_frag_size_sub(skb_frag_t *frag, int delta)
++{
++ frag->size -= delta;
++}
++
++#define HAVE_HW_TIME_STAMP
++
++/**
++ * struct skb_shared_hwtstamps - hardware time stamps
++ * @hwtstamp: hardware time stamp transformed into duration
++ * since arbitrary point in time
++ *
++ * Software time stamps generated by ktime_get_real() are stored in
++ * skb->tstamp.
++ *
++ * hwtstamps can only be compared against other hwtstamps from
++ * the same device.
++ *
++ * This structure is attached to packets as part of the
++ * &skb_shared_info. Use skb_hwtstamps() to get a pointer.
++ */
++struct skb_shared_hwtstamps {
++ ktime_t hwtstamp;
++};
++
++/* Definitions for tx_flags in struct skb_shared_info */
++enum {
++ /* generate hardware time stamp */
++ SKBTX_HW_TSTAMP = 1 << 0,
++
++ /* generate software time stamp when queueing packet to NIC */
++ SKBTX_SW_TSTAMP = 1 << 1,
++
++ /* device driver is going to provide hardware time stamp */
++ SKBTX_IN_PROGRESS = 1 << 2,
++
++ /* device driver supports TX zero-copy buffers */
++ SKBTX_DEV_ZEROCOPY = 1 << 3,
++
++ /* generate wifi status information (where possible) */
++ SKBTX_WIFI_STATUS = 1 << 4,
++
++ /* This indicates at least one fragment might be overwritten
++ * (as in vmsplice(), sendfile() ...)
++ * If we need to compute a TX checksum, we'll need to copy
++ * all frags to avoid possible bad checksum
++ */
++ SKBTX_SHARED_FRAG = 1 << 5,
++
++ /* generate software time stamp when entering packet scheduling */
++ SKBTX_SCHED_TSTAMP = 1 << 6,
++
++ /* generate software timestamp on peer data acknowledgment */
++ SKBTX_ACK_TSTAMP = 1 << 7,
++};
++
++#define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \
++ SKBTX_SCHED_TSTAMP | \
++ SKBTX_ACK_TSTAMP)
++#define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | SKBTX_ANY_SW_TSTAMP)
++
++/*
++ * The callback notifies userspace to release buffers when skb DMA is done in
++ * lower device, the skb last reference should be 0 when calling this.
++ * The zerocopy_success argument is true if zero copy transmit occurred,
++ * false on data copy or out of memory error caused by data copy attempt.
++ * The ctx field is used to track device context.
++ * The desc field is used to track userspace buffer index.
++ */
++struct ubuf_info {
++ void (*callback)(struct ubuf_info *, bool zerocopy_success);
++ void *ctx;
++ unsigned long desc;
++};
++
++/* This data is invariant across clones and lives at
++ * the end of the header data, ie. at skb->end.
++ */
++struct skb_shared_info {
++ unsigned char nr_frags;
++ __u8 tx_flags;
++ unsigned short gso_size;
++ /* Warning: this field is not always filled in (UFO)! */
++ unsigned short gso_segs;
++ unsigned short gso_type;
++ struct sk_buff *frag_list;
++ struct skb_shared_hwtstamps hwtstamps;
++ u32 tskey;
++ __be32 ip6_frag_id;
++
++ /*
++ * Warning : all fields before dataref are cleared in __alloc_skb()
++ */
++ atomic_t dataref;
++
++ /* Intermediate layers must ensure that destructor_arg
++ * remains valid until skb destructor */
++ void * destructor_arg;
++
++ /* must be last field, see pskb_expand_head() */
++ skb_frag_t frags[MAX_SKB_FRAGS];
++};
++
++/* We divide dataref into two halves. The higher 16 bits hold references
++ * to the payload part of skb->data. The lower 16 bits hold references to
++ * the entire skb->data. A clone of a headerless skb holds the length of
++ * the header in skb->hdr_len.
++ *
++ * All users must obey the rule that the skb->data reference count must be
++ * greater than or equal to the payload reference count.
++ *
++ * Holding a reference to the payload part means that the user does not
++ * care about modifications to the header part of skb->data.
++ */
++#define SKB_DATAREF_SHIFT 16
++#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
++
++
++enum {
++ SKB_FCLONE_UNAVAILABLE, /* skb has no fclone (from head_cache) */
++ SKB_FCLONE_ORIG, /* orig skb (from fclone_cache) */
++ SKB_FCLONE_CLONE, /* companion fclone skb (from fclone_cache) */
++ SKB_FCLONE_FREE, /* this companion fclone skb is available */
++};
++
++enum {
++ SKB_GSO_TCPV4 = 1 << 0,
++ SKB_GSO_UDP = 1 << 1,
++
++ /* This indicates the skb is from an untrusted source. */
++ SKB_GSO_DODGY = 1 << 2,
++
++ /* This indicates the tcp segment has CWR set. */
++ SKB_GSO_TCP_ECN = 1 << 3,
++
++ SKB_GSO_TCPV6 = 1 << 4,
++
++ SKB_GSO_FCOE = 1 << 5,
++
++ SKB_GSO_GRE = 1 << 6,
++
++ SKB_GSO_GRE_CSUM = 1 << 7,
++
++ SKB_GSO_IPIP = 1 << 8,
++
++ SKB_GSO_SIT = 1 << 9,
++
++ SKB_GSO_UDP_TUNNEL = 1 << 10,
++
++ SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
++
++ SKB_GSO_MPLS = 1 << 12,
++
++};
++
++#if BITS_PER_LONG > 32
++#define NET_SKBUFF_DATA_USES_OFFSET 1
++#endif
++
++#ifdef NET_SKBUFF_DATA_USES_OFFSET
++typedef unsigned int sk_buff_data_t;
++#else
++typedef unsigned char *sk_buff_data_t;
++#endif
++
++/**
++ * struct skb_mstamp - multi resolution time stamps
++ * @stamp_us: timestamp in us resolution
++ * @stamp_jiffies: timestamp in jiffies
++ */
++struct skb_mstamp {
++ union {
++ u64 v64;
++ struct {
++ u32 stamp_us;
++ u32 stamp_jiffies;
++ };
++ };
++};
++
++/**
++ * skb_mstamp_get - get current timestamp
++ * @cl: place to store timestamps
++ */
++static inline void skb_mstamp_get(struct skb_mstamp *cl)
++{
++ u64 val = local_clock();
++
++ do_div(val, NSEC_PER_USEC);
++ cl->stamp_us = (u32)val;
++ cl->stamp_jiffies = (u32)jiffies;
++}
++
++/**
++ * skb_mstamp_delta - compute the difference in usec between two skb_mstamp
++ * @t1: pointer to newest sample
++ * @t0: pointer to oldest sample
++ */
++static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1,
++ const struct skb_mstamp *t0)
++{
++ s32 delta_us = t1->stamp_us - t0->stamp_us;
++ u32 delta_jiffies = t1->stamp_jiffies - t0->stamp_jiffies;
++
++ /* If delta_us is negative, this might be because interval is too big,
++ * or local_clock() drift is too big : fallback using jiffies.
++ */
++ if (delta_us <= 0 ||
++ delta_jiffies >= (INT_MAX / (USEC_PER_SEC / HZ)))
++
++ delta_us = jiffies_to_usecs(delta_jiffies);
++
++ return delta_us;
++}
++
++
++/**
++ * struct sk_buff - socket buffer
++ * @next: Next buffer in list
++ * @prev: Previous buffer in list
++ * @tstamp: Time we arrived/left
++ * @sk: Socket we are owned by
++ * @dev: Device we arrived on/are leaving by
++ * @cb: Control buffer. Free for use by every layer. Put private vars here
++ * @_skb_refdst: destination entry (with norefcount bit)
++ * @sp: the security path, used for xfrm
++ * @len: Length of actual data
++ * @data_len: Data length
++ * @mac_len: Length of link layer header
++ * @hdr_len: writable header length of cloned skb
++ * @csum: Checksum (must include start/offset pair)
++ * @csum_start: Offset from skb->head where checksumming should start
++ * @csum_offset: Offset from csum_start where checksum should be stored
++ * @priority: Packet queueing priority
++ * @ignore_df: allow local fragmentation
++ * @cloned: Head may be cloned (check refcnt to be sure)
++ * @ip_summed: Driver fed us an IP checksum
++ * @nohdr: Payload reference only, must not modify header
++ * @nfctinfo: Relationship of this skb to the connection
++ * @pkt_type: Packet class
++ * @fclone: skbuff clone status
++ * @ipvs_property: skbuff is owned by ipvs
++ * @peeked: this packet has been seen already, so stats have been
++ * done for it, don't do them again
++ * @nf_trace: netfilter packet trace flag
++ * @protocol: Packet protocol from driver
++ * @destructor: Destruct function
++ * @nfct: Associated connection, if any
++ * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
++ * @skb_iif: ifindex of device we arrived on
++ * @tc_index: Traffic control index
++ * @tc_verd: traffic control verdict
++ * @hash: the packet hash
++ * @queue_mapping: Queue mapping for multiqueue devices
++ * @xmit_more: More SKBs are pending for this queue
++ * @ndisc_nodetype: router type (from link layer)
++ * @ooo_okay: allow the mapping of a socket to a queue to be changed
++ * @l4_hash: indicate hash is a canonical 4-tuple hash over transport
++ * ports.
++ * @sw_hash: indicates hash was computed in software stack
++ * @wifi_acked_valid: wifi_acked was set
++ * @wifi_acked: whether frame was acked on wifi or not
++ * @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS
++ * @napi_id: id of the NAPI struct this skb came from
++ * @secmark: security marking
++ * @mark: Generic packet mark
++ * @dropcount: total number of sk_receive_queue overflows
++ * @vlan_proto: vlan encapsulation protocol
++ * @vlan_tci: vlan tag control information
++ * @inner_protocol: Protocol (encapsulation)
++ * @inner_transport_header: Inner transport layer header (encapsulation)
++ * @inner_network_header: Network layer header (encapsulation)
++ * @inner_mac_header: Link layer header (encapsulation)
++ * @transport_header: Transport layer header
++ * @network_header: Network layer header
++ * @mac_header: Link layer header
++ * @tail: Tail pointer
++ * @end: End pointer
++ * @head: Head of buffer
++ * @data: Data head pointer
++ * @truesize: Buffer size
++ * @users: User count - see {datagram,tcp}.c
++ */
++
++struct sk_buff {
++ /* These two members must be first. */
++ struct sk_buff *next;
++ struct sk_buff *prev;
++
++ union {
++ ktime_t tstamp;
++ struct skb_mstamp skb_mstamp;
++ };
++
++ struct sock *sk;
++ struct net_device *dev;
++
++ /*
++ * This is the control buffer. It is free to use for every
++ * layer. Please put your private variables there. If you
++ * want to keep them across layers you have to do a skb_clone()
++ * first. This is owned by whoever has the skb queued ATM.
++ */
++ char cb[48] __aligned(8);
++
++ unsigned long _skb_refdst;
++ void (*destructor)(struct sk_buff *skb);
++#ifdef CONFIG_XFRM
++ struct sec_path *sp;
++#endif
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++ struct nf_conntrack *nfct;
++#endif
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++ struct nf_bridge_info *nf_bridge;
++#endif
++ unsigned int len,
++ data_len;
++ __u16 mac_len,
++ hdr_len;
++
++ /* Following fields are _not_ copied in __copy_skb_header()
++ * Note that queue_mapping is here mostly to fill a hole.
++ */
++ kmemcheck_bitfield_begin(flags1);
++ __u16 queue_mapping;
++ __u8 cloned:1,
++ nohdr:1,
++ fclone:2,
++ peeked:1,
++ head_frag:1,
++ xmit_more:1;
++ /* one bit hole */
++ kmemcheck_bitfield_end(flags1);
++
++ /* fields enclosed in headers_start/headers_end are copied
++ * using a single memcpy() in __copy_skb_header()
++ */
++ /* private: */
++ __u32 headers_start[0];
++ /* public: */
++
++/* if you move pkt_type around you also must adapt those constants */
++#ifdef __BIG_ENDIAN_BITFIELD
++#define PKT_TYPE_MAX (7 << 5)
++#else
++#define PKT_TYPE_MAX 7
++#endif
++#define PKT_TYPE_OFFSET() offsetof(struct sk_buff, __pkt_type_offset)
++
++ __u8 __pkt_type_offset[0];
++ __u8 pkt_type:3;
++ __u8 pfmemalloc:1;
++ __u8 ignore_df:1;
++ __u8 nfctinfo:3;
++
++ __u8 nf_trace:1;
++ __u8 ip_summed:2;
++ __u8 ooo_okay:1;
++ __u8 l4_hash:1;
++ __u8 sw_hash:1;
++ __u8 wifi_acked_valid:1;
++ __u8 wifi_acked:1;
++
++ __u8 no_fcs:1;
++ /* Indicates the inner headers are valid in the skbuff. */
++ __u8 encapsulation:1;
++ __u8 encap_hdr_csum:1;
++ __u8 csum_valid:1;
++ __u8 csum_complete_sw:1;
++ __u8 csum_level:2;
++ __u8 csum_bad:1;
++
++#ifdef CONFIG_IPV6_NDISC_NODETYPE
++ __u8 ndisc_nodetype:2;
++#endif
++ __u8 ipvs_property:1;
++ __u8 inner_protocol_type:1;
++ /* 4 or 6 bit hole */
++
++#ifdef CONFIG_NET_SCHED
++ __u16 tc_index; /* traffic control index */
++#ifdef CONFIG_NET_CLS_ACT
++ __u16 tc_verd; /* traffic control verdict */
++#endif
++#endif
++
++ union {
++ __wsum csum;
++ struct {
++ __u16 csum_start;
++ __u16 csum_offset;
++ };
++ };
++ __u32 priority;
++ int skb_iif;
++ __u32 hash;
++ __be16 vlan_proto;
++ __u16 vlan_tci;
++#ifdef CONFIG_NET_RX_BUSY_POLL
++ unsigned int napi_id;
++#endif
++#ifdef CONFIG_NETWORK_SECMARK
++ __u32 secmark;
++#endif
++ union {
++ __u32 mark;
++ __u32 dropcount;
++ __u32 reserved_tailroom;
++ };
++
++ union {
++ __be16 inner_protocol;
++ __u8 inner_ipproto;
++ };
++
++ __u16 inner_transport_header;
++ __u16 inner_network_header;
++ __u16 inner_mac_header;
++
++ __be16 protocol;
++ __u16 transport_header;
++ __u16 network_header;
++ __u16 mac_header;
++
++ /* private: */
++ __u32 headers_end[0];
++ /* public: */
++
++ /* These elements must be at the end, see alloc_skb() for details. */
++ sk_buff_data_t tail;
++ sk_buff_data_t end;
++ unsigned char *head,
++ *data;
++ unsigned int truesize;
++ atomic_t users;
++};
++
++#ifdef __KERNEL__
++/*
++ * Handling routines are only of interest to the kernel
++ */
++#include <linux/slab.h>
++
++
++#define SKB_ALLOC_FCLONE 0x01
++#define SKB_ALLOC_RX 0x02
++
++/* Returns true if the skb was allocated from PFMEMALLOC reserves */
++static inline bool skb_pfmemalloc(const struct sk_buff *skb)
++{
++ return unlikely(skb->pfmemalloc);
++}
++
++/*
++ * skb might have a dst pointer attached, refcounted or not.
++ * _skb_refdst low order bit is set if refcount was _not_ taken
++ */
++#define SKB_DST_NOREF 1UL
++#define SKB_DST_PTRMASK ~(SKB_DST_NOREF)
++
++/**
++ * skb_dst - returns skb dst_entry
++ * @skb: buffer
++ *
++ * Returns skb dst_entry, regardless of reference taken or not.
++ */
++static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
++{
++ /* If refdst was not refcounted, check we still are in a
++ * rcu_read_lock section
++ */
++ WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) &&
++ !rcu_read_lock_held() &&
++ !rcu_read_lock_bh_held());
++ return (struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK);
++}
++
++/**
++ * skb_dst_set - sets skb dst
++ * @skb: buffer
++ * @dst: dst entry
++ *
++ * Sets skb dst, assuming a reference was taken on dst and should
++ * be released by skb_dst_drop()
++ */
++static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
++{
++ skb->_skb_refdst = (unsigned long)dst;
++}
++
++void __skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst,
++ bool force);
++
++/**
++ * skb_dst_set_noref - sets skb dst, hopefully, without taking reference
++ * @skb: buffer
++ * @dst: dst entry
++ *
++ * Sets skb dst, assuming a reference was not taken on dst.
++ * If dst entry is cached, we do not take reference and dst_release
++ * will be avoided by refdst_drop. If dst entry is not cached, we take
++ * reference, so that last dst_release can destroy the dst immediately.
++ */
++static inline void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst)
++{
++ __skb_dst_set_noref(skb, dst, false);
++}
++
++/**
++ * skb_dst_set_noref_force - sets skb dst, without taking reference
++ * @skb: buffer
++ * @dst: dst entry
++ *
++ * Sets skb dst, assuming a reference was not taken on dst.
++ * No reference is taken and no dst_release will be called. While for
++ * cached dsts deferred reclaim is a basic feature, for entries that are
++ * not cached it is caller's job to guarantee that last dst_release for
++ * provided dst happens when nobody uses it, eg. after a RCU grace period.
++ */
++static inline void skb_dst_set_noref_force(struct sk_buff *skb,
++ struct dst_entry *dst)
++{
++ __skb_dst_set_noref(skb, dst, true);
++}
++
++/**
++ * skb_dst_is_noref - Test if skb dst isn't refcounted
++ * @skb: buffer
++ */
++static inline bool skb_dst_is_noref(const struct sk_buff *skb)
++{
++ return (skb->_skb_refdst & SKB_DST_NOREF) && skb_dst(skb);
++}
++
++static inline struct rtable *skb_rtable(const struct sk_buff *skb)
++{
++ return (struct rtable *)skb_dst(skb);
++}
++
++void kfree_skb(struct sk_buff *skb);
++void kfree_skb_list(struct sk_buff *segs);
++void skb_tx_error(struct sk_buff *skb);
++void consume_skb(struct sk_buff *skb);
++void __kfree_skb(struct sk_buff *skb);
++extern struct kmem_cache *skbuff_head_cache;
++
++void kfree_skb_partial(struct sk_buff *skb, bool head_stolen);
++bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
++ bool *fragstolen, int *delta_truesize);
++
++struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags,
++ int node);
++struct sk_buff *__build_skb(void *data, unsigned int frag_size);
++struct sk_buff *build_skb(void *data, unsigned int frag_size);
++static inline struct sk_buff *alloc_skb(unsigned int size,
++ gfp_t priority)
++{
++ return __alloc_skb(size, priority, 0, NUMA_NO_NODE);
++}
++
++struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
++ unsigned long data_len,
++ int max_page_order,
++ int *errcode,
++ gfp_t gfp_mask);
++
++/* Layout of fast clones : [skb1][skb2][fclone_ref] */
++struct sk_buff_fclones {
++ struct sk_buff skb1;
++
++ struct sk_buff skb2;
++
++ atomic_t fclone_ref;
++};
++
++/**
++ * skb_fclone_busy - check if fclone is busy
++ * @skb: buffer
++ *
++ * Returns true is skb is a fast clone, and its clone is not freed.
++ * Some drivers call skb_orphan() in their ndo_start_xmit(),
++ * so we also check that this didnt happen.
++ */
++static inline bool skb_fclone_busy(const struct sock *sk,
++ const struct sk_buff *skb)
++{
++ const struct sk_buff_fclones *fclones;
++
++ fclones = container_of(skb, struct sk_buff_fclones, skb1);
++
++ return skb->fclone == SKB_FCLONE_ORIG &&
++ fclones->skb2.fclone == SKB_FCLONE_CLONE &&
++ fclones->skb2.sk == sk;
++}
++
++static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
++ gfp_t priority)
++{
++ return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE);
++}
++
++struct sk_buff *__alloc_skb_head(gfp_t priority, int node);
++static inline struct sk_buff *alloc_skb_head(gfp_t priority)
++{
++ return __alloc_skb_head(priority, -1);
++}
++
++struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
++int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
++struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority);
++struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority);
++struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
++ gfp_t gfp_mask, bool fclone);
++static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom,
++ gfp_t gfp_mask)
++{
++ return __pskb_copy_fclone(skb, headroom, gfp_mask, false);
++}
++
++int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask);
++struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
++ unsigned int headroom);
++struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom,
++ int newtailroom, gfp_t priority);
++int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
++ int offset, int len);
++int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset,
++ int len);
++int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer);
++int skb_pad(struct sk_buff *skb, int pad);
++#define dev_kfree_skb(a) consume_skb(a)
++
++int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
++ int getfrag(void *from, char *to, int offset,
++ int len, int odd, struct sk_buff *skb),
++ void *from, int length);
++
++struct skb_seq_state {
++ __u32 lower_offset;
++ __u32 upper_offset;
++ __u32 frag_idx;
++ __u32 stepped_offset;
++ struct sk_buff *root_skb;
++ struct sk_buff *cur_skb;
++ __u8 *frag_data;
++};
++
++void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
++ unsigned int to, struct skb_seq_state *st);
++unsigned int skb_seq_read(unsigned int consumed, const u8 **data,
++ struct skb_seq_state *st);
++void skb_abort_seq_read(struct skb_seq_state *st);
++
++unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
++ unsigned int to, struct ts_config *config,
++ struct ts_state *state);
++
++/*
++ * Packet hash types specify the type of hash in skb_set_hash.
++ *
++ * Hash types refer to the protocol layer addresses which are used to
++ * construct a packet's hash. The hashes are used to differentiate or identify
++ * flows of the protocol layer for the hash type. Hash types are either
++ * layer-2 (L2), layer-3 (L3), or layer-4 (L4).
++ *
++ * Properties of hashes:
++ *
++ * 1) Two packets in different flows have different hash values
++ * 2) Two packets in the same flow should have the same hash value
++ *
++ * A hash at a higher layer is considered to be more specific. A driver should
++ * set the most specific hash possible.
++ *
++ * A driver cannot indicate a more specific hash than the layer at which a hash
++ * was computed. For instance an L3 hash cannot be set as an L4 hash.
++ *
++ * A driver may indicate a hash level which is less specific than the
++ * actual layer the hash was computed on. For instance, a hash computed
++ * at L4 may be considered an L3 hash. This should only be done if the
++ * driver can't unambiguously determine that the HW computed the hash at
++ * the higher layer. Note that the "should" in the second property above
++ * permits this.
++ */
++enum pkt_hash_types {
++ PKT_HASH_TYPE_NONE, /* Undefined type */
++ PKT_HASH_TYPE_L2, /* Input: src_MAC, dest_MAC */
++ PKT_HASH_TYPE_L3, /* Input: src_IP, dst_IP */
++ PKT_HASH_TYPE_L4, /* Input: src_IP, dst_IP, src_port, dst_port */
++};
++
++static inline void
++skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
++{
++ skb->l4_hash = (type == PKT_HASH_TYPE_L4);
++ skb->sw_hash = 0;
++ skb->hash = hash;
++}
++
++void __skb_get_hash(struct sk_buff *skb);
++static inline __u32 skb_get_hash(struct sk_buff *skb)
++{
++ if (!skb->l4_hash && !skb->sw_hash)
++ __skb_get_hash(skb);
++
++ return skb->hash;
++}
++
++static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)
++{
++ return skb->hash;
++}
++
++static inline void skb_clear_hash(struct sk_buff *skb)
++{
++ skb->hash = 0;
++ skb->sw_hash = 0;
++ skb->l4_hash = 0;
++}
++
++static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb)
++{
++ if (!skb->l4_hash)
++ skb_clear_hash(skb);
++}
++
++static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
++{
++ to->hash = from->hash;
++ to->sw_hash = from->sw_hash;
++ to->l4_hash = from->l4_hash;
++};
++
++#ifdef NET_SKBUFF_DATA_USES_OFFSET
++static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
++{
++ return skb->head + skb->end;
++}
++
++static inline unsigned int skb_end_offset(const struct sk_buff *skb)
++{
++ return skb->end;
++}
++#else
++static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
++{
++ return skb->end;
++}
++
++static inline unsigned int skb_end_offset(const struct sk_buff *skb)
++{
++ return skb->end - skb->head;
++}
++#endif
++
++/* Internal */
++#define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB)))
++
++static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
++{
++ return &skb_shinfo(skb)->hwtstamps;
++}
++
++/**
++ * skb_queue_empty - check if a queue is empty
++ * @list: queue head
++ *
++ * Returns true if the queue is empty, false otherwise.
++ */
++static inline int skb_queue_empty(const struct sk_buff_head *list)
++{
++ return list->next == (const struct sk_buff *) list;
++}
++
++/**
++ * skb_queue_is_last - check if skb is the last entry in the queue
++ * @list: queue head
++ * @skb: buffer
++ *
++ * Returns true if @skb is the last buffer on the list.
++ */
++static inline bool skb_queue_is_last(const struct sk_buff_head *list,
++ const struct sk_buff *skb)
++{
++ return skb->next == (const struct sk_buff *) list;
++}
++
++/**
++ * skb_queue_is_first - check if skb is the first entry in the queue
++ * @list: queue head
++ * @skb: buffer
++ *
++ * Returns true if @skb is the first buffer on the list.
++ */
++static inline bool skb_queue_is_first(const struct sk_buff_head *list,
++ const struct sk_buff *skb)
++{
++ return skb->prev == (const struct sk_buff *) list;
++}
++
++/**
++ * skb_queue_next - return the next packet in the queue
++ * @list: queue head
++ * @skb: current buffer
++ *
++ * Return the next packet in @list after @skb. It is only valid to
++ * call this if skb_queue_is_last() evaluates to false.
++ */
++static inline struct sk_buff *skb_queue_next(const struct sk_buff_head *list,
++ const struct sk_buff *skb)
++{
++ /* This BUG_ON may seem severe, but if we just return then we
++ * are going to dereference garbage.
++ */
++ BUG_ON(skb_queue_is_last(list, skb));
++ return skb->next;
++}
++
++/**
++ * skb_queue_prev - return the prev packet in the queue
++ * @list: queue head
++ * @skb: current buffer
++ *
++ * Return the prev packet in @list before @skb. It is only valid to
++ * call this if skb_queue_is_first() evaluates to false.
++ */
++static inline struct sk_buff *skb_queue_prev(const struct sk_buff_head *list,
++ const struct sk_buff *skb)
++{
++ /* This BUG_ON may seem severe, but if we just return then we
++ * are going to dereference garbage.
++ */
++ BUG_ON(skb_queue_is_first(list, skb));
++ return skb->prev;
++}
++
++/**
++ * skb_get - reference buffer
++ * @skb: buffer to reference
++ *
++ * Makes another reference to a socket buffer and returns a pointer
++ * to the buffer.
++ */
++static inline struct sk_buff *skb_get(struct sk_buff *skb)
++{
++ atomic_inc(&skb->users);
++ return skb;
++}
++
++/*
++ * If users == 1, we are the only owner and are can avoid redundant
++ * atomic change.
++ */
++
++/**
++ * skb_cloned - is the buffer a clone
++ * @skb: buffer to check
++ *
++ * Returns true if the buffer was generated with skb_clone() and is
++ * one of multiple shared copies of the buffer. Cloned buffers are
++ * shared data so must not be written to under normal circumstances.
++ */
++static inline int skb_cloned(const struct sk_buff *skb)
++{
++ return skb->cloned &&
++ (atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1;
++}
++
++static inline int skb_unclone(struct sk_buff *skb, gfp_t pri)
++{
++ might_sleep_if(pri & __GFP_WAIT);
++
++ if (skb_cloned(skb))
++ return pskb_expand_head(skb, 0, 0, pri);
++
++ return 0;
++}
++
++/**
++ * skb_header_cloned - is the header a clone
++ * @skb: buffer to check
++ *
++ * Returns true if modifying the header part of the buffer requires
++ * the data to be copied.
++ */
++static inline int skb_header_cloned(const struct sk_buff *skb)
++{
++ int dataref;
++
++ if (!skb->cloned)
++ return 0;
++
++ dataref = atomic_read(&skb_shinfo(skb)->dataref);
++ dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT);
++ return dataref != 1;
++}
++
++/**
++ * skb_header_release - release reference to header
++ * @skb: buffer to operate on
++ *
++ * Drop a reference to the header part of the buffer. This is done
++ * by acquiring a payload reference. You must not read from the header
++ * part of skb->data after this.
++ * Note : Check if you can use __skb_header_release() instead.
++ */
++static inline void skb_header_release(struct sk_buff *skb)
++{
++ BUG_ON(skb->nohdr);
++ skb->nohdr = 1;
++ atomic_add(1 << SKB_DATAREF_SHIFT, &skb_shinfo(skb)->dataref);
++}
++
++/**
++ * __skb_header_release - release reference to header
++ * @skb: buffer to operate on
++ *
++ * Variant of skb_header_release() assuming skb is private to caller.
++ * We can avoid one atomic operation.
++ */
++static inline void __skb_header_release(struct sk_buff *skb)
++{
++ skb->nohdr = 1;
++ atomic_set(&skb_shinfo(skb)->dataref, 1 + (1 << SKB_DATAREF_SHIFT));
++}
++
++
++/**
++ * skb_shared - is the buffer shared
++ * @skb: buffer to check
++ *
++ * Returns true if more than one person has a reference to this
++ * buffer.
++ */
++static inline int skb_shared(const struct sk_buff *skb)
++{
++ return atomic_read(&skb->users) != 1;
++}
++
++/**
++ * skb_share_check - check if buffer is shared and if so clone it
++ * @skb: buffer to check
++ * @pri: priority for memory allocation
++ *
++ * If the buffer is shared the buffer is cloned and the old copy
++ * drops a reference. A new clone with a single reference is returned.
++ * If the buffer is not shared the original buffer is returned. When
++ * being called from interrupt status or with spinlocks held pri must
++ * be GFP_ATOMIC.
++ *
++ * NULL is returned on a memory allocation failure.
++ */
++static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri)
++{
++ might_sleep_if(pri & __GFP_WAIT);
++ if (skb_shared(skb)) {
++ struct sk_buff *nskb = skb_clone(skb, pri);
++
++ if (likely(nskb))
++ consume_skb(skb);
++ else
++ kfree_skb(skb);
++ skb = nskb;
++ }
++ return skb;
++}
++
++/*
++ * Copy shared buffers into a new sk_buff. We effectively do COW on
++ * packets to handle cases where we have a local reader and forward
++ * and a couple of other messy ones. The normal one is tcpdumping
++ * a packet thats being forwarded.
++ */
++
++/**
++ * skb_unshare - make a copy of a shared buffer
++ * @skb: buffer to check
++ * @pri: priority for memory allocation
++ *
++ * If the socket buffer is a clone then this function creates a new
++ * copy of the data, drops a reference count on the old copy and returns
++ * the new copy with the reference count at 1. If the buffer is not a clone
++ * the original buffer is returned. When called with a spinlock held or
++ * from interrupt state @pri must be %GFP_ATOMIC
++ *
++ * %NULL is returned on a memory allocation failure.
++ */
++static inline struct sk_buff *skb_unshare(struct sk_buff *skb,
++ gfp_t pri)
++{
++ might_sleep_if(pri & __GFP_WAIT);
++ if (skb_cloned(skb)) {
++ struct sk_buff *nskb = skb_copy(skb, pri);
++
++ /* Free our shared copy */
++ if (likely(nskb))
++ consume_skb(skb);
++ else
++ kfree_skb(skb);
++ skb = nskb;
++ }
++ return skb;
++}
++
++/**
++ * skb_peek - peek at the head of an &sk_buff_head
++ * @list_: list to peek at
++ *
++ * Peek an &sk_buff. Unlike most other operations you _MUST_
++ * be careful with this one. A peek leaves the buffer on the
++ * list and someone else may run off with it. You must hold
++ * the appropriate locks or have a private queue to do this.
++ *
++ * Returns %NULL for an empty list or a pointer to the head element.
++ * The reference count is not incremented and the reference is therefore
++ * volatile. Use with caution.
++ */
++static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_)
++{
++ struct sk_buff *skb = list_->next;
++
++ if (skb == (struct sk_buff *)list_)
++ skb = NULL;
++ return skb;
++}
++
++/**
++ * skb_peek_next - peek skb following the given one from a queue
++ * @skb: skb to start from
++ * @list_: list to peek at
++ *
++ * Returns %NULL when the end of the list is met or a pointer to the
++ * next element. The reference count is not incremented and the
++ * reference is therefore volatile. Use with caution.
++ */
++static inline struct sk_buff *skb_peek_next(struct sk_buff *skb,
++ const struct sk_buff_head *list_)
++{
++ struct sk_buff *next = skb->next;
++
++ if (next == (struct sk_buff *)list_)
++ next = NULL;
++ return next;
++}
++
++/**
++ * skb_peek_tail - peek at the tail of an &sk_buff_head
++ * @list_: list to peek at
++ *
++ * Peek an &sk_buff. Unlike most other operations you _MUST_
++ * be careful with this one. A peek leaves the buffer on the
++ * list and someone else may run off with it. You must hold
++ * the appropriate locks or have a private queue to do this.
++ *
++ * Returns %NULL for an empty list or a pointer to the tail element.
++ * The reference count is not incremented and the reference is therefore
++ * volatile. Use with caution.
++ */
++static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_)
++{
++ struct sk_buff *skb = list_->prev;
++
++ if (skb == (struct sk_buff *)list_)
++ skb = NULL;
++ return skb;
++
++}
++
++/**
++ * skb_queue_len - get queue length
++ * @list_: list to measure
++ *
++ * Return the length of an &sk_buff queue.
++ */
++static inline __u32 skb_queue_len(const struct sk_buff_head *list_)
++{
++ return list_->qlen;
++}
++
++/**
++ * __skb_queue_head_init - initialize non-spinlock portions of sk_buff_head
++ * @list: queue to initialize
++ *
++ * This initializes only the list and queue length aspects of
++ * an sk_buff_head object. This allows to initialize the list
++ * aspects of an sk_buff_head without reinitializing things like
++ * the spinlock. It can also be used for on-stack sk_buff_head
++ * objects where the spinlock is known to not be used.
++ */
++static inline void __skb_queue_head_init(struct sk_buff_head *list)
++{
++ list->prev = list->next = (struct sk_buff *)list;
++ list->qlen = 0;
++}
++
++/*
++ * This function creates a split out lock class for each invocation;
++ * this is needed for now since a whole lot of users of the skb-queue
++ * infrastructure in drivers have different locking usage (in hardirq)
++ * than the networking core (in softirq only). In the long run either the
++ * network layer or drivers should need annotation to consolidate the
++ * main types of usage into 3 classes.
++ */
++static inline void skb_queue_head_init(struct sk_buff_head *list)
++{
++ spin_lock_init(&list->lock);
++ __skb_queue_head_init(list);
++}
++
++static inline void skb_queue_head_init_class(struct sk_buff_head *list,
++ struct lock_class_key *class)
++{
++ skb_queue_head_init(list);
++ lockdep_set_class(&list->lock, class);
++}
++
++/*
++ * Insert an sk_buff on a list.
++ *
++ * The "__skb_xxxx()" functions are the non-atomic ones that
++ * can only be called with interrupts disabled.
++ */
++void skb_insert(struct sk_buff *old, struct sk_buff *newsk,
++ struct sk_buff_head *list);
++static inline void __skb_insert(struct sk_buff *newsk,
++ struct sk_buff *prev, struct sk_buff *next,
++ struct sk_buff_head *list)
++{
++ newsk->next = next;
++ newsk->prev = prev;
++ next->prev = prev->next = newsk;
++ list->qlen++;
++}
++
++static inline void __skb_queue_splice(const struct sk_buff_head *list,
++ struct sk_buff *prev,
++ struct sk_buff *next)
++{
++ struct sk_buff *first = list->next;
++ struct sk_buff *last = list->prev;
++
++ first->prev = prev;
++ prev->next = first;
++
++ last->next = next;
++ next->prev = last;
++}
++
++/**
++ * skb_queue_splice - join two skb lists, this is designed for stacks
++ * @list: the new list to add
++ * @head: the place to add it in the first list
++ */
++static inline void skb_queue_splice(const struct sk_buff_head *list,
++ struct sk_buff_head *head)
++{
++ if (!skb_queue_empty(list)) {
++ __skb_queue_splice(list, (struct sk_buff *) head, head->next);
++ head->qlen += list->qlen;
++ }
++}
++
++/**
++ * skb_queue_splice_init - join two skb lists and reinitialise the emptied list
++ * @list: the new list to add
++ * @head: the place to add it in the first list
++ *
++ * The list at @list is reinitialised
++ */
++static inline void skb_queue_splice_init(struct sk_buff_head *list,
++ struct sk_buff_head *head)
++{
++ if (!skb_queue_empty(list)) {
++ __skb_queue_splice(list, (struct sk_buff *) head, head->next);
++ head->qlen += list->qlen;
++ __skb_queue_head_init(list);
++ }
++}
++
++/**
++ * skb_queue_splice_tail - join two skb lists, each list being a queue
++ * @list: the new list to add
++ * @head: the place to add it in the first list
++ */
++static inline void skb_queue_splice_tail(const struct sk_buff_head *list,
++ struct sk_buff_head *head)
++{
++ if (!skb_queue_empty(list)) {
++ __skb_queue_splice(list, head->prev, (struct sk_buff *) head);
++ head->qlen += list->qlen;
++ }
++}
++
++/**
++ * skb_queue_splice_tail_init - join two skb lists and reinitialise the emptied list
++ * @list: the new list to add
++ * @head: the place to add it in the first list
++ *
++ * Each of the lists is a queue.
++ * The list at @list is reinitialised
++ */
++static inline void skb_queue_splice_tail_init(struct sk_buff_head *list,
++ struct sk_buff_head *head)
++{
++ if (!skb_queue_empty(list)) {
++ __skb_queue_splice(list, head->prev, (struct sk_buff *) head);
++ head->qlen += list->qlen;
++ __skb_queue_head_init(list);
++ }
++}
++
++/**
++ * __skb_queue_after - queue a buffer at the list head
++ * @list: list to use
++ * @prev: place after this buffer
++ * @newsk: buffer to queue
++ *
++ * Queue a buffer int the middle of a list. This function takes no locks
++ * and you must therefore hold required locks before calling it.
++ *
++ * A buffer cannot be placed on two lists at the same time.
++ */
++static inline void __skb_queue_after(struct sk_buff_head *list,
++ struct sk_buff *prev,
++ struct sk_buff *newsk)
++{
++ __skb_insert(newsk, prev, prev->next, list);
++}
++
++void skb_append(struct sk_buff *old, struct sk_buff *newsk,
++ struct sk_buff_head *list);
++
++static inline void __skb_queue_before(struct sk_buff_head *list,
++ struct sk_buff *next,
++ struct sk_buff *newsk)
++{
++ __skb_insert(newsk, next->prev, next, list);
++}
++
++/**
++ * __skb_queue_head - queue a buffer at the list head
++ * @list: list to use
++ * @newsk: buffer to queue
++ *
++ * Queue a buffer at the start of a list. This function takes no locks
++ * and you must therefore hold required locks before calling it.
++ *
++ * A buffer cannot be placed on two lists at the same time.
++ */
++void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk);
++static inline void __skb_queue_head(struct sk_buff_head *list,
++ struct sk_buff *newsk)
++{
++ __skb_queue_after(list, (struct sk_buff *)list, newsk);
++}
++
++/**
++ * __skb_queue_tail - queue a buffer at the list tail
++ * @list: list to use
++ * @newsk: buffer to queue
++ *
++ * Queue a buffer at the end of a list. This function takes no locks
++ * and you must therefore hold required locks before calling it.
++ *
++ * A buffer cannot be placed on two lists at the same time.
++ */
++void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk);
++static inline void __skb_queue_tail(struct sk_buff_head *list,
++ struct sk_buff *newsk)
++{
++ __skb_queue_before(list, (struct sk_buff *)list, newsk);
++}
++
++/*
++ * remove sk_buff from list. _Must_ be called atomically, and with
++ * the list known..
++ */
++void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list);
++static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
++{
++ struct sk_buff *next, *prev;
++
++ list->qlen--;
++ next = skb->next;
++ prev = skb->prev;
++ skb->next = skb->prev = NULL;
++ next->prev = prev;
++ prev->next = next;
++}
++
++/**
++ * __skb_dequeue - remove from the head of the queue
++ * @list: list to dequeue from
++ *
++ * Remove the head of the list. This function does not take any locks
++ * so must be used with appropriate locks held only. The head item is
++ * returned or %NULL if the list is empty.
++ */
++struct sk_buff *skb_dequeue(struct sk_buff_head *list);
++static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
++{
++ struct sk_buff *skb = skb_peek(list);
++ if (skb)
++ __skb_unlink(skb, list);
++ return skb;
++}
++
++/**
++ * __skb_dequeue_tail - remove from the tail of the queue
++ * @list: list to dequeue from
++ *
++ * Remove the tail of the list. This function does not take any locks
++ * so must be used with appropriate locks held only. The tail item is
++ * returned or %NULL if the list is empty.
++ */
++struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list);
++static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)
++{
++ struct sk_buff *skb = skb_peek_tail(list);
++ if (skb)
++ __skb_unlink(skb, list);
++ return skb;
++}
++
++
++static inline bool skb_is_nonlinear(const struct sk_buff *skb)
++{
++ return skb->data_len;
++}
++
++static inline unsigned int skb_headlen(const struct sk_buff *skb)
++{
++ return skb->len - skb->data_len;
++}
++
++static inline int skb_pagelen(const struct sk_buff *skb)
++{
++ int i, len = 0;
++
++ for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
++ len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
++ return len + skb_headlen(skb);
++}
++
++/**
++ * __skb_fill_page_desc - initialise a paged fragment in an skb
++ * @skb: buffer containing fragment to be initialised
++ * @i: paged fragment index to initialise
++ * @page: the page to use for this fragment
++ * @off: the offset to the data with @page
++ * @size: the length of the data
++ *
++ * Initialises the @i'th fragment of @skb to point to &size bytes at
++ * offset @off within @page.
++ *
++ * Does not take any additional reference on the fragment.
++ */
++static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
++ struct page *page, int off, int size)
++{
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++
++ /*
++ * Propagate page->pfmemalloc to the skb if we can. The problem is
++ * that not all callers have unique ownership of the page. If
++ * pfmemalloc is set, we check the mapping as a mapping implies
++ * page->index is set (index and pfmemalloc share space).
++ * If it's a valid mapping, we cannot use page->pfmemalloc but we
++ * do not lose pfmemalloc information as the pages would not be
++ * allocated using __GFP_MEMALLOC.
++ */
++ frag->page.p = page;
++ frag->page_offset = off;
++ skb_frag_size_set(frag, size);
++
++ page = compound_head(page);
++ if (page->pfmemalloc && !page->mapping)
++ skb->pfmemalloc = true;
++}
++
++/**
++ * skb_fill_page_desc - initialise a paged fragment in an skb
++ * @skb: buffer containing fragment to be initialised
++ * @i: paged fragment index to initialise
++ * @page: the page to use for this fragment
++ * @off: the offset to the data with @page
++ * @size: the length of the data
++ *
++ * As per __skb_fill_page_desc() -- initialises the @i'th fragment of
++ * @skb to point to @size bytes at offset @off within @page. In
++ * addition updates @skb such that @i is the last fragment.
++ *
++ * Does not take any additional reference on the fragment.
++ */
++static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
++ struct page *page, int off, int size)
++{
++ __skb_fill_page_desc(skb, i, page, off, size);
++ skb_shinfo(skb)->nr_frags = i + 1;
++}
++
++void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
++ int size, unsigned int truesize);
++
++void skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size,
++ unsigned int truesize);
++
++#define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags)
++#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb))
++#define SKB_LINEAR_ASSERT(skb) BUG_ON(skb_is_nonlinear(skb))
++
++#ifdef NET_SKBUFF_DATA_USES_OFFSET
++static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
++{
++ return skb->head + skb->tail;
++}
++
++static inline void skb_reset_tail_pointer(struct sk_buff *skb)
++{
++ skb->tail = skb->data - skb->head;
++}
++
++static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
++{
++ skb_reset_tail_pointer(skb);
++ skb->tail += offset;
++}
++
++#else /* NET_SKBUFF_DATA_USES_OFFSET */
++static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
++{
++ return skb->tail;
++}
++
++static inline void skb_reset_tail_pointer(struct sk_buff *skb)
++{
++ skb->tail = skb->data;
++}
++
++static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
++{
++ skb->tail = skb->data + offset;
++}
++
++#endif /* NET_SKBUFF_DATA_USES_OFFSET */
++
++/*
++ * Add data to an sk_buff
++ */
++unsigned char *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
++unsigned char *skb_put(struct sk_buff *skb, unsigned int len);
++static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
++{
++ unsigned char *tmp = skb_tail_pointer(skb);
++ SKB_LINEAR_ASSERT(skb);
++ skb->tail += len;
++ skb->len += len;
++ return tmp;
++}
++
++unsigned char *skb_push(struct sk_buff *skb, unsigned int len);
++static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
++{
++ skb->data -= len;
++ skb->len += len;
++ return skb->data;
++}
++
++unsigned char *skb_pull(struct sk_buff *skb, unsigned int len);
++static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
++{
++ skb->len -= len;
++ BUG_ON(skb->len < skb->data_len);
++ return skb->data += len;
++}
++
++static inline unsigned char *skb_pull_inline(struct sk_buff *skb, unsigned int len)
++{
++ return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
++}
++
++unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
++
++static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len)
++{
++ if (len > skb_headlen(skb) &&
++ !__pskb_pull_tail(skb, len - skb_headlen(skb)))
++ return NULL;
++ skb->len -= len;
++ return skb->data += len;
++}
++
++static inline unsigned char *pskb_pull(struct sk_buff *skb, unsigned int len)
++{
++ return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len);
++}
++
++static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
++{
++ if (likely(len <= skb_headlen(skb)))
++ return 1;
++ if (unlikely(len > skb->len))
++ return 0;
++ return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
++}
++
++/**
++ * skb_headroom - bytes at buffer head
++ * @skb: buffer to check
++ *
++ * Return the number of bytes of free space at the head of an &sk_buff.
++ */
++static inline unsigned int skb_headroom(const struct sk_buff *skb)
++{
++ return skb->data - skb->head;
++}
++
++/**
++ * skb_tailroom - bytes at buffer end
++ * @skb: buffer to check
++ *
++ * Return the number of bytes of free space at the tail of an sk_buff
++ */
++static inline int skb_tailroom(const struct sk_buff *skb)
++{
++ return skb_is_nonlinear(skb) ? 0 : skb->end - skb->tail;
++}
++
++/**
++ * skb_availroom - bytes at buffer end
++ * @skb: buffer to check
++ *
++ * Return the number of bytes of free space at the tail of an sk_buff
++ * allocated by sk_stream_alloc()
++ */
++static inline int skb_availroom(const struct sk_buff *skb)
++{
++ if (skb_is_nonlinear(skb))
++ return 0;
++
++ return skb->end - skb->tail - skb->reserved_tailroom;
++}
++
++/**
++ * skb_reserve - adjust headroom
++ * @skb: buffer to alter
++ * @len: bytes to move
++ *
++ * Increase the headroom of an empty &sk_buff by reducing the tail
++ * room. This is only allowed for an empty buffer.
++ */
++static inline void skb_reserve(struct sk_buff *skb, int len)
++{
++ skb->data += len;
++ skb->tail += len;
++}
++
++#define ENCAP_TYPE_ETHER 0
++#define ENCAP_TYPE_IPPROTO 1
++
++static inline void skb_set_inner_protocol(struct sk_buff *skb,
++ __be16 protocol)
++{
++ skb->inner_protocol = protocol;
++ skb->inner_protocol_type = ENCAP_TYPE_ETHER;
++}
++
++static inline void skb_set_inner_ipproto(struct sk_buff *skb,
++ __u8 ipproto)
++{
++ skb->inner_ipproto = ipproto;
++ skb->inner_protocol_type = ENCAP_TYPE_IPPROTO;
++}
++
++static inline void skb_reset_inner_headers(struct sk_buff *skb)
++{
++ skb->inner_mac_header = skb->mac_header;
++ skb->inner_network_header = skb->network_header;
++ skb->inner_transport_header = skb->transport_header;
++}
++
++static inline void skb_reset_mac_len(struct sk_buff *skb)
++{
++ skb->mac_len = skb->network_header - skb->mac_header;
++}
++
++static inline unsigned char *skb_inner_transport_header(const struct sk_buff
++ *skb)
++{
++ return skb->head + skb->inner_transport_header;
++}
++
++static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
++{
++ skb->inner_transport_header = skb->data - skb->head;
++}
++
++static inline void skb_set_inner_transport_header(struct sk_buff *skb,
++ const int offset)
++{
++ skb_reset_inner_transport_header(skb);
++ skb->inner_transport_header += offset;
++}
++
++static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
++{
++ return skb->head + skb->inner_network_header;
++}
++
++static inline void skb_reset_inner_network_header(struct sk_buff *skb)
++{
++ skb->inner_network_header = skb->data - skb->head;
++}
++
++static inline void skb_set_inner_network_header(struct sk_buff *skb,
++ const int offset)
++{
++ skb_reset_inner_network_header(skb);
++ skb->inner_network_header += offset;
++}
++
++static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
++{
++ return skb->head + skb->inner_mac_header;
++}
++
++static inline void skb_reset_inner_mac_header(struct sk_buff *skb)
++{
++ skb->inner_mac_header = skb->data - skb->head;
++}
++
++static inline void skb_set_inner_mac_header(struct sk_buff *skb,
++ const int offset)
++{
++ skb_reset_inner_mac_header(skb);
++ skb->inner_mac_header += offset;
++}
++static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
++{
++ return skb->transport_header != (typeof(skb->transport_header))~0U;
++}
++
++static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
++{
++ return skb->head + skb->transport_header;
++}
++
++static inline void skb_reset_transport_header(struct sk_buff *skb)
++{
++ skb->transport_header = skb->data - skb->head;
++}
++
++static inline void skb_set_transport_header(struct sk_buff *skb,
++ const int offset)
++{
++ skb_reset_transport_header(skb);
++ skb->transport_header += offset;
++}
++
++static inline unsigned char *skb_network_header(const struct sk_buff *skb)
++{
++ return skb->head + skb->network_header;
++}
++
++static inline void skb_reset_network_header(struct sk_buff *skb)
++{
++ skb->network_header = skb->data - skb->head;
++}
++
++static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
++{
++ skb_reset_network_header(skb);
++ skb->network_header += offset;
++}
++
++static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
++{
++ return skb->head + skb->mac_header;
++}
++
++static inline int skb_mac_header_was_set(const struct sk_buff *skb)
++{
++ return skb->mac_header != (typeof(skb->mac_header))~0U;
++}
++
++static inline void skb_reset_mac_header(struct sk_buff *skb)
++{
++ skb->mac_header = skb->data - skb->head;
++}
++
++static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
++{
++ skb_reset_mac_header(skb);
++ skb->mac_header += offset;
++}
++
++static inline void skb_pop_mac_header(struct sk_buff *skb)
++{
++ skb->mac_header = skb->network_header;
++}
++
++static inline void skb_probe_transport_header(struct sk_buff *skb,
++ const int offset_hint)
++{
++ struct flow_keys keys;
++
++ if (skb_transport_header_was_set(skb))
++ return;
++ else if (skb_flow_dissect(skb, &keys))
++ skb_set_transport_header(skb, keys.thoff);
++ else
++ skb_set_transport_header(skb, offset_hint);
++}
++
++static inline void skb_mac_header_rebuild(struct sk_buff *skb)
++{
++ if (skb_mac_header_was_set(skb)) {
++ const unsigned char *old_mac = skb_mac_header(skb);
++
++ skb_set_mac_header(skb, -skb->mac_len);
++ memmove(skb_mac_header(skb), old_mac, skb->mac_len);
++ }
++}
++
++static inline int skb_checksum_start_offset(const struct sk_buff *skb)
++{
++ return skb->csum_start - skb_headroom(skb);
++}
++
++static inline int skb_transport_offset(const struct sk_buff *skb)
++{
++ return skb_transport_header(skb) - skb->data;
++}
++
++static inline u32 skb_network_header_len(const struct sk_buff *skb)
++{
++ return skb->transport_header - skb->network_header;
++}
++
++static inline u32 skb_inner_network_header_len(const struct sk_buff *skb)
++{
++ return skb->inner_transport_header - skb->inner_network_header;
++}
++
++static inline int skb_network_offset(const struct sk_buff *skb)
++{
++ return skb_network_header(skb) - skb->data;
++}
++
++static inline int skb_inner_network_offset(const struct sk_buff *skb)
++{
++ return skb_inner_network_header(skb) - skb->data;
++}
++
++static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
++{
++ return pskb_may_pull(skb, skb_network_offset(skb) + len);
++}
++
++/*
++ * CPUs often take a performance hit when accessing unaligned memory
++ * locations. The actual performance hit varies, it can be small if the
++ * hardware handles it or large if we have to take an exception and fix it
++ * in software.
++ *
++ * Since an ethernet header is 14 bytes network drivers often end up with
++ * the IP header at an unaligned offset. The IP header can be aligned by
++ * shifting the start of the packet by 2 bytes. Drivers should do this
++ * with:
++ *
++ * skb_reserve(skb, NET_IP_ALIGN);
++ *
++ * The downside to this alignment of the IP header is that the DMA is now
++ * unaligned. On some architectures the cost of an unaligned DMA is high
++ * and this cost outweighs the gains made by aligning the IP header.
++ *
++ * Since this trade off varies between architectures, we allow NET_IP_ALIGN
++ * to be overridden.
++ */
++#ifndef NET_IP_ALIGN
++#define NET_IP_ALIGN 2
++#endif
++
++/*
++ * The networking layer reserves some headroom in skb data (via
++ * dev_alloc_skb). This is used to avoid having to reallocate skb data when
++ * the header has to grow. In the default case, if the header has to grow
++ * 32 bytes or less we avoid the reallocation.
++ *
++ * Unfortunately this headroom changes the DMA alignment of the resulting
++ * network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive
++ * on some architectures. An architecture can override this value,
++ * perhaps setting it to a cacheline in size (since that will maintain
++ * cacheline alignment of the DMA). It must be a power of 2.
++ *
++ * Various parts of the networking layer expect at least 32 bytes of
++ * headroom, you should not reduce this.
++ *
++ * Using max(32, L1_CACHE_BYTES) makes sense (especially with RPS)
++ * to reduce average number of cache lines per packet.
++ * get_rps_cpus() for example only access one 64 bytes aligned block :
++ * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
++ */
++#ifndef NET_SKB_PAD
++#define NET_SKB_PAD max(32, L1_CACHE_BYTES)
++#endif
++
++int ___pskb_trim(struct sk_buff *skb, unsigned int len);
++
++static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
++{
++ if (unlikely(skb_is_nonlinear(skb))) {
++ WARN_ON(1);
++ return;
++ }
++ skb->len = len;
++ skb_set_tail_pointer(skb, len);
++}
++
++void skb_trim(struct sk_buff *skb, unsigned int len);
++
++static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
++{
++ if (skb->data_len)
++ return ___pskb_trim(skb, len);
++ __skb_trim(skb, len);
++ return 0;
++}
++
++static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
++{
++ return (len < skb->len) ? __pskb_trim(skb, len) : 0;
++}
++
++/**
++ * pskb_trim_unique - remove end from a paged unique (not cloned) buffer
++ * @skb: buffer to alter
++ * @len: new length
++ *
++ * This is identical to pskb_trim except that the caller knows that
++ * the skb is not cloned so we should never get an error due to out-
++ * of-memory.
++ */
++static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)
++{
++ int err = pskb_trim(skb, len);
++ BUG_ON(err);
++}
++
++/**
++ * skb_orphan - orphan a buffer
++ * @skb: buffer to orphan
++ *
++ * If a buffer currently has an owner then we call the owner's
++ * destructor function and make the @skb unowned. The buffer continues
++ * to exist but is no longer charged to its former owner.
++ */
++static inline void skb_orphan(struct sk_buff *skb)
++{
++ if (skb->destructor) {
++ skb->destructor(skb);
++ skb->destructor = NULL;
++ skb->sk = NULL;
++ } else {
++ BUG_ON(skb->sk);
++ }
++}
++
++/**
++ * skb_orphan_frags - orphan the frags contained in a buffer
++ * @skb: buffer to orphan frags from
++ * @gfp_mask: allocation mask for replacement pages
++ *
++ * For each frag in the SKB which needs a destructor (i.e. has an
++ * owner) create a copy of that frag and release the original
++ * page by calling the destructor.
++ */
++static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask)
++{
++ if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)))
++ return 0;
++ return skb_copy_ubufs(skb, gfp_mask);
++}
++
++/**
++ * __skb_queue_purge - empty a list
++ * @list: list to empty
++ *
++ * Delete all buffers on an &sk_buff list. Each buffer is removed from
++ * the list and one reference dropped. This function does not take the
++ * list lock and the caller must hold the relevant locks to use it.
++ */
++void skb_queue_purge(struct sk_buff_head *list);
++static inline void __skb_queue_purge(struct sk_buff_head *list)
++{
++ struct sk_buff *skb;
++ while ((skb = __skb_dequeue(list)) != NULL)
++ kfree_skb(skb);
++}
++
++#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768)
++#define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER)
++#define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE
++
++void *netdev_alloc_frag(unsigned int fragsz);
++
++struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int length,
++ gfp_t gfp_mask);
++
++/**
++ * netdev_alloc_skb - allocate an skbuff for rx on a specific device
++ * @dev: network device to receive on
++ * @length: length to allocate
++ *
++ * Allocate a new &sk_buff and assign it a usage count of one. The
++ * buffer has unspecified headroom built in. Users should allocate
++ * the headroom they think they need without accounting for the
++ * built in space. The built in space is used for optimisations.
++ *
++ * %NULL is returned if there is no free memory. Although this function
++ * allocates memory it can be called from an interrupt.
++ */
++static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
++ unsigned int length)
++{
++ return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
++}
++
++/* legacy helper around __netdev_alloc_skb() */
++static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
++ gfp_t gfp_mask)
++{
++ return __netdev_alloc_skb(NULL, length, gfp_mask);
++}
++
++/* legacy helper around netdev_alloc_skb() */
++static inline struct sk_buff *dev_alloc_skb(unsigned int length)
++{
++ return netdev_alloc_skb(NULL, length);
++}
++
++
++static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
++ unsigned int length, gfp_t gfp)
++{
++ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
++
++ if (NET_IP_ALIGN && skb)
++ skb_reserve(skb, NET_IP_ALIGN);
++ return skb;
++}
++
++static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
++ unsigned int length)
++{
++ return __netdev_alloc_skb_ip_align(dev, length, GFP_ATOMIC);
++}
++
++/**
++ * __skb_alloc_pages - allocate pages for ps-rx on a skb and preserve pfmemalloc data
++ * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX
++ * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used
++ * @order: size of the allocation
++ *
++ * Allocate a new page.
++ *
++ * %NULL is returned if there is no free memory.
++*/
++static inline struct page *__skb_alloc_pages(gfp_t gfp_mask,
++ struct sk_buff *skb,
++ unsigned int order)
++{
++ struct page *page;
++
++ gfp_mask |= __GFP_COLD;
++
++ if (!(gfp_mask & __GFP_NOMEMALLOC))
++ gfp_mask |= __GFP_MEMALLOC;
++
++ page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
++ if (skb && page && page->pfmemalloc)
++ skb->pfmemalloc = true;
++
++ return page;
++}
++
++/**
++ * __skb_alloc_page - allocate a page for ps-rx for a given skb and preserve pfmemalloc data
++ * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX
++ * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used
++ *
++ * Allocate a new page.
++ *
++ * %NULL is returned if there is no free memory.
++ */
++static inline struct page *__skb_alloc_page(gfp_t gfp_mask,
++ struct sk_buff *skb)
++{
++ return __skb_alloc_pages(gfp_mask, skb, 0);
++}
++
++/**
++ * skb_propagate_pfmemalloc - Propagate pfmemalloc if skb is allocated after RX page
++ * @page: The page that was allocated from skb_alloc_page
++ * @skb: The skb that may need pfmemalloc set
++ */
++static inline void skb_propagate_pfmemalloc(struct page *page,
++ struct sk_buff *skb)
++{
++ if (page && page->pfmemalloc)
++ skb->pfmemalloc = true;
++}
++
++/**
++ * skb_frag_page - retrieve the page referred to by a paged fragment
++ * @frag: the paged fragment
++ *
++ * Returns the &struct page associated with @frag.
++ */
++static inline struct page *skb_frag_page(const skb_frag_t *frag)
++{
++ return frag->page.p;
++}
++
++/**
++ * __skb_frag_ref - take an addition reference on a paged fragment.
++ * @frag: the paged fragment
++ *
++ * Takes an additional reference on the paged fragment @frag.
++ */
++static inline void __skb_frag_ref(skb_frag_t *frag)
++{
++ get_page(skb_frag_page(frag));
++}
++
++/**
++ * skb_frag_ref - take an addition reference on a paged fragment of an skb.
++ * @skb: the buffer
++ * @f: the fragment offset.
++ *
++ * Takes an additional reference on the @f'th paged fragment of @skb.
++ */
++static inline void skb_frag_ref(struct sk_buff *skb, int f)
++{
++ __skb_frag_ref(&skb_shinfo(skb)->frags[f]);
++}
++
++/**
++ * __skb_frag_unref - release a reference on a paged fragment.
++ * @frag: the paged fragment
++ *
++ * Releases a reference on the paged fragment @frag.
++ */
++static inline void __skb_frag_unref(skb_frag_t *frag)
++{
++ put_page(skb_frag_page(frag));
++}
++
++/**
++ * skb_frag_unref - release a reference on a paged fragment of an skb.
++ * @skb: the buffer
++ * @f: the fragment offset
++ *
++ * Releases a reference on the @f'th paged fragment of @skb.
++ */
++static inline void skb_frag_unref(struct sk_buff *skb, int f)
++{
++ __skb_frag_unref(&skb_shinfo(skb)->frags[f]);
++}
++
++/**
++ * skb_frag_address - gets the address of the data contained in a paged fragment
++ * @frag: the paged fragment buffer
++ *
++ * Returns the address of the data within @frag. The page must already
++ * be mapped.
++ */
++static inline void *skb_frag_address(const skb_frag_t *frag)
++{
++ return page_address(skb_frag_page(frag)) + frag->page_offset;
++}
++
++/**
++ * skb_frag_address_safe - gets the address of the data contained in a paged fragment
++ * @frag: the paged fragment buffer
++ *
++ * Returns the address of the data within @frag. Checks that the page
++ * is mapped and returns %NULL otherwise.
++ */
++static inline void *skb_frag_address_safe(const skb_frag_t *frag)
++{
++ void *ptr = page_address(skb_frag_page(frag));
++ if (unlikely(!ptr))
++ return NULL;
++
++ return ptr + frag->page_offset;
++}
++
++/**
++ * __skb_frag_set_page - sets the page contained in a paged fragment
++ * @frag: the paged fragment
++ * @page: the page to set
++ *
++ * Sets the fragment @frag to contain @page.
++ */
++static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page)
++{
++ frag->page.p = page;
++}
++
++/**
++ * skb_frag_set_page - sets the page contained in a paged fragment of an skb
++ * @skb: the buffer
++ * @f: the fragment offset
++ * @page: the page to set
++ *
++ * Sets the @f'th fragment of @skb to contain @page.
++ */
++static inline void skb_frag_set_page(struct sk_buff *skb, int f,
++ struct page *page)
++{
++ __skb_frag_set_page(&skb_shinfo(skb)->frags[f], page);
++}
++
++bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio);
++
++/**
++ * skb_frag_dma_map - maps a paged fragment via the DMA API
++ * @dev: the device to map the fragment to
++ * @frag: the paged fragment to map
++ * @offset: the offset within the fragment (starting at the
++ * fragment's own offset)
++ * @size: the number of bytes to map
++ * @dir: the direction of the mapping (%PCI_DMA_*)
++ *
++ * Maps the page associated with @frag to @device.
++ */
++static inline dma_addr_t skb_frag_dma_map(struct device *dev,
++ const skb_frag_t *frag,
++ size_t offset, size_t size,
++ enum dma_data_direction dir)
++{
++ return dma_map_page(dev, skb_frag_page(frag),
++ frag->page_offset + offset, size, dir);
++}
++
++static inline struct sk_buff *pskb_copy(struct sk_buff *skb,
++ gfp_t gfp_mask)
++{
++ return __pskb_copy(skb, skb_headroom(skb), gfp_mask);
++}
++
++
++static inline struct sk_buff *pskb_copy_for_clone(struct sk_buff *skb,
++ gfp_t gfp_mask)
++{
++ return __pskb_copy_fclone(skb, skb_headroom(skb), gfp_mask, true);
++}
++
++
++/**
++ * skb_clone_writable - is the header of a clone writable
++ * @skb: buffer to check
++ * @len: length up to which to write
++ *
++ * Returns true if modifying the header part of the cloned buffer
++ * does not requires the data to be copied.
++ */
++static inline int skb_clone_writable(const struct sk_buff *skb, unsigned int len)
++{
++ return !skb_header_cloned(skb) &&
++ skb_headroom(skb) + len <= skb->hdr_len;
++}
++
++static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
++ int cloned)
++{
++ int delta = 0;
++
++ if (headroom > skb_headroom(skb))
++ delta = headroom - skb_headroom(skb);
++
++ if (delta || cloned)
++ return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0,
++ GFP_ATOMIC);
++ return 0;
++}
++
++/**
++ * skb_cow - copy header of skb when it is required
++ * @skb: buffer to cow
++ * @headroom: needed headroom
++ *
++ * If the skb passed lacks sufficient headroom or its data part
++ * is shared, data is reallocated. If reallocation fails, an error
++ * is returned and original skb is not changed.
++ *
++ * The result is skb with writable area skb->head...skb->tail
++ * and at least @headroom of space at head.
++ */
++static inline int skb_cow(struct sk_buff *skb, unsigned int headroom)
++{
++ return __skb_cow(skb, headroom, skb_cloned(skb));
++}
++
++/**
++ * skb_cow_head - skb_cow but only making the head writable
++ * @skb: buffer to cow
++ * @headroom: needed headroom
++ *
++ * This function is identical to skb_cow except that we replace the
++ * skb_cloned check by skb_header_cloned. It should be used when
++ * you only need to push on some header and do not need to modify
++ * the data.
++ */
++static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom)
++{
++ return __skb_cow(skb, headroom, skb_header_cloned(skb));
++}
++
++/**
++ * skb_padto - pad an skbuff up to a minimal size
++ * @skb: buffer to pad
++ * @len: minimal length
++ *
++ * Pads up a buffer to ensure the trailing bytes exist and are
++ * blanked. If the buffer already contains sufficient data it
++ * is untouched. Otherwise it is extended. Returns zero on
++ * success. The skb is freed on error.
++ */
++
++static inline int skb_padto(struct sk_buff *skb, unsigned int len)
++{
++ unsigned int size = skb->len;
++ if (likely(size >= len))
++ return 0;
++ return skb_pad(skb, len - size);
++}
++
++static inline int skb_add_data(struct sk_buff *skb,
++ char __user *from, int copy)
++{
++ const int off = skb->len;
++
++ if (skb->ip_summed == CHECKSUM_NONE) {
++ int err = 0;
++ __wsum csum = csum_and_copy_from_user(from, skb_put(skb, copy),
++ copy, 0, &err);
++ if (!err) {
++ skb->csum = csum_block_add(skb->csum, csum, off);
++ return 0;
++ }
++ } else if (!copy_from_user(skb_put(skb, copy), from, copy))
++ return 0;
++
++ __skb_trim(skb, off);
++ return -EFAULT;
++}
++
++static inline bool skb_can_coalesce(struct sk_buff *skb, int i,
++ const struct page *page, int off)
++{
++ if (i) {
++ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
++
++ return page == skb_frag_page(frag) &&
++ off == frag->page_offset + skb_frag_size(frag);
++ }
++ return false;
++}
++
++static inline int __skb_linearize(struct sk_buff *skb)
++{
++ return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
++}
++
++/**
++ * skb_linearize - convert paged skb to linear one
++ * @skb: buffer to linarize
++ *
++ * If there is no free memory -ENOMEM is returned, otherwise zero
++ * is returned and the old skb data released.
++ */
++static inline int skb_linearize(struct sk_buff *skb)
++{
++ return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
++}
++
++/**
++ * skb_has_shared_frag - can any frag be overwritten
++ * @skb: buffer to test
++ *
++ * Return true if the skb has at least one frag that might be modified
++ * by an external entity (as in vmsplice()/sendfile())
++ */
++static inline bool skb_has_shared_frag(const struct sk_buff *skb)
++{
++ return skb_is_nonlinear(skb) &&
++ skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
++}
++
++/**
++ * skb_linearize_cow - make sure skb is linear and writable
++ * @skb: buffer to process
++ *
++ * If there is no free memory -ENOMEM is returned, otherwise zero
++ * is returned and the old skb data released.
++ */
++static inline int skb_linearize_cow(struct sk_buff *skb)
++{
++ return skb_is_nonlinear(skb) || skb_cloned(skb) ?
++ __skb_linearize(skb) : 0;
++}
++
++/**
++ * skb_postpull_rcsum - update checksum for received skb after pull
++ * @skb: buffer to update
++ * @start: start of data before pull
++ * @len: length of data pulled
++ *
++ * After doing a pull on a received packet, you need to call this to
++ * update the CHECKSUM_COMPLETE checksum, or set ip_summed to
++ * CHECKSUM_NONE so that it can be recomputed from scratch.
++ */
++
++static inline void skb_postpull_rcsum(struct sk_buff *skb,
++ const void *start, unsigned int len)
++{
++ if (skb->ip_summed == CHECKSUM_COMPLETE)
++ skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
++}
++
++unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
++
++/**
++ * pskb_trim_rcsum - trim received skb and update checksum
++ * @skb: buffer to trim
++ * @len: new length
++ *
++ * This is exactly the same as pskb_trim except that it ensures the
++ * checksum of received packets are still valid after the operation.
++ */
++
++static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
++{
++ if (likely(len >= skb->len))
++ return 0;
++ if (skb->ip_summed == CHECKSUM_COMPLETE)
++ skb->ip_summed = CHECKSUM_NONE;
++ return __pskb_trim(skb, len);
++}
++
++#define skb_queue_walk(queue, skb) \
++ for (skb = (queue)->next; \
++ skb != (struct sk_buff *)(queue); \
++ skb = skb->next)
++
++#define skb_queue_walk_safe(queue, skb, tmp) \
++ for (skb = (queue)->next, tmp = skb->next; \
++ skb != (struct sk_buff *)(queue); \
++ skb = tmp, tmp = skb->next)
++
++#define skb_queue_walk_from(queue, skb) \
++ for (; skb != (struct sk_buff *)(queue); \
++ skb = skb->next)
++
++#define skb_queue_walk_from_safe(queue, skb, tmp) \
++ for (tmp = skb->next; \
++ skb != (struct sk_buff *)(queue); \
++ skb = tmp, tmp = skb->next)
++
++#define skb_queue_reverse_walk(queue, skb) \
++ for (skb = (queue)->prev; \
++ skb != (struct sk_buff *)(queue); \
++ skb = skb->prev)
++
++#define skb_queue_reverse_walk_safe(queue, skb, tmp) \
++ for (skb = (queue)->prev, tmp = skb->prev; \
++ skb != (struct sk_buff *)(queue); \
++ skb = tmp, tmp = skb->prev)
++
++#define skb_queue_reverse_walk_from_safe(queue, skb, tmp) \
++ for (tmp = skb->prev; \
++ skb != (struct sk_buff *)(queue); \
++ skb = tmp, tmp = skb->prev)
++
++static inline bool skb_has_frag_list(const struct sk_buff *skb)
++{
++ return skb_shinfo(skb)->frag_list != NULL;
++}
++
++static inline void skb_frag_list_init(struct sk_buff *skb)
++{
++ skb_shinfo(skb)->frag_list = NULL;
++}
++
++static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag)
++{
++ frag->next = skb_shinfo(skb)->frag_list;
++ skb_shinfo(skb)->frag_list = frag;
++}
++
++#define skb_walk_frags(skb, iter) \
++ for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next)
++
++struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
++ int *peeked, int *off, int *err);
++struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
++ int *err);
++unsigned int datagram_poll(struct file *file, struct socket *sock,
++ struct poll_table_struct *wait);
++int skb_copy_datagram_iovec(const struct sk_buff *from, int offset,
++ struct iovec *to, int size);
++int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
++ struct iovec *iov);
++int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
++ const struct iovec *from, int from_offset,
++ int len);
++int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *frm,
++ int offset, size_t count);
++int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset,
++ const struct iovec *to, int to_offset,
++ int size);
++void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
++void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb);
++int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags);
++int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
++int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len);
++__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to,
++ int len, __wsum csum);
++int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
++ struct pipe_inode_info *pipe, unsigned int len,
++ unsigned int flags);
++void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
++unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
++int skb_zerocopy(struct sk_buff *to, struct sk_buff *from,
++ int len, int hlen);
++void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
++int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
++void skb_scrub_packet(struct sk_buff *skb, bool xnet);
++unsigned int skb_gso_transport_seglen(const struct sk_buff *skb);
++struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);
++struct sk_buff *skb_vlan_untag(struct sk_buff *skb);
++
++struct skb_checksum_ops {
++ __wsum (*update)(const void *mem, int len, __wsum wsum);
++ __wsum (*combine)(__wsum csum, __wsum csum2, int offset, int len);
++};
++
++__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
++ __wsum csum, const struct skb_checksum_ops *ops);
++__wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
++ __wsum csum);
++
++static inline void *__skb_header_pointer(const struct sk_buff *skb, int offset,
++ int len, void *data, int hlen, void *buffer)
++{
++ if (hlen - offset >= len)
++ return data + offset;
++
++ if (!skb ||
++ skb_copy_bits(skb, offset, buffer, len) < 0)
++ return NULL;
++
++ return buffer;
++}
++
++static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
++ int len, void *buffer)
++{
++ return __skb_header_pointer(skb, offset, len, skb->data,
++ skb_headlen(skb), buffer);
++}
++
++/**
++ * skb_needs_linearize - check if we need to linearize a given skb
++ * depending on the given device features.
++ * @skb: socket buffer to check
++ * @features: net device features
++ *
++ * Returns true if either:
++ * 1. skb has frag_list and the device doesn't support FRAGLIST, or
++ * 2. skb is fragmented and the device does not support SG.
++ */
++static inline bool skb_needs_linearize(struct sk_buff *skb,
++ netdev_features_t features)
++{
++ return skb_is_nonlinear(skb) &&
++ ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
++ (skb_shinfo(skb)->nr_frags && !(features & NETIF_F_SG)));
++}
++
++static inline void skb_copy_from_linear_data(const struct sk_buff *skb,
++ void *to,
++ const unsigned int len)
++{
++ memcpy(to, skb->data, len);
++}
++
++static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb,
++ const int offset, void *to,
++ const unsigned int len)
++{
++ memcpy(to, skb->data + offset, len);
++}
++
++static inline void skb_copy_to_linear_data(struct sk_buff *skb,
++ const void *from,
++ const unsigned int len)
++{
++ memcpy(skb->data, from, len);
++}
++
++static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb,
++ const int offset,
++ const void *from,
++ const unsigned int len)
++{
++ memcpy(skb->data + offset, from, len);
++}
++
++void skb_init(void);
++
++static inline ktime_t skb_get_ktime(const struct sk_buff *skb)
++{
++ return skb->tstamp;
++}
++
++/**
++ * skb_get_timestamp - get timestamp from a skb
++ * @skb: skb to get stamp from
++ * @stamp: pointer to struct timeval to store stamp in
++ *
++ * Timestamps are stored in the skb as offsets to a base timestamp.
++ * This function converts the offset back to a struct timeval and stores
++ * it in stamp.
++ */
++static inline void skb_get_timestamp(const struct sk_buff *skb,
++ struct timeval *stamp)
++{
++ *stamp = ktime_to_timeval(skb->tstamp);
++}
++
++static inline void skb_get_timestampns(const struct sk_buff *skb,
++ struct timespec *stamp)
++{
++ *stamp = ktime_to_timespec(skb->tstamp);
++}
++
++static inline void __net_timestamp(struct sk_buff *skb)
++{
++ skb->tstamp = ktime_get_real();
++}
++
++static inline ktime_t net_timedelta(ktime_t t)
++{
++ return ktime_sub(ktime_get_real(), t);
++}
++
++static inline ktime_t net_invalid_timestamp(void)
++{
++ return ktime_set(0, 0);
++}
++
++struct sk_buff *skb_clone_sk(struct sk_buff *skb);
++
++#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
++
++void skb_clone_tx_timestamp(struct sk_buff *skb);
++bool skb_defer_rx_timestamp(struct sk_buff *skb);
++
++#else /* CONFIG_NETWORK_PHY_TIMESTAMPING */
++
++static inline void skb_clone_tx_timestamp(struct sk_buff *skb)
++{
++}
++
++static inline bool skb_defer_rx_timestamp(struct sk_buff *skb)
++{
++ return false;
++}
++
++#endif /* !CONFIG_NETWORK_PHY_TIMESTAMPING */
++
++/**
++ * skb_complete_tx_timestamp() - deliver cloned skb with tx timestamps
++ *
++ * PHY drivers may accept clones of transmitted packets for
++ * timestamping via their phy_driver.txtstamp method. These drivers
++ * must call this function to return the skb back to the stack, with
++ * or without a timestamp.
++ *
++ * @skb: clone of the the original outgoing packet
++ * @hwtstamps: hardware time stamps, may be NULL if not available
++ *
++ */
++void skb_complete_tx_timestamp(struct sk_buff *skb,
++ struct skb_shared_hwtstamps *hwtstamps);
++
++void __skb_tstamp_tx(struct sk_buff *orig_skb,
++ struct skb_shared_hwtstamps *hwtstamps,
++ struct sock *sk, int tstype);
++
++/**
++ * skb_tstamp_tx - queue clone of skb with send time stamps
++ * @orig_skb: the original outgoing packet
++ * @hwtstamps: hardware time stamps, may be NULL if not available
++ *
++ * If the skb has a socket associated, then this function clones the
++ * skb (thus sharing the actual data and optional structures), stores
++ * the optional hardware time stamping information (if non NULL) or
++ * generates a software time stamp (otherwise), then queues the clone
++ * to the error queue of the socket. Errors are silently ignored.
++ */
++void skb_tstamp_tx(struct sk_buff *orig_skb,
++ struct skb_shared_hwtstamps *hwtstamps);
++
++static inline void sw_tx_timestamp(struct sk_buff *skb)
++{
++ if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP &&
++ !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
++ skb_tstamp_tx(skb, NULL);
++}
++
++/**
++ * skb_tx_timestamp() - Driver hook for transmit timestamping
++ *
++ * Ethernet MAC Drivers should call this function in their hard_xmit()
++ * function immediately before giving the sk_buff to the MAC hardware.
++ *
++ * Specifically, one should make absolutely sure that this function is
++ * called before TX completion of this packet can trigger. Otherwise
++ * the packet could potentially already be freed.
++ *
++ * @skb: A socket buffer.
++ */
++static inline void skb_tx_timestamp(struct sk_buff *skb)
++{
++ skb_clone_tx_timestamp(skb);
++ sw_tx_timestamp(skb);
++}
++
++/**
++ * skb_complete_wifi_ack - deliver skb with wifi status
++ *
++ * @skb: the original outgoing packet
++ * @acked: ack status
++ *
++ */
++void skb_complete_wifi_ack(struct sk_buff *skb, bool acked);
++
++__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
++__sum16 __skb_checksum_complete(struct sk_buff *skb);
++
++static inline int skb_csum_unnecessary(const struct sk_buff *skb)
++{
++ return ((skb->ip_summed & CHECKSUM_UNNECESSARY) || skb->csum_valid);
++}
++
++/**
++ * skb_checksum_complete - Calculate checksum of an entire packet
++ * @skb: packet to process
++ *
++ * This function calculates the checksum over the entire packet plus
++ * the value of skb->csum. The latter can be used to supply the
++ * checksum of a pseudo header as used by TCP/UDP. It returns the
++ * checksum.
++ *
++ * For protocols that contain complete checksums such as ICMP/TCP/UDP,
++ * this function can be used to verify that checksum on received
++ * packets. In that case the function should return zero if the
++ * checksum is correct. In particular, this function will return zero
++ * if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the
++ * hardware has already verified the correctness of the checksum.
++ */
++static inline __sum16 skb_checksum_complete(struct sk_buff *skb)
++{
++ return skb_csum_unnecessary(skb) ?
++ 0 : __skb_checksum_complete(skb);
++}
++
++static inline void __skb_decr_checksum_unnecessary(struct sk_buff *skb)
++{
++ if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
++ if (skb->csum_level == 0)
++ skb->ip_summed = CHECKSUM_NONE;
++ else
++ skb->csum_level--;
++ }
++}
++
++static inline void __skb_incr_checksum_unnecessary(struct sk_buff *skb)
++{
++ if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
++ if (skb->csum_level < SKB_MAX_CSUM_LEVEL)
++ skb->csum_level++;
++ } else if (skb->ip_summed == CHECKSUM_NONE) {
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb->csum_level = 0;
++ }
++}
++
++static inline void __skb_mark_checksum_bad(struct sk_buff *skb)
++{
++ /* Mark current checksum as bad (typically called from GRO
++ * path). In the case that ip_summed is CHECKSUM_NONE
++ * this must be the first checksum encountered in the packet.
++ * When ip_summed is CHECKSUM_UNNECESSARY, this is the first
++ * checksum after the last one validated. For UDP, a zero
++ * checksum can not be marked as bad.
++ */
++
++ if (skb->ip_summed == CHECKSUM_NONE ||
++ skb->ip_summed == CHECKSUM_UNNECESSARY)
++ skb->csum_bad = 1;
++}
++
++/* Check if we need to perform checksum complete validation.
++ *
++ * Returns true if checksum complete is needed, false otherwise
++ * (either checksum is unnecessary or zero checksum is allowed).
++ */
++static inline bool __skb_checksum_validate_needed(struct sk_buff *skb,
++ bool zero_okay,
++ __sum16 check)
++{
++ if (skb_csum_unnecessary(skb) || (zero_okay && !check)) {
++ skb->csum_valid = 1;
++ __skb_decr_checksum_unnecessary(skb);
++ return false;
++ }
++
++ return true;
++}
++
++/* For small packets <= CHECKSUM_BREAK peform checksum complete directly
++ * in checksum_init.
++ */
++#define CHECKSUM_BREAK 76
++
++/* Unset checksum-complete
++ *
++ * Unset checksum complete can be done when packet is being modified
++ * (uncompressed for instance) and checksum-complete value is
++ * invalidated.
++ */
++static inline void skb_checksum_complete_unset(struct sk_buff *skb)
++{
++ if (skb->ip_summed == CHECKSUM_COMPLETE)
++ skb->ip_summed = CHECKSUM_NONE;
++}
++
++/* Validate (init) checksum based on checksum complete.
++ *
++ * Return values:
++ * 0: checksum is validated or try to in skb_checksum_complete. In the latter
++ * case the ip_summed will not be CHECKSUM_UNNECESSARY and the pseudo
++ * checksum is stored in skb->csum for use in __skb_checksum_complete
++ * non-zero: value of invalid checksum
++ *
++ */
++static inline __sum16 __skb_checksum_validate_complete(struct sk_buff *skb,
++ bool complete,
++ __wsum psum)
++{
++ if (skb->ip_summed == CHECKSUM_COMPLETE) {
++ if (!csum_fold(csum_add(psum, skb->csum))) {
++ skb->csum_valid = 1;
++ return 0;
++ }
++ } else if (skb->csum_bad) {
++ /* ip_summed == CHECKSUM_NONE in this case */
++ return 1;
++ }
++
++ skb->csum = psum;
++
++ if (complete || skb->len <= CHECKSUM_BREAK) {
++ __sum16 csum;
++
++ csum = __skb_checksum_complete(skb);
++ skb->csum_valid = !csum;
++ return csum;
++ }
++
++ return 0;
++}
++
++static inline __wsum null_compute_pseudo(struct sk_buff *skb, int proto)
++{
++ return 0;
++}
++
++/* Perform checksum validate (init). Note that this is a macro since we only
++ * want to calculate the pseudo header which is an input function if necessary.
++ * First we try to validate without any computation (checksum unnecessary) and
++ * then calculate based on checksum complete calling the function to compute
++ * pseudo header.
++ *
++ * Return values:
++ * 0: checksum is validated or try to in skb_checksum_complete
++ * non-zero: value of invalid checksum
++ */
++#define __skb_checksum_validate(skb, proto, complete, \
++ zero_okay, check, compute_pseudo) \
++({ \
++ __sum16 __ret = 0; \
++ skb->csum_valid = 0; \
++ if (__skb_checksum_validate_needed(skb, zero_okay, check)) \
++ __ret = __skb_checksum_validate_complete(skb, \
++ complete, compute_pseudo(skb, proto)); \
++ __ret; \
++})
++
++#define skb_checksum_init(skb, proto, compute_pseudo) \
++ __skb_checksum_validate(skb, proto, false, false, 0, compute_pseudo)
++
++#define skb_checksum_init_zero_check(skb, proto, check, compute_pseudo) \
++ __skb_checksum_validate(skb, proto, false, true, check, compute_pseudo)
++
++#define skb_checksum_validate(skb, proto, compute_pseudo) \
++ __skb_checksum_validate(skb, proto, true, false, 0, compute_pseudo)
++
++#define skb_checksum_validate_zero_check(skb, proto, check, \
++ compute_pseudo) \
++ __skb_checksum_validate_(skb, proto, true, true, check, compute_pseudo)
++
++#define skb_checksum_simple_validate(skb) \
++ __skb_checksum_validate(skb, 0, true, false, 0, null_compute_pseudo)
++
++static inline bool __skb_checksum_convert_check(struct sk_buff *skb)
++{
++ return (skb->ip_summed == CHECKSUM_NONE &&
++ skb->csum_valid && !skb->csum_bad);
++}
++
++static inline void __skb_checksum_convert(struct sk_buff *skb,
++ __sum16 check, __wsum pseudo)
++{
++ skb->csum = ~pseudo;
++ skb->ip_summed = CHECKSUM_COMPLETE;
++}
++
++#define skb_checksum_try_convert(skb, proto, check, compute_pseudo) \
++do { \
++ if (__skb_checksum_convert_check(skb)) \
++ __skb_checksum_convert(skb, check, \
++ compute_pseudo(skb, proto)); \
++} while (0)
++
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++void nf_conntrack_destroy(struct nf_conntrack *nfct);
++static inline void nf_conntrack_put(struct nf_conntrack *nfct)
++{
++ if (nfct && atomic_dec_and_test(&nfct->use))
++ nf_conntrack_destroy(nfct);
++}
++static inline void nf_conntrack_get(struct nf_conntrack *nfct)
++{
++ if (nfct)
++ atomic_inc(&nfct->use);
++}
++#endif
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
++{
++ if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
++ kfree(nf_bridge);
++}
++static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
++{
++ if (nf_bridge)
++ atomic_inc(&nf_bridge->use);
++}
++#endif /* CONFIG_BRIDGE_NETFILTER */
++static inline void nf_reset(struct sk_buff *skb)
++{
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++ nf_conntrack_put(skb->nfct);
++ skb->nfct = NULL;
++#endif
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++ nf_bridge_put(skb->nf_bridge);
++ skb->nf_bridge = NULL;
++#endif
++}
++
++static inline void nf_reset_trace(struct sk_buff *skb)
++{
++#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
++ skb->nf_trace = 0;
++#endif
++}
++
++/* Note: This doesn't put any conntrack and bridge info in dst. */
++static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
++ bool copy)
++{
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++ dst->nfct = src->nfct;
++ nf_conntrack_get(src->nfct);
++ if (copy)
++ dst->nfctinfo = src->nfctinfo;
++#endif
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++ dst->nf_bridge = src->nf_bridge;
++ nf_bridge_get(src->nf_bridge);
++#endif
++#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
++ if (copy)
++ dst->nf_trace = src->nf_trace;
++#endif
++}
++
++static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
++{
++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
++ nf_conntrack_put(dst->nfct);
++#endif
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++ nf_bridge_put(dst->nf_bridge);
++#endif
++ __nf_copy(dst, src, true);
++}
++
++#ifdef CONFIG_NETWORK_SECMARK
++static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
++{
++ to->secmark = from->secmark;
++}
++
++static inline void skb_init_secmark(struct sk_buff *skb)
++{
++ skb->secmark = 0;
++}
++#else
++static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
++{ }
++
++static inline void skb_init_secmark(struct sk_buff *skb)
++{ }
++#endif
++
++static inline bool skb_irq_freeable(const struct sk_buff *skb)
++{
++ return !skb->destructor &&
++#if IS_ENABLED(CONFIG_XFRM)
++ !skb->sp &&
++#endif
++#if IS_ENABLED(CONFIG_NF_CONNTRACK)
++ !skb->nfct &&
++#endif
++ !skb->_skb_refdst &&
++ !skb_has_frag_list(skb);
++}
++
++static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping)
++{
++ skb->queue_mapping = queue_mapping;
++}
++
++static inline u16 skb_get_queue_mapping(const struct sk_buff *skb)
++{
++ return skb->queue_mapping;
++}
++
++static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from)
++{
++ to->queue_mapping = from->queue_mapping;
++}
++
++static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue)
++{
++ skb->queue_mapping = rx_queue + 1;
++}
++
++static inline u16 skb_get_rx_queue(const struct sk_buff *skb)
++{
++ return skb->queue_mapping - 1;
++}
++
++static inline bool skb_rx_queue_recorded(const struct sk_buff *skb)
++{
++ return skb->queue_mapping != 0;
++}
++
++u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb,
++ unsigned int num_tx_queues);
++
++static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
++{
++#ifdef CONFIG_XFRM
++ return skb->sp;
++#else
++ return NULL;
++#endif
++}
++
++/* Keeps track of mac header offset relative to skb->head.
++ * It is useful for TSO of Tunneling protocol. e.g. GRE.
++ * For non-tunnel skb it points to skb_mac_header() and for
++ * tunnel skb it points to outer mac header.
++ * Keeps track of level of encapsulation of network headers.
++ */
++struct skb_gso_cb {
++ int mac_offset;
++ int encap_level;
++ __u16 csum_start;
++};
++#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb)
++
++static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
++{
++ return (skb_mac_header(inner_skb) - inner_skb->head) -
++ SKB_GSO_CB(inner_skb)->mac_offset;
++}
++
++static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
++{
++ int new_headroom, headroom;
++ int ret;
++
++ headroom = skb_headroom(skb);
++ ret = pskb_expand_head(skb, extra, 0, GFP_ATOMIC);
++ if (ret)
++ return ret;
++
++ new_headroom = skb_headroom(skb);
++ SKB_GSO_CB(skb)->mac_offset += (new_headroom - headroom);
++ return 0;
++}
++
++/* Compute the checksum for a gso segment. First compute the checksum value
++ * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and
++ * then add in skb->csum (checksum from csum_start to end of packet).
++ * skb->csum and csum_start are then updated to reflect the checksum of the
++ * resultant packet starting from the transport header-- the resultant checksum
++ * is in the res argument (i.e. normally zero or ~ of checksum of a pseudo
++ * header.
++ */
++static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res)
++{
++ int plen = SKB_GSO_CB(skb)->csum_start - skb_headroom(skb) -
++ skb_transport_offset(skb);
++ __u16 csum;
++
++ csum = csum_fold(csum_partial(skb_transport_header(skb),
++ plen, skb->csum));
++ skb->csum = res;
++ SKB_GSO_CB(skb)->csum_start -= plen;
++
++ return csum;
++}
++
++static inline bool skb_is_gso(const struct sk_buff *skb)
++{
++ return skb_shinfo(skb)->gso_size;
++}
++
++/* Note: Should be called only if skb_is_gso(skb) is true */
++static inline bool skb_is_gso_v6(const struct sk_buff *skb)
++{
++ return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
++}
++
++void __skb_warn_lro_forwarding(const struct sk_buff *skb);
++
++static inline bool skb_warn_if_lro(const struct sk_buff *skb)
++{
++ /* LRO sets gso_size but not gso_type, whereas if GSO is really
++ * wanted then gso_type will be set. */
++ const struct skb_shared_info *shinfo = skb_shinfo(skb);
++
++ if (skb_is_nonlinear(skb) && shinfo->gso_size != 0 &&
++ unlikely(shinfo->gso_type == 0)) {
++ __skb_warn_lro_forwarding(skb);
++ return true;
++ }
++ return false;
++}
++
++static inline void skb_forward_csum(struct sk_buff *skb)
++{
++ /* Unfortunately we don't support this one. Any brave souls? */
++ if (skb->ip_summed == CHECKSUM_COMPLETE)
++ skb->ip_summed = CHECKSUM_NONE;
++}
++
++/**
++ * skb_checksum_none_assert - make sure skb ip_summed is CHECKSUM_NONE
++ * @skb: skb to check
++ *
++ * fresh skbs have their ip_summed set to CHECKSUM_NONE.
++ * Instead of forcing ip_summed to CHECKSUM_NONE, we can
++ * use this helper, to document places where we make this assertion.
++ */
++static inline void skb_checksum_none_assert(const struct sk_buff *skb)
++{
++#ifdef DEBUG
++ BUG_ON(skb->ip_summed != CHECKSUM_NONE);
++#endif
++}
++
++bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
++
++int skb_checksum_setup(struct sk_buff *skb, bool recalculate);
++
++u32 skb_get_poff(const struct sk_buff *skb);
++u32 __skb_get_poff(const struct sk_buff *skb, void *data,
++ const struct flow_keys *keys, int hlen);
++
++/**
++ * skb_head_is_locked - Determine if the skb->head is locked down
++ * @skb: skb to check
++ *
++ * The head on skbs build around a head frag can be removed if they are
++ * not cloned. This function returns true if the skb head is locked down
++ * due to either being allocated via kmalloc, or by being a clone with
++ * multiple references to the head.
++ */
++static inline bool skb_head_is_locked(const struct sk_buff *skb)
++{
++ return !skb->head_frag || skb_cloned(skb);
++}
++
++/**
++ * skb_gso_network_seglen - Return length of individual segments of a gso packet
++ *
++ * @skb: GSO skb
++ *
++ * skb_gso_network_seglen is used to determine the real size of the
++ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
++ *
++ * The MAC/L2 header is not accounted for.
++ */
++static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
++{
++ unsigned int hdr_len = skb_transport_header(skb) -
++ skb_network_header(skb);
++ return hdr_len + skb_gso_transport_seglen(skb);
++}
++#endif /* __KERNEL__ */
++#endif /* _LINUX_SKBUFF_H */
+diff -Nur linux-3.18.14.orig/include/linux/smp.h linux-3.18.14-rt/include/linux/smp.h
+--- linux-3.18.14.orig/include/linux/smp.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/smp.h 2015-05-31 15:32:48.405635367 -0500
@@ -178,6 +178,9 @@
#define get_cpu() ({ preempt_disable(); smp_processor_id(); })
#define put_cpu() preempt_enable()
@@ -10083,9 +18206,9 @@ diff -Nur linux-3.18.12.orig/include/linux/smp.h linux-3.18.12/include/linux/smp
/*
* Callback to arch code if there's nosmp or maxcpus=0 on the
* boot command line:
-diff -Nur linux-3.18.12.orig/include/linux/spinlock_api_smp.h linux-3.18.12/include/linux/spinlock_api_smp.h
---- linux-3.18.12.orig/include/linux/spinlock_api_smp.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/spinlock_api_smp.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock_api_smp.h linux-3.18.14-rt/include/linux/spinlock_api_smp.h
+--- linux-3.18.14.orig/include/linux/spinlock_api_smp.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/spinlock_api_smp.h 2015-05-31 15:32:48.409635367 -0500
@@ -187,6 +187,8 @@
return 0;
}
@@ -10096,9 +18219,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_api_smp.h linux-3.18.12/incl
+#endif
#endif /* __LINUX_SPINLOCK_API_SMP_H */
-diff -Nur linux-3.18.12.orig/include/linux/spinlock.h linux-3.18.12/include/linux/spinlock.h
---- linux-3.18.12.orig/include/linux/spinlock.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/spinlock.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock.h linux-3.18.14-rt/include/linux/spinlock.h
+--- linux-3.18.14.orig/include/linux/spinlock.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/spinlock.h 2015-05-31 15:32:48.405635367 -0500
@@ -278,7 +278,11 @@
#define raw_spin_can_lock(lock) (!raw_spin_is_locked(lock))
@@ -10130,9 +18253,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock.h linux-3.18.12/include/linu
+#endif /* !PREEMPT_RT_FULL */
+
#endif /* __LINUX_SPINLOCK_H */
-diff -Nur linux-3.18.12.orig/include/linux/spinlock_rt.h linux-3.18.12/include/linux/spinlock_rt.h
---- linux-3.18.12.orig/include/linux/spinlock_rt.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/spinlock_rt.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock_rt.h linux-3.18.14-rt/include/linux/spinlock_rt.h
+--- linux-3.18.14.orig/include/linux/spinlock_rt.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/spinlock_rt.h 2015-05-31 15:32:48.413635367 -0500
@@ -0,0 +1,167 @@
+#ifndef __LINUX_SPINLOCK_RT_H
+#define __LINUX_SPINLOCK_RT_H
@@ -10301,9 +18424,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_rt.h linux-3.18.12/include/l
+ atomic_dec_and_spin_lock(atomic, lock)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/spinlock_types.h linux-3.18.12/include/linux/spinlock_types.h
---- linux-3.18.12.orig/include/linux/spinlock_types.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/spinlock_types.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock_types.h linux-3.18.14-rt/include/linux/spinlock_types.h
+--- linux-3.18.14.orig/include/linux/spinlock_types.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/spinlock_types.h 2015-05-31 15:32:48.413635367 -0500
@@ -9,80 +9,15 @@
* Released under the General Public License (GPL).
*/
@@ -10392,9 +18515,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types.h linux-3.18.12/includ
-#include <linux/rwlock_types.h>
-
#endif /* __LINUX_SPINLOCK_TYPES_H */
-diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_nort.h linux-3.18.12/include/linux/spinlock_types_nort.h
---- linux-3.18.12.orig/include/linux/spinlock_types_nort.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/spinlock_types_nort.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock_types_nort.h linux-3.18.14-rt/include/linux/spinlock_types_nort.h
+--- linux-3.18.14.orig/include/linux/spinlock_types_nort.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/spinlock_types_nort.h 2015-05-31 15:32:48.413635367 -0500
@@ -0,0 +1,33 @@
+#ifndef __LINUX_SPINLOCK_TYPES_NORT_H
+#define __LINUX_SPINLOCK_TYPES_NORT_H
@@ -10429,9 +18552,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_nort.h linux-3.18.12/i
+#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_raw.h linux-3.18.12/include/linux/spinlock_types_raw.h
---- linux-3.18.12.orig/include/linux/spinlock_types_raw.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/spinlock_types_raw.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock_types_raw.h linux-3.18.14-rt/include/linux/spinlock_types_raw.h
+--- linux-3.18.14.orig/include/linux/spinlock_types_raw.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/spinlock_types_raw.h 2015-05-31 15:32:48.413635367 -0500
@@ -0,0 +1,56 @@
+#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
+#define __LINUX_SPINLOCK_TYPES_RAW_H
@@ -10489,9 +18612,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_raw.h linux-3.18.12/in
+#define DEFINE_RAW_SPINLOCK(x) raw_spinlock_t x = __RAW_SPIN_LOCK_UNLOCKED(x)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_rt.h linux-3.18.12/include/linux/spinlock_types_rt.h
---- linux-3.18.12.orig/include/linux/spinlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/spinlock_types_rt.h 2015-04-26 13:32:22.423684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/spinlock_types_rt.h linux-3.18.14-rt/include/linux/spinlock_types_rt.h
+--- linux-3.18.14.orig/include/linux/spinlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/spinlock_types_rt.h 2015-05-31 15:32:48.413635367 -0500
@@ -0,0 +1,51 @@
+#ifndef __LINUX_SPINLOCK_TYPES_RT_H
+#define __LINUX_SPINLOCK_TYPES_RT_H
@@ -10544,9 +18667,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_rt.h linux-3.18.12/inc
+ spinlock_t name __cacheline_aligned_in_smp = __SPIN_LOCK_UNLOCKED(name)
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/srcu.h linux-3.18.12/include/linux/srcu.h
---- linux-3.18.12.orig/include/linux/srcu.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/srcu.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/srcu.h linux-3.18.14-rt/include/linux/srcu.h
+--- linux-3.18.14.orig/include/linux/srcu.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/srcu.h 2015-05-31 15:32:48.445635367 -0500
@@ -84,10 +84,10 @@
void process_srcu(struct work_struct *work);
@@ -10575,9 +18698,9 @@ diff -Nur linux-3.18.12.orig/include/linux/srcu.h linux-3.18.12/include/linux/sr
/**
* call_srcu() - Queue a callback for invocation after an SRCU grace period
-diff -Nur linux-3.18.12.orig/include/linux/swap.h linux-3.18.12/include/linux/swap.h
---- linux-3.18.12.orig/include/linux/swap.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/swap.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/swap.h linux-3.18.14-rt/include/linux/swap.h
+--- linux-3.18.14.orig/include/linux/swap.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/swap.h 2015-05-31 15:32:48.449635367 -0500
@@ -11,6 +11,7 @@
#include <linux/fs.h>
#include <linux/atomic.h>
@@ -10596,9 +18719,9 @@ diff -Nur linux-3.18.12.orig/include/linux/swap.h linux-3.18.12/include/linux/sw
static inline unsigned int workingset_node_pages(struct radix_tree_node *node)
{
-diff -Nur linux-3.18.12.orig/include/linux/sysctl.h linux-3.18.12/include/linux/sysctl.h
---- linux-3.18.12.orig/include/linux/sysctl.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/sysctl.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/sysctl.h linux-3.18.14-rt/include/linux/sysctl.h
+--- linux-3.18.14.orig/include/linux/sysctl.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/sysctl.h 2015-05-31 15:32:48.449635367 -0500
@@ -25,6 +25,7 @@
#include <linux/rcupdate.h>
#include <linux/wait.h>
@@ -10607,9 +18730,9 @@ diff -Nur linux-3.18.12.orig/include/linux/sysctl.h linux-3.18.12/include/linux/
#include <uapi/linux/sysctl.h>
/* For the /proc/sys support */
-diff -Nur linux-3.18.12.orig/include/linux/thread_info.h linux-3.18.12/include/linux/thread_info.h
---- linux-3.18.12.orig/include/linux/thread_info.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/thread_info.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/thread_info.h linux-3.18.14-rt/include/linux/thread_info.h
+--- linux-3.18.14.orig/include/linux/thread_info.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/thread_info.h 2015-05-31 15:32:48.449635367 -0500
@@ -102,7 +102,17 @@
#define test_thread_flag(flag) \
test_ti_thread_flag(current_thread_info(), flag)
@@ -10629,9 +18752,9 @@ diff -Nur linux-3.18.12.orig/include/linux/thread_info.h linux-3.18.12/include/l
#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
/*
-diff -Nur linux-3.18.12.orig/include/linux/timer.h linux-3.18.12/include/linux/timer.h
---- linux-3.18.12.orig/include/linux/timer.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/timer.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/timer.h linux-3.18.14-rt/include/linux/timer.h
+--- linux-3.18.14.orig/include/linux/timer.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/timer.h 2015-05-31 15:32:48.449635367 -0500
@@ -241,7 +241,7 @@
extern int try_to_del_timer_sync(struct timer_list *timer);
@@ -10641,9 +18764,9 @@ diff -Nur linux-3.18.12.orig/include/linux/timer.h linux-3.18.12/include/linux/t
extern int del_timer_sync(struct timer_list *timer);
#else
# define del_timer_sync(t) del_timer(t)
-diff -Nur linux-3.18.12.orig/include/linux/uaccess.h linux-3.18.12/include/linux/uaccess.h
---- linux-3.18.12.orig/include/linux/uaccess.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/uaccess.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/uaccess.h linux-3.18.14-rt/include/linux/uaccess.h
+--- linux-3.18.14.orig/include/linux/uaccess.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/uaccess.h 2015-05-31 15:32:48.449635367 -0500
@@ -6,14 +6,9 @@
/*
@@ -10704,9 +18827,9 @@ diff -Nur linux-3.18.12.orig/include/linux/uaccess.h linux-3.18.12/include/linux
set_fs(old_fs); \
ret; \
})
-diff -Nur linux-3.18.12.orig/include/linux/uprobes.h linux-3.18.12/include/linux/uprobes.h
---- linux-3.18.12.orig/include/linux/uprobes.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/uprobes.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/uprobes.h linux-3.18.14-rt/include/linux/uprobes.h
+--- linux-3.18.14.orig/include/linux/uprobes.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/uprobes.h 2015-05-31 15:32:48.481635367 -0500
@@ -27,6 +27,7 @@
#include <linux/errno.h>
#include <linux/rbtree.h>
@@ -10715,9 +18838,9 @@ diff -Nur linux-3.18.12.orig/include/linux/uprobes.h linux-3.18.12/include/linux
struct vm_area_struct;
struct mm_struct;
-diff -Nur linux-3.18.12.orig/include/linux/vmstat.h linux-3.18.12/include/linux/vmstat.h
---- linux-3.18.12.orig/include/linux/vmstat.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/vmstat.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/vmstat.h linux-3.18.14-rt/include/linux/vmstat.h
+--- linux-3.18.14.orig/include/linux/vmstat.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/vmstat.h 2015-05-31 15:32:48.481635367 -0500
@@ -33,7 +33,9 @@
*/
static inline void __count_vm_event(enum vm_event_item item)
@@ -10738,9 +18861,9 @@ diff -Nur linux-3.18.12.orig/include/linux/vmstat.h linux-3.18.12/include/linux/
}
static inline void count_vm_events(enum vm_event_item item, long delta)
-diff -Nur linux-3.18.12.orig/include/linux/wait.h linux-3.18.12/include/linux/wait.h
---- linux-3.18.12.orig/include/linux/wait.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/linux/wait.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/wait.h linux-3.18.14-rt/include/linux/wait.h
+--- linux-3.18.14.orig/include/linux/wait.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/linux/wait.h 2015-05-31 15:32:48.481635367 -0500
@@ -8,6 +8,7 @@
#include <linux/spinlock.h>
#include <asm/current.h>
@@ -10749,9 +18872,9 @@ diff -Nur linux-3.18.12.orig/include/linux/wait.h linux-3.18.12/include/linux/wa
typedef struct __wait_queue wait_queue_t;
typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
-diff -Nur linux-3.18.12.orig/include/linux/wait-simple.h linux-3.18.12/include/linux/wait-simple.h
---- linux-3.18.12.orig/include/linux/wait-simple.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/wait-simple.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/wait-simple.h linux-3.18.14-rt/include/linux/wait-simple.h
+--- linux-3.18.14.orig/include/linux/wait-simple.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/wait-simple.h 2015-05-31 15:32:48.481635367 -0500
@@ -0,0 +1,207 @@
+#ifndef _LINUX_WAIT_SIMPLE_H
+#define _LINUX_WAIT_SIMPLE_H
@@ -10960,9 +19083,9 @@ diff -Nur linux-3.18.12.orig/include/linux/wait-simple.h linux-3.18.12/include/l
+})
+
+#endif
-diff -Nur linux-3.18.12.orig/include/linux/work-simple.h linux-3.18.12/include/linux/work-simple.h
---- linux-3.18.12.orig/include/linux/work-simple.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/linux/work-simple.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/linux/work-simple.h linux-3.18.14-rt/include/linux/work-simple.h
+--- linux-3.18.14.orig/include/linux/work-simple.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/linux/work-simple.h 2015-05-31 15:32:48.481635367 -0500
@@ -0,0 +1,24 @@
+#ifndef _LINUX_SWORK_H
+#define _LINUX_SWORK_H
@@ -10988,9 +19111,9 @@ diff -Nur linux-3.18.12.orig/include/linux/work-simple.h linux-3.18.12/include/l
+void swork_put(void);
+
+#endif /* _LINUX_SWORK_H */
-diff -Nur linux-3.18.12.orig/include/net/dst.h linux-3.18.12/include/net/dst.h
---- linux-3.18.12.orig/include/net/dst.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/net/dst.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/net/dst.h linux-3.18.14-rt/include/net/dst.h
+--- linux-3.18.14.orig/include/net/dst.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/net/dst.h 2015-05-31 15:32:48.497635366 -0500
@@ -403,7 +403,7 @@
static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
struct sk_buff *skb)
@@ -11000,9 +19123,9 @@ diff -Nur linux-3.18.12.orig/include/net/dst.h linux-3.18.12/include/net/dst.h
if (dst->pending_confirm) {
unsigned long now = jiffies;
-diff -Nur linux-3.18.12.orig/include/net/neighbour.h linux-3.18.12/include/net/neighbour.h
---- linux-3.18.12.orig/include/net/neighbour.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/net/neighbour.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/net/neighbour.h linux-3.18.14-rt/include/net/neighbour.h
+--- linux-3.18.14.orig/include/net/neighbour.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/net/neighbour.h 2015-05-31 15:32:48.521635366 -0500
@@ -387,7 +387,7 @@
}
#endif
@@ -11021,9 +19144,9 @@ diff -Nur linux-3.18.12.orig/include/net/neighbour.h linux-3.18.12/include/net/n
const struct net_device *dev)
{
unsigned int seq;
-diff -Nur linux-3.18.12.orig/include/net/netns/ipv4.h linux-3.18.12/include/net/netns/ipv4.h
---- linux-3.18.12.orig/include/net/netns/ipv4.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/include/net/netns/ipv4.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/net/netns/ipv4.h linux-3.18.14-rt/include/net/netns/ipv4.h
+--- linux-3.18.14.orig/include/net/netns/ipv4.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/include/net/netns/ipv4.h 2015-05-31 15:32:48.521635366 -0500
@@ -67,6 +67,7 @@
int sysctl_icmp_echo_ignore_all;
@@ -11032,9 +19155,9 @@ diff -Nur linux-3.18.12.orig/include/net/netns/ipv4.h linux-3.18.12/include/net/
int sysctl_icmp_ignore_bogus_error_responses;
int sysctl_icmp_ratelimit;
int sysctl_icmp_ratemask;
-diff -Nur linux-3.18.12.orig/include/trace/events/hist.h linux-3.18.12/include/trace/events/hist.h
---- linux-3.18.12.orig/include/trace/events/hist.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/trace/events/hist.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/trace/events/hist.h linux-3.18.14-rt/include/trace/events/hist.h
+--- linux-3.18.14.orig/include/trace/events/hist.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/trace/events/hist.h 2015-05-31 15:32:48.521635366 -0500
@@ -0,0 +1,72 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hist
@@ -11108,9 +19231,9 @@ diff -Nur linux-3.18.12.orig/include/trace/events/hist.h linux-3.18.12/include/t
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-diff -Nur linux-3.18.12.orig/include/trace/events/latency_hist.h linux-3.18.12/include/trace/events/latency_hist.h
---- linux-3.18.12.orig/include/trace/events/latency_hist.h 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/include/trace/events/latency_hist.h 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/include/trace/events/latency_hist.h linux-3.18.14-rt/include/trace/events/latency_hist.h
+--- linux-3.18.14.orig/include/trace/events/latency_hist.h 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/include/trace/events/latency_hist.h 2015-05-31 15:32:48.521635366 -0500
@@ -0,0 +1,29 @@
+#ifndef _LATENCY_HIST_H
+#define _LATENCY_HIST_H
@@ -11141,9 +19264,9 @@ diff -Nur linux-3.18.12.orig/include/trace/events/latency_hist.h linux-3.18.12/i
+}
+
+#endif /* _LATENCY_HIST_H */
-diff -Nur linux-3.18.12.orig/init/Kconfig linux-3.18.12/init/Kconfig
---- linux-3.18.12.orig/init/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/init/Kconfig 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/init/Kconfig linux-3.18.14-rt/init/Kconfig
+--- linux-3.18.14.orig/init/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/init/Kconfig 2015-05-31 15:32:48.525635366 -0500
@@ -635,7 +635,7 @@
config RCU_FAST_NO_HZ
@@ -11186,9 +19309,9 @@ diff -Nur linux-3.18.12.orig/init/Kconfig linux-3.18.12/init/Kconfig
help
SLOB replaces the stock allocator with a drastically simpler
allocator. SLOB is generally more space efficient but
-diff -Nur linux-3.18.12.orig/init/main.c linux-3.18.12/init/main.c
---- linux-3.18.12.orig/init/main.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/init/main.c 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/init/main.c linux-3.18.14-rt/init/main.c
+--- linux-3.18.14.orig/init/main.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/init/main.c 2015-05-31 15:32:48.545635366 -0500
@@ -533,6 +533,7 @@
setup_command_line(command_line);
setup_nr_cpu_ids();
@@ -11197,18 +19320,18 @@ diff -Nur linux-3.18.12.orig/init/main.c linux-3.18.12/init/main.c
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
build_all_zonelists(NULL, NULL);
-diff -Nur linux-3.18.12.orig/init/Makefile linux-3.18.12/init/Makefile
---- linux-3.18.12.orig/init/Makefile 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/init/Makefile 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/init/Makefile linux-3.18.14-rt/init/Makefile
+--- linux-3.18.14.orig/init/Makefile 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/init/Makefile 2015-05-31 15:32:48.525635366 -0500
@@ -33,4 +33,4 @@
include/generated/compile.h: FORCE
@$($(quiet)chk_compile.h)
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
- "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
+ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CONFIG_PREEMPT_RT_FULL)" "$(CC) $(KBUILD_CFLAGS)"
-diff -Nur linux-3.18.12.orig/ipc/mqueue.c linux-3.18.12/ipc/mqueue.c
---- linux-3.18.12.orig/ipc/mqueue.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/ipc/mqueue.c 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/ipc/mqueue.c linux-3.18.14-rt/ipc/mqueue.c
+--- linux-3.18.14.orig/ipc/mqueue.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/ipc/mqueue.c 2015-05-31 15:32:48.557635366 -0500
@@ -923,12 +923,17 @@
struct msg_msg *message,
struct ext_wait_queue *receiver)
@@ -11253,9 +19376,9 @@ diff -Nur linux-3.18.12.orig/ipc/mqueue.c linux-3.18.12/ipc/mqueue.c
}
SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
-diff -Nur linux-3.18.12.orig/ipc/msg.c linux-3.18.12/ipc/msg.c
---- linux-3.18.12.orig/ipc/msg.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/ipc/msg.c 2015-04-26 13:32:22.427684003 -0500
+diff -Nur linux-3.18.14.orig/ipc/msg.c linux-3.18.14-rt/ipc/msg.c
+--- linux-3.18.14.orig/ipc/msg.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/ipc/msg.c 2015-05-31 15:32:48.577635366 -0500
@@ -188,6 +188,12 @@
struct msg_receiver *msr, *t;
@@ -11305,9 +19428,9 @@ diff -Nur linux-3.18.12.orig/ipc/msg.c linux-3.18.12/ipc/msg.c
return 0;
}
-diff -Nur linux-3.18.12.orig/ipc/sem.c linux-3.18.12/ipc/sem.c
---- linux-3.18.12.orig/ipc/sem.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/ipc/sem.c 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/ipc/sem.c linux-3.18.14-rt/ipc/sem.c
+--- linux-3.18.14.orig/ipc/sem.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/ipc/sem.c 2015-05-31 15:32:48.577635366 -0500
@@ -673,6 +673,13 @@
static void wake_up_sem_queue_prepare(struct list_head *pt,
struct sem_queue *q, int error)
@@ -11346,9 +19469,9 @@ diff -Nur linux-3.18.12.orig/ipc/sem.c linux-3.18.12/ipc/sem.c
}
static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
-diff -Nur linux-3.18.12.orig/kernel/cgroup.c linux-3.18.12/kernel/cgroup.c
---- linux-3.18.12.orig/kernel/cgroup.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/cgroup.c 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/cgroup.c linux-3.18.14-rt/kernel/cgroup.c
+--- linux-3.18.14.orig/kernel/cgroup.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/cgroup.c 2015-05-31 15:32:48.597635365 -0500
@@ -4355,10 +4355,10 @@
queue_work(cgroup_destroy_wq, &css->destroy_work);
}
@@ -11381,9 +19504,9 @@ diff -Nur linux-3.18.12.orig/kernel/cgroup.c linux-3.18.12/kernel/cgroup.c
/*
* Used to destroy pidlists and separate to serve as flush domain.
-diff -Nur linux-3.18.12.orig/kernel/cpu.c linux-3.18.12/kernel/cpu.c
---- linux-3.18.12.orig/kernel/cpu.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/cpu.c 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/cpu.c linux-3.18.14-rt/kernel/cpu.c
+--- linux-3.18.14.orig/kernel/cpu.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/cpu.c 2015-05-31 15:32:48.601635365 -0500
@@ -86,6 +86,290 @@
#define cpuhp_lock_acquire() lock_map_acquire(&cpu_hotplug.dep_map)
#define cpuhp_lock_release() lock_map_release(&cpu_hotplug.dep_map)
@@ -11763,9 +19886,9 @@ diff -Nur linux-3.18.12.orig/kernel/cpu.c linux-3.18.12/kernel/cpu.c
return err;
}
-diff -Nur linux-3.18.12.orig/kernel/debug/kdb/kdb_io.c linux-3.18.12/kernel/debug/kdb/kdb_io.c
---- linux-3.18.12.orig/kernel/debug/kdb/kdb_io.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/debug/kdb/kdb_io.c 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/debug/kdb/kdb_io.c linux-3.18.14-rt/kernel/debug/kdb/kdb_io.c
+--- linux-3.18.14.orig/kernel/debug/kdb/kdb_io.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/debug/kdb/kdb_io.c 2015-05-31 15:32:48.605635366 -0500
@@ -554,7 +554,6 @@
int linecount;
int colcount;
@@ -11803,9 +19926,9 @@ diff -Nur linux-3.18.12.orig/kernel/debug/kdb/kdb_io.c linux-3.18.12/kernel/debu
return r;
}
-diff -Nur linux-3.18.12.orig/kernel/events/core.c linux-3.18.12/kernel/events/core.c
---- linux-3.18.12.orig/kernel/events/core.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/events/core.c 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/events/core.c linux-3.18.14-rt/kernel/events/core.c
+--- linux-3.18.14.orig/kernel/events/core.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/events/core.c 2015-05-31 15:32:48.637635365 -0500
@@ -6346,6 +6346,7 @@
hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -11814,8352 +19937,9 @@ diff -Nur linux-3.18.12.orig/kernel/events/core.c linux-3.18.12/kernel/events/co
/*
* Since hrtimers have a fixed rate, we can do a static freq->period
-diff -Nur linux-3.18.12.orig/kernel/events/core.c.orig linux-3.18.12/kernel/events/core.c.orig
---- linux-3.18.12.orig/kernel/events/core.c.orig 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/kernel/events/core.c.orig 2015-04-20 14:48:02.000000000 -0500
-@@ -0,0 +1,8339 @@
-+/*
-+ * Performance events core code:
-+ *
-+ * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
-+ * Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
-+ * Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
-+ * Copyright © 2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
-+ *
-+ * For licensing details see kernel-base/COPYING
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/cpu.h>
-+#include <linux/smp.h>
-+#include <linux/idr.h>
-+#include <linux/file.h>
-+#include <linux/poll.h>
-+#include <linux/slab.h>
-+#include <linux/hash.h>
-+#include <linux/tick.h>
-+#include <linux/sysfs.h>
-+#include <linux/dcache.h>
-+#include <linux/percpu.h>
-+#include <linux/ptrace.h>
-+#include <linux/reboot.h>
-+#include <linux/vmstat.h>
-+#include <linux/device.h>
-+#include <linux/export.h>
-+#include <linux/vmalloc.h>
-+#include <linux/hardirq.h>
-+#include <linux/rculist.h>
-+#include <linux/uaccess.h>
-+#include <linux/syscalls.h>
-+#include <linux/anon_inodes.h>
-+#include <linux/kernel_stat.h>
-+#include <linux/perf_event.h>
-+#include <linux/ftrace_event.h>
-+#include <linux/hw_breakpoint.h>
-+#include <linux/mm_types.h>
-+#include <linux/cgroup.h>
-+#include <linux/module.h>
-+#include <linux/mman.h>
-+#include <linux/compat.h>
-+
-+#include "internal.h"
-+
-+#include <asm/irq_regs.h>
-+
-+static struct workqueue_struct *perf_wq;
-+
-+struct remote_function_call {
-+ struct task_struct *p;
-+ int (*func)(void *info);
-+ void *info;
-+ int ret;
-+};
-+
-+static void remote_function(void *data)
-+{
-+ struct remote_function_call *tfc = data;
-+ struct task_struct *p = tfc->p;
-+
-+ if (p) {
-+ tfc->ret = -EAGAIN;
-+ if (task_cpu(p) != smp_processor_id() || !task_curr(p))
-+ return;
-+ }
-+
-+ tfc->ret = tfc->func(tfc->info);
-+}
-+
-+/**
-+ * task_function_call - call a function on the cpu on which a task runs
-+ * @p: the task to evaluate
-+ * @func: the function to be called
-+ * @info: the function call argument
-+ *
-+ * Calls the function @func when the task is currently running. This might
-+ * be on the current CPU, which just calls the function directly
-+ *
-+ * returns: @func return value, or
-+ * -ESRCH - when the process isn't running
-+ * -EAGAIN - when the process moved away
-+ */
-+static int
-+task_function_call(struct task_struct *p, int (*func) (void *info), void *info)
-+{
-+ struct remote_function_call data = {
-+ .p = p,
-+ .func = func,
-+ .info = info,
-+ .ret = -ESRCH, /* No such (running) process */
-+ };
-+
-+ if (task_curr(p))
-+ smp_call_function_single(task_cpu(p), remote_function, &data, 1);
-+
-+ return data.ret;
-+}
-+
-+/**
-+ * cpu_function_call - call a function on the cpu
-+ * @func: the function to be called
-+ * @info: the function call argument
-+ *
-+ * Calls the function @func on the remote cpu.
-+ *
-+ * returns: @func return value or -ENXIO when the cpu is offline
-+ */
-+static int cpu_function_call(int cpu, int (*func) (void *info), void *info)
-+{
-+ struct remote_function_call data = {
-+ .p = NULL,
-+ .func = func,
-+ .info = info,
-+ .ret = -ENXIO, /* No such CPU */
-+ };
-+
-+ smp_call_function_single(cpu, remote_function, &data, 1);
-+
-+ return data.ret;
-+}
-+
-+#define EVENT_OWNER_KERNEL ((void *) -1)
-+
-+static bool is_kernel_event(struct perf_event *event)
-+{
-+ return event->owner == EVENT_OWNER_KERNEL;
-+}
-+
-+#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\
-+ PERF_FLAG_FD_OUTPUT |\
-+ PERF_FLAG_PID_CGROUP |\
-+ PERF_FLAG_FD_CLOEXEC)
-+
-+/*
-+ * branch priv levels that need permission checks
-+ */
-+#define PERF_SAMPLE_BRANCH_PERM_PLM \
-+ (PERF_SAMPLE_BRANCH_KERNEL |\
-+ PERF_SAMPLE_BRANCH_HV)
-+
-+enum event_type_t {
-+ EVENT_FLEXIBLE = 0x1,
-+ EVENT_PINNED = 0x2,
-+ EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
-+};
-+
-+/*
-+ * perf_sched_events : >0 events exist
-+ * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
-+ */
-+struct static_key_deferred perf_sched_events __read_mostly;
-+static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
-+static DEFINE_PER_CPU(atomic_t, perf_branch_stack_events);
-+
-+static atomic_t nr_mmap_events __read_mostly;
-+static atomic_t nr_comm_events __read_mostly;
-+static atomic_t nr_task_events __read_mostly;
-+static atomic_t nr_freq_events __read_mostly;
-+
-+static LIST_HEAD(pmus);
-+static DEFINE_MUTEX(pmus_lock);
-+static struct srcu_struct pmus_srcu;
-+
-+/*
-+ * perf event paranoia level:
-+ * -1 - not paranoid at all
-+ * 0 - disallow raw tracepoint access for unpriv
-+ * 1 - disallow cpu events for unpriv
-+ * 2 - disallow kernel profiling for unpriv
-+ */
-+int sysctl_perf_event_paranoid __read_mostly = 1;
-+
-+/* Minimum for 512 kiB + 1 user control page */
-+int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
-+
-+/*
-+ * max perf event sample rate
-+ */
-+#define DEFAULT_MAX_SAMPLE_RATE 100000
-+#define DEFAULT_SAMPLE_PERIOD_NS (NSEC_PER_SEC / DEFAULT_MAX_SAMPLE_RATE)
-+#define DEFAULT_CPU_TIME_MAX_PERCENT 25
-+
-+int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE;
-+
-+static int max_samples_per_tick __read_mostly = DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ);
-+static int perf_sample_period_ns __read_mostly = DEFAULT_SAMPLE_PERIOD_NS;
-+
-+static int perf_sample_allowed_ns __read_mostly =
-+ DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100;
-+
-+void update_perf_cpu_limits(void)
-+{
-+ u64 tmp = perf_sample_period_ns;
-+
-+ tmp *= sysctl_perf_cpu_time_max_percent;
-+ do_div(tmp, 100);
-+ ACCESS_ONCE(perf_sample_allowed_ns) = tmp;
-+}
-+
-+static int perf_rotate_context(struct perf_cpu_context *cpuctx);
-+
-+int perf_proc_update_handler(struct ctl_table *table, int write,
-+ void __user *buffer, size_t *lenp,
-+ loff_t *ppos)
-+{
-+ int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
-+
-+ if (ret || !write)
-+ return ret;
-+
-+ max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
-+ perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
-+ update_perf_cpu_limits();
-+
-+ return 0;
-+}
-+
-+int sysctl_perf_cpu_time_max_percent __read_mostly = DEFAULT_CPU_TIME_MAX_PERCENT;
-+
-+int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
-+ void __user *buffer, size_t *lenp,
-+ loff_t *ppos)
-+{
-+ int ret = proc_dointvec(table, write, buffer, lenp, ppos);
-+
-+ if (ret || !write)
-+ return ret;
-+
-+ update_perf_cpu_limits();
-+
-+ return 0;
-+}
-+
-+/*
-+ * perf samples are done in some very critical code paths (NMIs).
-+ * If they take too much CPU time, the system can lock up and not
-+ * get any real work done. This will drop the sample rate when
-+ * we detect that events are taking too long.
-+ */
-+#define NR_ACCUMULATED_SAMPLES 128
-+static DEFINE_PER_CPU(u64, running_sample_length);
-+
-+static void perf_duration_warn(struct irq_work *w)
-+{
-+ u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
-+ u64 avg_local_sample_len;
-+ u64 local_samples_len;
-+
-+ local_samples_len = __this_cpu_read(running_sample_length);
-+ avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
-+
-+ printk_ratelimited(KERN_WARNING
-+ "perf interrupt took too long (%lld > %lld), lowering "
-+ "kernel.perf_event_max_sample_rate to %d\n",
-+ avg_local_sample_len, allowed_ns >> 1,
-+ sysctl_perf_event_sample_rate);
-+}
-+
-+static DEFINE_IRQ_WORK(perf_duration_work, perf_duration_warn);
-+
-+void perf_sample_event_took(u64 sample_len_ns)
-+{
-+ u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
-+ u64 avg_local_sample_len;
-+ u64 local_samples_len;
-+
-+ if (allowed_ns == 0)
-+ return;
-+
-+ /* decay the counter by 1 average sample */
-+ local_samples_len = __this_cpu_read(running_sample_length);
-+ local_samples_len -= local_samples_len/NR_ACCUMULATED_SAMPLES;
-+ local_samples_len += sample_len_ns;
-+ __this_cpu_write(running_sample_length, local_samples_len);
-+
-+ /*
-+ * note: this will be biased artifically low until we have
-+ * seen NR_ACCUMULATED_SAMPLES. Doing it this way keeps us
-+ * from having to maintain a count.
-+ */
-+ avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
-+
-+ if (avg_local_sample_len <= allowed_ns)
-+ return;
-+
-+ if (max_samples_per_tick <= 1)
-+ return;
-+
-+ max_samples_per_tick = DIV_ROUND_UP(max_samples_per_tick, 2);
-+ sysctl_perf_event_sample_rate = max_samples_per_tick * HZ;
-+ perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
-+
-+ update_perf_cpu_limits();
-+
-+ if (!irq_work_queue(&perf_duration_work)) {
-+ early_printk("perf interrupt took too long (%lld > %lld), lowering "
-+ "kernel.perf_event_max_sample_rate to %d\n",
-+ avg_local_sample_len, allowed_ns >> 1,
-+ sysctl_perf_event_sample_rate);
-+ }
-+}
-+
-+static atomic64_t perf_event_id;
-+
-+static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type);
-+
-+static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type,
-+ struct task_struct *task);
-+
-+static void update_context_time(struct perf_event_context *ctx);
-+static u64 perf_event_time(struct perf_event *event);
-+
-+void __weak perf_event_print_debug(void) { }
-+
-+extern __weak const char *perf_pmu_name(void)
-+{
-+ return "pmu";
-+}
-+
-+static inline u64 perf_clock(void)
-+{
-+ return local_clock();
-+}
-+
-+static inline struct perf_cpu_context *
-+__get_cpu_context(struct perf_event_context *ctx)
-+{
-+ return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
-+}
-+
-+static void perf_ctx_lock(struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx)
-+{
-+ raw_spin_lock(&cpuctx->ctx.lock);
-+ if (ctx)
-+ raw_spin_lock(&ctx->lock);
-+}
-+
-+static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx)
-+{
-+ if (ctx)
-+ raw_spin_unlock(&ctx->lock);
-+ raw_spin_unlock(&cpuctx->ctx.lock);
-+}
-+
-+#ifdef CONFIG_CGROUP_PERF
-+
-+/*
-+ * perf_cgroup_info keeps track of time_enabled for a cgroup.
-+ * This is a per-cpu dynamically allocated data structure.
-+ */
-+struct perf_cgroup_info {
-+ u64 time;
-+ u64 timestamp;
-+};
-+
-+struct perf_cgroup {
-+ struct cgroup_subsys_state css;
-+ struct perf_cgroup_info __percpu *info;
-+};
-+
-+/*
-+ * Must ensure cgroup is pinned (css_get) before calling
-+ * this function. In other words, we cannot call this function
-+ * if there is no cgroup event for the current CPU context.
-+ */
-+static inline struct perf_cgroup *
-+perf_cgroup_from_task(struct task_struct *task)
-+{
-+ return container_of(task_css(task, perf_event_cgrp_id),
-+ struct perf_cgroup, css);
-+}
-+
-+static inline bool
-+perf_cgroup_match(struct perf_event *event)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+
-+ /* @event doesn't care about cgroup */
-+ if (!event->cgrp)
-+ return true;
-+
-+ /* wants specific cgroup scope but @cpuctx isn't associated with any */
-+ if (!cpuctx->cgrp)
-+ return false;
-+
-+ /*
-+ * Cgroup scoping is recursive. An event enabled for a cgroup is
-+ * also enabled for all its descendant cgroups. If @cpuctx's
-+ * cgroup is a descendant of @event's (the test covers identity
-+ * case), it's a match.
-+ */
-+ return cgroup_is_descendant(cpuctx->cgrp->css.cgroup,
-+ event->cgrp->css.cgroup);
-+}
-+
-+static inline void perf_detach_cgroup(struct perf_event *event)
-+{
-+ css_put(&event->cgrp->css);
-+ event->cgrp = NULL;
-+}
-+
-+static inline int is_cgroup_event(struct perf_event *event)
-+{
-+ return event->cgrp != NULL;
-+}
-+
-+static inline u64 perf_cgroup_event_time(struct perf_event *event)
-+{
-+ struct perf_cgroup_info *t;
-+
-+ t = per_cpu_ptr(event->cgrp->info, event->cpu);
-+ return t->time;
-+}
-+
-+static inline void __update_cgrp_time(struct perf_cgroup *cgrp)
-+{
-+ struct perf_cgroup_info *info;
-+ u64 now;
-+
-+ now = perf_clock();
-+
-+ info = this_cpu_ptr(cgrp->info);
-+
-+ info->time += now - info->timestamp;
-+ info->timestamp = now;
-+}
-+
-+static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
-+{
-+ struct perf_cgroup *cgrp_out = cpuctx->cgrp;
-+ if (cgrp_out)
-+ __update_cgrp_time(cgrp_out);
-+}
-+
-+static inline void update_cgrp_time_from_event(struct perf_event *event)
-+{
-+ struct perf_cgroup *cgrp;
-+
-+ /*
-+ * ensure we access cgroup data only when needed and
-+ * when we know the cgroup is pinned (css_get)
-+ */
-+ if (!is_cgroup_event(event))
-+ return;
-+
-+ cgrp = perf_cgroup_from_task(current);
-+ /*
-+ * Do not update time when cgroup is not active
-+ */
-+ if (cgrp == event->cgrp)
-+ __update_cgrp_time(event->cgrp);
-+}
-+
-+static inline void
-+perf_cgroup_set_timestamp(struct task_struct *task,
-+ struct perf_event_context *ctx)
-+{
-+ struct perf_cgroup *cgrp;
-+ struct perf_cgroup_info *info;
-+
-+ /*
-+ * ctx->lock held by caller
-+ * ensure we do not access cgroup data
-+ * unless we have the cgroup pinned (css_get)
-+ */
-+ if (!task || !ctx->nr_cgroups)
-+ return;
-+
-+ cgrp = perf_cgroup_from_task(task);
-+ info = this_cpu_ptr(cgrp->info);
-+ info->timestamp = ctx->timestamp;
-+}
-+
-+#define PERF_CGROUP_SWOUT 0x1 /* cgroup switch out every event */
-+#define PERF_CGROUP_SWIN 0x2 /* cgroup switch in events based on task */
-+
-+/*
-+ * reschedule events based on the cgroup constraint of task.
-+ *
-+ * mode SWOUT : schedule out everything
-+ * mode SWIN : schedule in based on cgroup for next
-+ */
-+void perf_cgroup_switch(struct task_struct *task, int mode)
-+{
-+ struct perf_cpu_context *cpuctx;
-+ struct pmu *pmu;
-+ unsigned long flags;
-+
-+ /*
-+ * disable interrupts to avoid geting nr_cgroup
-+ * changes via __perf_event_disable(). Also
-+ * avoids preemption.
-+ */
-+ local_irq_save(flags);
-+
-+ /*
-+ * we reschedule only in the presence of cgroup
-+ * constrained events.
-+ */
-+ rcu_read_lock();
-+
-+ list_for_each_entry_rcu(pmu, &pmus, entry) {
-+ cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
-+ if (cpuctx->unique_pmu != pmu)
-+ continue; /* ensure we process each cpuctx once */
-+
-+ /*
-+ * perf_cgroup_events says at least one
-+ * context on this CPU has cgroup events.
-+ *
-+ * ctx->nr_cgroups reports the number of cgroup
-+ * events for a context.
-+ */
-+ if (cpuctx->ctx.nr_cgroups > 0) {
-+ perf_ctx_lock(cpuctx, cpuctx->task_ctx);
-+ perf_pmu_disable(cpuctx->ctx.pmu);
-+
-+ if (mode & PERF_CGROUP_SWOUT) {
-+ cpu_ctx_sched_out(cpuctx, EVENT_ALL);
-+ /*
-+ * must not be done before ctxswout due
-+ * to event_filter_match() in event_sched_out()
-+ */
-+ cpuctx->cgrp = NULL;
-+ }
-+
-+ if (mode & PERF_CGROUP_SWIN) {
-+ WARN_ON_ONCE(cpuctx->cgrp);
-+ /*
-+ * set cgrp before ctxsw in to allow
-+ * event_filter_match() to not have to pass
-+ * task around
-+ */
-+ cpuctx->cgrp = perf_cgroup_from_task(task);
-+ cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
-+ }
-+ perf_pmu_enable(cpuctx->ctx.pmu);
-+ perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-+ }
-+ }
-+
-+ rcu_read_unlock();
-+
-+ local_irq_restore(flags);
-+}
-+
-+static inline void perf_cgroup_sched_out(struct task_struct *task,
-+ struct task_struct *next)
-+{
-+ struct perf_cgroup *cgrp1;
-+ struct perf_cgroup *cgrp2 = NULL;
-+
-+ /*
-+ * we come here when we know perf_cgroup_events > 0
-+ */
-+ cgrp1 = perf_cgroup_from_task(task);
-+
-+ /*
-+ * next is NULL when called from perf_event_enable_on_exec()
-+ * that will systematically cause a cgroup_switch()
-+ */
-+ if (next)
-+ cgrp2 = perf_cgroup_from_task(next);
-+
-+ /*
-+ * only schedule out current cgroup events if we know
-+ * that we are switching to a different cgroup. Otherwise,
-+ * do no touch the cgroup events.
-+ */
-+ if (cgrp1 != cgrp2)
-+ perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
-+}
-+
-+static inline void perf_cgroup_sched_in(struct task_struct *prev,
-+ struct task_struct *task)
-+{
-+ struct perf_cgroup *cgrp1;
-+ struct perf_cgroup *cgrp2 = NULL;
-+
-+ /*
-+ * we come here when we know perf_cgroup_events > 0
-+ */
-+ cgrp1 = perf_cgroup_from_task(task);
-+
-+ /* prev can never be NULL */
-+ cgrp2 = perf_cgroup_from_task(prev);
-+
-+ /*
-+ * only need to schedule in cgroup events if we are changing
-+ * cgroup during ctxsw. Cgroup events were not scheduled
-+ * out of ctxsw out if that was not the case.
-+ */
-+ if (cgrp1 != cgrp2)
-+ perf_cgroup_switch(task, PERF_CGROUP_SWIN);
-+}
-+
-+static inline int perf_cgroup_connect(int fd, struct perf_event *event,
-+ struct perf_event_attr *attr,
-+ struct perf_event *group_leader)
-+{
-+ struct perf_cgroup *cgrp;
-+ struct cgroup_subsys_state *css;
-+ struct fd f = fdget(fd);
-+ int ret = 0;
-+
-+ if (!f.file)
-+ return -EBADF;
-+
-+ css = css_tryget_online_from_dir(f.file->f_dentry,
-+ &perf_event_cgrp_subsys);
-+ if (IS_ERR(css)) {
-+ ret = PTR_ERR(css);
-+ goto out;
-+ }
-+
-+ cgrp = container_of(css, struct perf_cgroup, css);
-+ event->cgrp = cgrp;
-+
-+ /*
-+ * all events in a group must monitor
-+ * the same cgroup because a task belongs
-+ * to only one perf cgroup at a time
-+ */
-+ if (group_leader && group_leader->cgrp != cgrp) {
-+ perf_detach_cgroup(event);
-+ ret = -EINVAL;
-+ }
-+out:
-+ fdput(f);
-+ return ret;
-+}
-+
-+static inline void
-+perf_cgroup_set_shadow_time(struct perf_event *event, u64 now)
-+{
-+ struct perf_cgroup_info *t;
-+ t = per_cpu_ptr(event->cgrp->info, event->cpu);
-+ event->shadow_ctx_time = now - t->timestamp;
-+}
-+
-+static inline void
-+perf_cgroup_defer_enabled(struct perf_event *event)
-+{
-+ /*
-+ * when the current task's perf cgroup does not match
-+ * the event's, we need to remember to call the
-+ * perf_mark_enable() function the first time a task with
-+ * a matching perf cgroup is scheduled in.
-+ */
-+ if (is_cgroup_event(event) && !perf_cgroup_match(event))
-+ event->cgrp_defer_enabled = 1;
-+}
-+
-+static inline void
-+perf_cgroup_mark_enabled(struct perf_event *event,
-+ struct perf_event_context *ctx)
-+{
-+ struct perf_event *sub;
-+ u64 tstamp = perf_event_time(event);
-+
-+ if (!event->cgrp_defer_enabled)
-+ return;
-+
-+ event->cgrp_defer_enabled = 0;
-+
-+ event->tstamp_enabled = tstamp - event->total_time_enabled;
-+ list_for_each_entry(sub, &event->sibling_list, group_entry) {
-+ if (sub->state >= PERF_EVENT_STATE_INACTIVE) {
-+ sub->tstamp_enabled = tstamp - sub->total_time_enabled;
-+ sub->cgrp_defer_enabled = 0;
-+ }
-+ }
-+}
-+#else /* !CONFIG_CGROUP_PERF */
-+
-+static inline bool
-+perf_cgroup_match(struct perf_event *event)
-+{
-+ return true;
-+}
-+
-+static inline void perf_detach_cgroup(struct perf_event *event)
-+{}
-+
-+static inline int is_cgroup_event(struct perf_event *event)
-+{
-+ return 0;
-+}
-+
-+static inline u64 perf_cgroup_event_cgrp_time(struct perf_event *event)
-+{
-+ return 0;
-+}
-+
-+static inline void update_cgrp_time_from_event(struct perf_event *event)
-+{
-+}
-+
-+static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
-+{
-+}
-+
-+static inline void perf_cgroup_sched_out(struct task_struct *task,
-+ struct task_struct *next)
-+{
-+}
-+
-+static inline void perf_cgroup_sched_in(struct task_struct *prev,
-+ struct task_struct *task)
-+{
-+}
-+
-+static inline int perf_cgroup_connect(pid_t pid, struct perf_event *event,
-+ struct perf_event_attr *attr,
-+ struct perf_event *group_leader)
-+{
-+ return -EINVAL;
-+}
-+
-+static inline void
-+perf_cgroup_set_timestamp(struct task_struct *task,
-+ struct perf_event_context *ctx)
-+{
-+}
-+
-+void
-+perf_cgroup_switch(struct task_struct *task, struct task_struct *next)
-+{
-+}
-+
-+static inline void
-+perf_cgroup_set_shadow_time(struct perf_event *event, u64 now)
-+{
-+}
-+
-+static inline u64 perf_cgroup_event_time(struct perf_event *event)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+perf_cgroup_defer_enabled(struct perf_event *event)
-+{
-+}
-+
-+static inline void
-+perf_cgroup_mark_enabled(struct perf_event *event,
-+ struct perf_event_context *ctx)
-+{
-+}
-+#endif
-+
-+/*
-+ * set default to be dependent on timer tick just
-+ * like original code
-+ */
-+#define PERF_CPU_HRTIMER (1000 / HZ)
-+/*
-+ * function must be called with interrupts disbled
-+ */
-+static enum hrtimer_restart perf_cpu_hrtimer_handler(struct hrtimer *hr)
-+{
-+ struct perf_cpu_context *cpuctx;
-+ enum hrtimer_restart ret = HRTIMER_NORESTART;
-+ int rotations = 0;
-+
-+ WARN_ON(!irqs_disabled());
-+
-+ cpuctx = container_of(hr, struct perf_cpu_context, hrtimer);
-+
-+ rotations = perf_rotate_context(cpuctx);
-+
-+ /*
-+ * arm timer if needed
-+ */
-+ if (rotations) {
-+ hrtimer_forward_now(hr, cpuctx->hrtimer_interval);
-+ ret = HRTIMER_RESTART;
-+ }
-+
-+ return ret;
-+}
-+
-+/* CPU is going down */
-+void perf_cpu_hrtimer_cancel(int cpu)
-+{
-+ struct perf_cpu_context *cpuctx;
-+ struct pmu *pmu;
-+ unsigned long flags;
-+
-+ if (WARN_ON(cpu != smp_processor_id()))
-+ return;
-+
-+ local_irq_save(flags);
-+
-+ rcu_read_lock();
-+
-+ list_for_each_entry_rcu(pmu, &pmus, entry) {
-+ cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
-+
-+ if (pmu->task_ctx_nr == perf_sw_context)
-+ continue;
-+
-+ hrtimer_cancel(&cpuctx->hrtimer);
-+ }
-+
-+ rcu_read_unlock();
-+
-+ local_irq_restore(flags);
-+}
-+
-+static void __perf_cpu_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu)
-+{
-+ struct hrtimer *hr = &cpuctx->hrtimer;
-+ struct pmu *pmu = cpuctx->ctx.pmu;
-+ int timer;
-+
-+ /* no multiplexing needed for SW PMU */
-+ if (pmu->task_ctx_nr == perf_sw_context)
-+ return;
-+
-+ /*
-+ * check default is sane, if not set then force to
-+ * default interval (1/tick)
-+ */
-+ timer = pmu->hrtimer_interval_ms;
-+ if (timer < 1)
-+ timer = pmu->hrtimer_interval_ms = PERF_CPU_HRTIMER;
-+
-+ cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer);
-+
-+ hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
-+ hr->function = perf_cpu_hrtimer_handler;
-+}
-+
-+static void perf_cpu_hrtimer_restart(struct perf_cpu_context *cpuctx)
-+{
-+ struct hrtimer *hr = &cpuctx->hrtimer;
-+ struct pmu *pmu = cpuctx->ctx.pmu;
-+
-+ /* not for SW PMU */
-+ if (pmu->task_ctx_nr == perf_sw_context)
-+ return;
-+
-+ if (hrtimer_active(hr))
-+ return;
-+
-+ if (!hrtimer_callback_running(hr))
-+ __hrtimer_start_range_ns(hr, cpuctx->hrtimer_interval,
-+ 0, HRTIMER_MODE_REL_PINNED, 0);
-+}
-+
-+void perf_pmu_disable(struct pmu *pmu)
-+{
-+ int *count = this_cpu_ptr(pmu->pmu_disable_count);
-+ if (!(*count)++)
-+ pmu->pmu_disable(pmu);
-+}
-+
-+void perf_pmu_enable(struct pmu *pmu)
-+{
-+ int *count = this_cpu_ptr(pmu->pmu_disable_count);
-+ if (!--(*count))
-+ pmu->pmu_enable(pmu);
-+}
-+
-+static DEFINE_PER_CPU(struct list_head, rotation_list);
-+
-+/*
-+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized
-+ * because they're strictly cpu affine and rotate_start is called with IRQs
-+ * disabled, while rotate_context is called from IRQ context.
-+ */
-+static void perf_pmu_rotate_start(struct pmu *pmu)
-+{
-+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
-+ struct list_head *head = this_cpu_ptr(&rotation_list);
-+
-+ WARN_ON(!irqs_disabled());
-+
-+ if (list_empty(&cpuctx->rotation_list))
-+ list_add(&cpuctx->rotation_list, head);
-+}
-+
-+static void get_ctx(struct perf_event_context *ctx)
-+{
-+ WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
-+}
-+
-+static void put_ctx(struct perf_event_context *ctx)
-+{
-+ if (atomic_dec_and_test(&ctx->refcount)) {
-+ if (ctx->parent_ctx)
-+ put_ctx(ctx->parent_ctx);
-+ if (ctx->task)
-+ put_task_struct(ctx->task);
-+ kfree_rcu(ctx, rcu_head);
-+ }
-+}
-+
-+/*
-+ * This must be done under the ctx->lock, such as to serialize against
-+ * context_equiv(), therefore we cannot call put_ctx() since that might end up
-+ * calling scheduler related locks and ctx->lock nests inside those.
-+ */
-+static __must_check struct perf_event_context *
-+unclone_ctx(struct perf_event_context *ctx)
-+{
-+ struct perf_event_context *parent_ctx = ctx->parent_ctx;
-+
-+ lockdep_assert_held(&ctx->lock);
-+
-+ if (parent_ctx)
-+ ctx->parent_ctx = NULL;
-+ ctx->generation++;
-+
-+ return parent_ctx;
-+}
-+
-+static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
-+{
-+ /*
-+ * only top level events have the pid namespace they were created in
-+ */
-+ if (event->parent)
-+ event = event->parent;
-+
-+ return task_tgid_nr_ns(p, event->ns);
-+}
-+
-+static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
-+{
-+ /*
-+ * only top level events have the pid namespace they were created in
-+ */
-+ if (event->parent)
-+ event = event->parent;
-+
-+ return task_pid_nr_ns(p, event->ns);
-+}
-+
-+/*
-+ * If we inherit events we want to return the parent event id
-+ * to userspace.
-+ */
-+static u64 primary_event_id(struct perf_event *event)
-+{
-+ u64 id = event->id;
-+
-+ if (event->parent)
-+ id = event->parent->id;
-+
-+ return id;
-+}
-+
-+/*
-+ * Get the perf_event_context for a task and lock it.
-+ * This has to cope with with the fact that until it is locked,
-+ * the context could get moved to another task.
-+ */
-+static struct perf_event_context *
-+perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
-+{
-+ struct perf_event_context *ctx;
-+
-+retry:
-+ /*
-+ * One of the few rules of preemptible RCU is that one cannot do
-+ * rcu_read_unlock() while holding a scheduler (or nested) lock when
-+ * part of the read side critical section was preemptible -- see
-+ * rcu_read_unlock_special().
-+ *
-+ * Since ctx->lock nests under rq->lock we must ensure the entire read
-+ * side critical section is non-preemptible.
-+ */
-+ preempt_disable();
-+ rcu_read_lock();
-+ ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
-+ if (ctx) {
-+ /*
-+ * If this context is a clone of another, it might
-+ * get swapped for another underneath us by
-+ * perf_event_task_sched_out, though the
-+ * rcu_read_lock() protects us from any context
-+ * getting freed. Lock the context and check if it
-+ * got swapped before we could get the lock, and retry
-+ * if so. If we locked the right context, then it
-+ * can't get swapped on us any more.
-+ */
-+ raw_spin_lock_irqsave(&ctx->lock, *flags);
-+ if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
-+ raw_spin_unlock_irqrestore(&ctx->lock, *flags);
-+ rcu_read_unlock();
-+ preempt_enable();
-+ goto retry;
-+ }
-+
-+ if (!atomic_inc_not_zero(&ctx->refcount)) {
-+ raw_spin_unlock_irqrestore(&ctx->lock, *flags);
-+ ctx = NULL;
-+ }
-+ }
-+ rcu_read_unlock();
-+ preempt_enable();
-+ return ctx;
-+}
-+
-+/*
-+ * Get the context for a task and increment its pin_count so it
-+ * can't get swapped to another task. This also increments its
-+ * reference count so that the context can't get freed.
-+ */
-+static struct perf_event_context *
-+perf_pin_task_context(struct task_struct *task, int ctxn)
-+{
-+ struct perf_event_context *ctx;
-+ unsigned long flags;
-+
-+ ctx = perf_lock_task_context(task, ctxn, &flags);
-+ if (ctx) {
-+ ++ctx->pin_count;
-+ raw_spin_unlock_irqrestore(&ctx->lock, flags);
-+ }
-+ return ctx;
-+}
-+
-+static void perf_unpin_context(struct perf_event_context *ctx)
-+{
-+ unsigned long flags;
-+
-+ raw_spin_lock_irqsave(&ctx->lock, flags);
-+ --ctx->pin_count;
-+ raw_spin_unlock_irqrestore(&ctx->lock, flags);
-+}
-+
-+/*
-+ * Update the record of the current time in a context.
-+ */
-+static void update_context_time(struct perf_event_context *ctx)
-+{
-+ u64 now = perf_clock();
-+
-+ ctx->time += now - ctx->timestamp;
-+ ctx->timestamp = now;
-+}
-+
-+static u64 perf_event_time(struct perf_event *event)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+
-+ if (is_cgroup_event(event))
-+ return perf_cgroup_event_time(event);
-+
-+ return ctx ? ctx->time : 0;
-+}
-+
-+/*
-+ * Update the total_time_enabled and total_time_running fields for a event.
-+ * The caller of this function needs to hold the ctx->lock.
-+ */
-+static void update_event_times(struct perf_event *event)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ u64 run_end;
-+
-+ if (event->state < PERF_EVENT_STATE_INACTIVE ||
-+ event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
-+ return;
-+ /*
-+ * in cgroup mode, time_enabled represents
-+ * the time the event was enabled AND active
-+ * tasks were in the monitored cgroup. This is
-+ * independent of the activity of the context as
-+ * there may be a mix of cgroup and non-cgroup events.
-+ *
-+ * That is why we treat cgroup events differently
-+ * here.
-+ */
-+ if (is_cgroup_event(event))
-+ run_end = perf_cgroup_event_time(event);
-+ else if (ctx->is_active)
-+ run_end = ctx->time;
-+ else
-+ run_end = event->tstamp_stopped;
-+
-+ event->total_time_enabled = run_end - event->tstamp_enabled;
-+
-+ if (event->state == PERF_EVENT_STATE_INACTIVE)
-+ run_end = event->tstamp_stopped;
-+ else
-+ run_end = perf_event_time(event);
-+
-+ event->total_time_running = run_end - event->tstamp_running;
-+
-+}
-+
-+/*
-+ * Update total_time_enabled and total_time_running for all events in a group.
-+ */
-+static void update_group_times(struct perf_event *leader)
-+{
-+ struct perf_event *event;
-+
-+ update_event_times(leader);
-+ list_for_each_entry(event, &leader->sibling_list, group_entry)
-+ update_event_times(event);
-+}
-+
-+static struct list_head *
-+ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
-+{
-+ if (event->attr.pinned)
-+ return &ctx->pinned_groups;
-+ else
-+ return &ctx->flexible_groups;
-+}
-+
-+/*
-+ * Add a event from the lists for its context.
-+ * Must be called with ctx->mutex and ctx->lock held.
-+ */
-+static void
-+list_add_event(struct perf_event *event, struct perf_event_context *ctx)
-+{
-+ WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT);
-+ event->attach_state |= PERF_ATTACH_CONTEXT;
-+
-+ /*
-+ * If we're a stand alone event or group leader, we go to the context
-+ * list, group events are kept attached to the group so that
-+ * perf_group_detach can, at all times, locate all siblings.
-+ */
-+ if (event->group_leader == event) {
-+ struct list_head *list;
-+
-+ if (is_software_event(event))
-+ event->group_flags |= PERF_GROUP_SOFTWARE;
-+
-+ list = ctx_group_list(event, ctx);
-+ list_add_tail(&event->group_entry, list);
-+ }
-+
-+ if (is_cgroup_event(event))
-+ ctx->nr_cgroups++;
-+
-+ if (has_branch_stack(event))
-+ ctx->nr_branch_stack++;
-+
-+ list_add_rcu(&event->event_entry, &ctx->event_list);
-+ if (!ctx->nr_events)
-+ perf_pmu_rotate_start(ctx->pmu);
-+ ctx->nr_events++;
-+ if (event->attr.inherit_stat)
-+ ctx->nr_stat++;
-+
-+ ctx->generation++;
-+}
-+
-+/*
-+ * Initialize event state based on the perf_event_attr::disabled.
-+ */
-+static inline void perf_event__state_init(struct perf_event *event)
-+{
-+ event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF :
-+ PERF_EVENT_STATE_INACTIVE;
-+}
-+
-+/*
-+ * Called at perf_event creation and when events are attached/detached from a
-+ * group.
-+ */
-+static void perf_event__read_size(struct perf_event *event)
-+{
-+ int entry = sizeof(u64); /* value */
-+ int size = 0;
-+ int nr = 1;
-+
-+ if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-+ size += sizeof(u64);
-+
-+ if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-+ size += sizeof(u64);
-+
-+ if (event->attr.read_format & PERF_FORMAT_ID)
-+ entry += sizeof(u64);
-+
-+ if (event->attr.read_format & PERF_FORMAT_GROUP) {
-+ nr += event->group_leader->nr_siblings;
-+ size += sizeof(u64);
-+ }
-+
-+ size += entry * nr;
-+ event->read_size = size;
-+}
-+
-+static void perf_event__header_size(struct perf_event *event)
-+{
-+ struct perf_sample_data *data;
-+ u64 sample_type = event->attr.sample_type;
-+ u16 size = 0;
-+
-+ perf_event__read_size(event);
-+
-+ if (sample_type & PERF_SAMPLE_IP)
-+ size += sizeof(data->ip);
-+
-+ if (sample_type & PERF_SAMPLE_ADDR)
-+ size += sizeof(data->addr);
-+
-+ if (sample_type & PERF_SAMPLE_PERIOD)
-+ size += sizeof(data->period);
-+
-+ if (sample_type & PERF_SAMPLE_WEIGHT)
-+ size += sizeof(data->weight);
-+
-+ if (sample_type & PERF_SAMPLE_READ)
-+ size += event->read_size;
-+
-+ if (sample_type & PERF_SAMPLE_DATA_SRC)
-+ size += sizeof(data->data_src.val);
-+
-+ if (sample_type & PERF_SAMPLE_TRANSACTION)
-+ size += sizeof(data->txn);
-+
-+ event->header_size = size;
-+}
-+
-+static void perf_event__id_header_size(struct perf_event *event)
-+{
-+ struct perf_sample_data *data;
-+ u64 sample_type = event->attr.sample_type;
-+ u16 size = 0;
-+
-+ if (sample_type & PERF_SAMPLE_TID)
-+ size += sizeof(data->tid_entry);
-+
-+ if (sample_type & PERF_SAMPLE_TIME)
-+ size += sizeof(data->time);
-+
-+ if (sample_type & PERF_SAMPLE_IDENTIFIER)
-+ size += sizeof(data->id);
-+
-+ if (sample_type & PERF_SAMPLE_ID)
-+ size += sizeof(data->id);
-+
-+ if (sample_type & PERF_SAMPLE_STREAM_ID)
-+ size += sizeof(data->stream_id);
-+
-+ if (sample_type & PERF_SAMPLE_CPU)
-+ size += sizeof(data->cpu_entry);
-+
-+ event->id_header_size = size;
-+}
-+
-+static void perf_group_attach(struct perf_event *event)
-+{
-+ struct perf_event *group_leader = event->group_leader, *pos;
-+
-+ /*
-+ * We can have double attach due to group movement in perf_event_open.
-+ */
-+ if (event->attach_state & PERF_ATTACH_GROUP)
-+ return;
-+
-+ event->attach_state |= PERF_ATTACH_GROUP;
-+
-+ if (group_leader == event)
-+ return;
-+
-+ if (group_leader->group_flags & PERF_GROUP_SOFTWARE &&
-+ !is_software_event(event))
-+ group_leader->group_flags &= ~PERF_GROUP_SOFTWARE;
-+
-+ list_add_tail(&event->group_entry, &group_leader->sibling_list);
-+ group_leader->nr_siblings++;
-+
-+ perf_event__header_size(group_leader);
-+
-+ list_for_each_entry(pos, &group_leader->sibling_list, group_entry)
-+ perf_event__header_size(pos);
-+}
-+
-+/*
-+ * Remove a event from the lists for its context.
-+ * Must be called with ctx->mutex and ctx->lock held.
-+ */
-+static void
-+list_del_event(struct perf_event *event, struct perf_event_context *ctx)
-+{
-+ struct perf_cpu_context *cpuctx;
-+ /*
-+ * We can have double detach due to exit/hot-unplug + close.
-+ */
-+ if (!(event->attach_state & PERF_ATTACH_CONTEXT))
-+ return;
-+
-+ event->attach_state &= ~PERF_ATTACH_CONTEXT;
-+
-+ if (is_cgroup_event(event)) {
-+ ctx->nr_cgroups--;
-+ cpuctx = __get_cpu_context(ctx);
-+ /*
-+ * if there are no more cgroup events
-+ * then cler cgrp to avoid stale pointer
-+ * in update_cgrp_time_from_cpuctx()
-+ */
-+ if (!ctx->nr_cgroups)
-+ cpuctx->cgrp = NULL;
-+ }
-+
-+ if (has_branch_stack(event))
-+ ctx->nr_branch_stack--;
-+
-+ ctx->nr_events--;
-+ if (event->attr.inherit_stat)
-+ ctx->nr_stat--;
-+
-+ list_del_rcu(&event->event_entry);
-+
-+ if (event->group_leader == event)
-+ list_del_init(&event->group_entry);
-+
-+ update_group_times(event);
-+
-+ /*
-+ * If event was in error state, then keep it
-+ * that way, otherwise bogus counts will be
-+ * returned on read(). The only way to get out
-+ * of error state is by explicit re-enabling
-+ * of the event
-+ */
-+ if (event->state > PERF_EVENT_STATE_OFF)
-+ event->state = PERF_EVENT_STATE_OFF;
-+
-+ ctx->generation++;
-+}
-+
-+static void perf_group_detach(struct perf_event *event)
-+{
-+ struct perf_event *sibling, *tmp;
-+ struct list_head *list = NULL;
-+
-+ /*
-+ * We can have double detach due to exit/hot-unplug + close.
-+ */
-+ if (!(event->attach_state & PERF_ATTACH_GROUP))
-+ return;
-+
-+ event->attach_state &= ~PERF_ATTACH_GROUP;
-+
-+ /*
-+ * If this is a sibling, remove it from its group.
-+ */
-+ if (event->group_leader != event) {
-+ list_del_init(&event->group_entry);
-+ event->group_leader->nr_siblings--;
-+ goto out;
-+ }
-+
-+ if (!list_empty(&event->group_entry))
-+ list = &event->group_entry;
-+
-+ /*
-+ * If this was a group event with sibling events then
-+ * upgrade the siblings to singleton events by adding them
-+ * to whatever list we are on.
-+ */
-+ list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) {
-+ if (list)
-+ list_move_tail(&sibling->group_entry, list);
-+ sibling->group_leader = sibling;
-+
-+ /* Inherit group flags from the previous leader */
-+ sibling->group_flags = event->group_flags;
-+ }
-+
-+out:
-+ perf_event__header_size(event->group_leader);
-+
-+ list_for_each_entry(tmp, &event->group_leader->sibling_list, group_entry)
-+ perf_event__header_size(tmp);
-+}
-+
-+/*
-+ * User event without the task.
-+ */
-+static bool is_orphaned_event(struct perf_event *event)
-+{
-+ return event && !is_kernel_event(event) && !event->owner;
-+}
-+
-+/*
-+ * Event has a parent but parent's task finished and it's
-+ * alive only because of children holding refference.
-+ */
-+static bool is_orphaned_child(struct perf_event *event)
-+{
-+ return is_orphaned_event(event->parent);
-+}
-+
-+static void orphans_remove_work(struct work_struct *work);
-+
-+static void schedule_orphans_remove(struct perf_event_context *ctx)
-+{
-+ if (!ctx->task || ctx->orphans_remove_sched || !perf_wq)
-+ return;
-+
-+ if (queue_delayed_work(perf_wq, &ctx->orphans_remove, 1)) {
-+ get_ctx(ctx);
-+ ctx->orphans_remove_sched = true;
-+ }
-+}
-+
-+static int __init perf_workqueue_init(void)
-+{
-+ perf_wq = create_singlethread_workqueue("perf");
-+ WARN(!perf_wq, "failed to create perf workqueue\n");
-+ return perf_wq ? 0 : -1;
-+}
-+
-+core_initcall(perf_workqueue_init);
-+
-+static inline int
-+event_filter_match(struct perf_event *event)
-+{
-+ return (event->cpu == -1 || event->cpu == smp_processor_id())
-+ && perf_cgroup_match(event);
-+}
-+
-+static void
-+event_sched_out(struct perf_event *event,
-+ struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx)
-+{
-+ u64 tstamp = perf_event_time(event);
-+ u64 delta;
-+ /*
-+ * An event which could not be activated because of
-+ * filter mismatch still needs to have its timings
-+ * maintained, otherwise bogus information is return
-+ * via read() for time_enabled, time_running:
-+ */
-+ if (event->state == PERF_EVENT_STATE_INACTIVE
-+ && !event_filter_match(event)) {
-+ delta = tstamp - event->tstamp_stopped;
-+ event->tstamp_running += delta;
-+ event->tstamp_stopped = tstamp;
-+ }
-+
-+ if (event->state != PERF_EVENT_STATE_ACTIVE)
-+ return;
-+
-+ perf_pmu_disable(event->pmu);
-+
-+ event->state = PERF_EVENT_STATE_INACTIVE;
-+ if (event->pending_disable) {
-+ event->pending_disable = 0;
-+ event->state = PERF_EVENT_STATE_OFF;
-+ }
-+ event->tstamp_stopped = tstamp;
-+ event->pmu->del(event, 0);
-+ event->oncpu = -1;
-+
-+ if (!is_software_event(event))
-+ cpuctx->active_oncpu--;
-+ ctx->nr_active--;
-+ if (event->attr.freq && event->attr.sample_freq)
-+ ctx->nr_freq--;
-+ if (event->attr.exclusive || !cpuctx->active_oncpu)
-+ cpuctx->exclusive = 0;
-+
-+ if (is_orphaned_child(event))
-+ schedule_orphans_remove(ctx);
-+
-+ perf_pmu_enable(event->pmu);
-+}
-+
-+static void
-+group_sched_out(struct perf_event *group_event,
-+ struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx)
-+{
-+ struct perf_event *event;
-+ int state = group_event->state;
-+
-+ event_sched_out(group_event, cpuctx, ctx);
-+
-+ /*
-+ * Schedule out siblings (if any):
-+ */
-+ list_for_each_entry(event, &group_event->sibling_list, group_entry)
-+ event_sched_out(event, cpuctx, ctx);
-+
-+ if (state == PERF_EVENT_STATE_ACTIVE && group_event->attr.exclusive)
-+ cpuctx->exclusive = 0;
-+}
-+
-+struct remove_event {
-+ struct perf_event *event;
-+ bool detach_group;
-+};
-+
-+/*
-+ * Cross CPU call to remove a performance event
-+ *
-+ * We disable the event on the hardware level first. After that we
-+ * remove it from the context list.
-+ */
-+static int __perf_remove_from_context(void *info)
-+{
-+ struct remove_event *re = info;
-+ struct perf_event *event = re->event;
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+
-+ raw_spin_lock(&ctx->lock);
-+ event_sched_out(event, cpuctx, ctx);
-+ if (re->detach_group)
-+ perf_group_detach(event);
-+ list_del_event(event, ctx);
-+ if (!ctx->nr_events && cpuctx->task_ctx == ctx) {
-+ ctx->is_active = 0;
-+ cpuctx->task_ctx = NULL;
-+ }
-+ raw_spin_unlock(&ctx->lock);
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * Remove the event from a task's (or a CPU's) list of events.
-+ *
-+ * CPU events are removed with a smp call. For task events we only
-+ * call when the task is on a CPU.
-+ *
-+ * If event->ctx is a cloned context, callers must make sure that
-+ * every task struct that event->ctx->task could possibly point to
-+ * remains valid. This is OK when called from perf_release since
-+ * that only calls us on the top-level context, which can't be a clone.
-+ * When called from perf_event_exit_task, it's OK because the
-+ * context has been detached from its task.
-+ */
-+static void perf_remove_from_context(struct perf_event *event, bool detach_group)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ struct task_struct *task = ctx->task;
-+ struct remove_event re = {
-+ .event = event,
-+ .detach_group = detach_group,
-+ };
-+
-+ lockdep_assert_held(&ctx->mutex);
-+
-+ if (!task) {
-+ /*
-+ * Per cpu events are removed via an smp call. The removal can
-+ * fail if the CPU is currently offline, but in that case we
-+ * already called __perf_remove_from_context from
-+ * perf_event_exit_cpu.
-+ */
-+ cpu_function_call(event->cpu, __perf_remove_from_context, &re);
-+ return;
-+ }
-+
-+retry:
-+ if (!task_function_call(task, __perf_remove_from_context, &re))
-+ return;
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+ /*
-+ * If we failed to find a running task, but find the context active now
-+ * that we've acquired the ctx->lock, retry.
-+ */
-+ if (ctx->is_active) {
-+ raw_spin_unlock_irq(&ctx->lock);
-+ /*
-+ * Reload the task pointer, it might have been changed by
-+ * a concurrent perf_event_context_sched_out().
-+ */
-+ task = ctx->task;
-+ goto retry;
-+ }
-+
-+ /*
-+ * Since the task isn't running, its safe to remove the event, us
-+ * holding the ctx->lock ensures the task won't get scheduled in.
-+ */
-+ if (detach_group)
-+ perf_group_detach(event);
-+ list_del_event(event, ctx);
-+ raw_spin_unlock_irq(&ctx->lock);
-+}
-+
-+/*
-+ * Cross CPU call to disable a performance event
-+ */
-+int __perf_event_disable(void *info)
-+{
-+ struct perf_event *event = info;
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+
-+ /*
-+ * If this is a per-task event, need to check whether this
-+ * event's task is the current task on this cpu.
-+ *
-+ * Can trigger due to concurrent perf_event_context_sched_out()
-+ * flipping contexts around.
-+ */
-+ if (ctx->task && cpuctx->task_ctx != ctx)
-+ return -EINVAL;
-+
-+ raw_spin_lock(&ctx->lock);
-+
-+ /*
-+ * If the event is on, turn it off.
-+ * If it is in error state, leave it in error state.
-+ */
-+ if (event->state >= PERF_EVENT_STATE_INACTIVE) {
-+ update_context_time(ctx);
-+ update_cgrp_time_from_event(event);
-+ update_group_times(event);
-+ if (event == event->group_leader)
-+ group_sched_out(event, cpuctx, ctx);
-+ else
-+ event_sched_out(event, cpuctx, ctx);
-+ event->state = PERF_EVENT_STATE_OFF;
-+ }
-+
-+ raw_spin_unlock(&ctx->lock);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Disable a event.
-+ *
-+ * If event->ctx is a cloned context, callers must make sure that
-+ * every task struct that event->ctx->task could possibly point to
-+ * remains valid. This condition is satisifed when called through
-+ * perf_event_for_each_child or perf_event_for_each because they
-+ * hold the top-level event's child_mutex, so any descendant that
-+ * goes to exit will block in sync_child_event.
-+ * When called from perf_pending_event it's OK because event->ctx
-+ * is the current context on this CPU and preemption is disabled,
-+ * hence we can't get into perf_event_task_sched_out for this context.
-+ */
-+void perf_event_disable(struct perf_event *event)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ struct task_struct *task = ctx->task;
-+
-+ if (!task) {
-+ /*
-+ * Disable the event on the cpu that it's on
-+ */
-+ cpu_function_call(event->cpu, __perf_event_disable, event);
-+ return;
-+ }
-+
-+retry:
-+ if (!task_function_call(task, __perf_event_disable, event))
-+ return;
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+ /*
-+ * If the event is still active, we need to retry the cross-call.
-+ */
-+ if (event->state == PERF_EVENT_STATE_ACTIVE) {
-+ raw_spin_unlock_irq(&ctx->lock);
-+ /*
-+ * Reload the task pointer, it might have been changed by
-+ * a concurrent perf_event_context_sched_out().
-+ */
-+ task = ctx->task;
-+ goto retry;
-+ }
-+
-+ /*
-+ * Since we have the lock this context can't be scheduled
-+ * in, so we can change the state safely.
-+ */
-+ if (event->state == PERF_EVENT_STATE_INACTIVE) {
-+ update_group_times(event);
-+ event->state = PERF_EVENT_STATE_OFF;
-+ }
-+ raw_spin_unlock_irq(&ctx->lock);
-+}
-+EXPORT_SYMBOL_GPL(perf_event_disable);
-+
-+static void perf_set_shadow_time(struct perf_event *event,
-+ struct perf_event_context *ctx,
-+ u64 tstamp)
-+{
-+ /*
-+ * use the correct time source for the time snapshot
-+ *
-+ * We could get by without this by leveraging the
-+ * fact that to get to this function, the caller
-+ * has most likely already called update_context_time()
-+ * and update_cgrp_time_xx() and thus both timestamp
-+ * are identical (or very close). Given that tstamp is,
-+ * already adjusted for cgroup, we could say that:
-+ * tstamp - ctx->timestamp
-+ * is equivalent to
-+ * tstamp - cgrp->timestamp.
-+ *
-+ * Then, in perf_output_read(), the calculation would
-+ * work with no changes because:
-+ * - event is guaranteed scheduled in
-+ * - no scheduled out in between
-+ * - thus the timestamp would be the same
-+ *
-+ * But this is a bit hairy.
-+ *
-+ * So instead, we have an explicit cgroup call to remain
-+ * within the time time source all along. We believe it
-+ * is cleaner and simpler to understand.
-+ */
-+ if (is_cgroup_event(event))
-+ perf_cgroup_set_shadow_time(event, tstamp);
-+ else
-+ event->shadow_ctx_time = tstamp - ctx->timestamp;
-+}
-+
-+#define MAX_INTERRUPTS (~0ULL)
-+
-+static void perf_log_throttle(struct perf_event *event, int enable);
-+
-+static int
-+event_sched_in(struct perf_event *event,
-+ struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx)
-+{
-+ u64 tstamp = perf_event_time(event);
-+ int ret = 0;
-+
-+ lockdep_assert_held(&ctx->lock);
-+
-+ if (event->state <= PERF_EVENT_STATE_OFF)
-+ return 0;
-+
-+ event->state = PERF_EVENT_STATE_ACTIVE;
-+ event->oncpu = smp_processor_id();
-+
-+ /*
-+ * Unthrottle events, since we scheduled we might have missed several
-+ * ticks already, also for a heavily scheduling task there is little
-+ * guarantee it'll get a tick in a timely manner.
-+ */
-+ if (unlikely(event->hw.interrupts == MAX_INTERRUPTS)) {
-+ perf_log_throttle(event, 1);
-+ event->hw.interrupts = 0;
-+ }
-+
-+ /*
-+ * The new state must be visible before we turn it on in the hardware:
-+ */
-+ smp_wmb();
-+
-+ perf_pmu_disable(event->pmu);
-+
-+ if (event->pmu->add(event, PERF_EF_START)) {
-+ event->state = PERF_EVENT_STATE_INACTIVE;
-+ event->oncpu = -1;
-+ ret = -EAGAIN;
-+ goto out;
-+ }
-+
-+ event->tstamp_running += tstamp - event->tstamp_stopped;
-+
-+ perf_set_shadow_time(event, ctx, tstamp);
-+
-+ if (!is_software_event(event))
-+ cpuctx->active_oncpu++;
-+ ctx->nr_active++;
-+ if (event->attr.freq && event->attr.sample_freq)
-+ ctx->nr_freq++;
-+
-+ if (event->attr.exclusive)
-+ cpuctx->exclusive = 1;
-+
-+ if (is_orphaned_child(event))
-+ schedule_orphans_remove(ctx);
-+
-+out:
-+ perf_pmu_enable(event->pmu);
-+
-+ return ret;
-+}
-+
-+static int
-+group_sched_in(struct perf_event *group_event,
-+ struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx)
-+{
-+ struct perf_event *event, *partial_group = NULL;
-+ struct pmu *pmu = ctx->pmu;
-+ u64 now = ctx->time;
-+ bool simulate = false;
-+
-+ if (group_event->state == PERF_EVENT_STATE_OFF)
-+ return 0;
-+
-+ pmu->start_txn(pmu);
-+
-+ if (event_sched_in(group_event, cpuctx, ctx)) {
-+ pmu->cancel_txn(pmu);
-+ perf_cpu_hrtimer_restart(cpuctx);
-+ return -EAGAIN;
-+ }
-+
-+ /*
-+ * Schedule in siblings as one group (if any):
-+ */
-+ list_for_each_entry(event, &group_event->sibling_list, group_entry) {
-+ if (event_sched_in(event, cpuctx, ctx)) {
-+ partial_group = event;
-+ goto group_error;
-+ }
-+ }
-+
-+ if (!pmu->commit_txn(pmu))
-+ return 0;
-+
-+group_error:
-+ /*
-+ * Groups can be scheduled in as one unit only, so undo any
-+ * partial group before returning:
-+ * The events up to the failed event are scheduled out normally,
-+ * tstamp_stopped will be updated.
-+ *
-+ * The failed events and the remaining siblings need to have
-+ * their timings updated as if they had gone thru event_sched_in()
-+ * and event_sched_out(). This is required to get consistent timings
-+ * across the group. This also takes care of the case where the group
-+ * could never be scheduled by ensuring tstamp_stopped is set to mark
-+ * the time the event was actually stopped, such that time delta
-+ * calculation in update_event_times() is correct.
-+ */
-+ list_for_each_entry(event, &group_event->sibling_list, group_entry) {
-+ if (event == partial_group)
-+ simulate = true;
-+
-+ if (simulate) {
-+ event->tstamp_running += now - event->tstamp_stopped;
-+ event->tstamp_stopped = now;
-+ } else {
-+ event_sched_out(event, cpuctx, ctx);
-+ }
-+ }
-+ event_sched_out(group_event, cpuctx, ctx);
-+
-+ pmu->cancel_txn(pmu);
-+
-+ perf_cpu_hrtimer_restart(cpuctx);
-+
-+ return -EAGAIN;
-+}
-+
-+/*
-+ * Work out whether we can put this event group on the CPU now.
-+ */
-+static int group_can_go_on(struct perf_event *event,
-+ struct perf_cpu_context *cpuctx,
-+ int can_add_hw)
-+{
-+ /*
-+ * Groups consisting entirely of software events can always go on.
-+ */
-+ if (event->group_flags & PERF_GROUP_SOFTWARE)
-+ return 1;
-+ /*
-+ * If an exclusive group is already on, no other hardware
-+ * events can go on.
-+ */
-+ if (cpuctx->exclusive)
-+ return 0;
-+ /*
-+ * If this group is exclusive and there are already
-+ * events on the CPU, it can't go on.
-+ */
-+ if (event->attr.exclusive && cpuctx->active_oncpu)
-+ return 0;
-+ /*
-+ * Otherwise, try to add it if all previous groups were able
-+ * to go on.
-+ */
-+ return can_add_hw;
-+}
-+
-+static void add_event_to_ctx(struct perf_event *event,
-+ struct perf_event_context *ctx)
-+{
-+ u64 tstamp = perf_event_time(event);
-+
-+ list_add_event(event, ctx);
-+ perf_group_attach(event);
-+ event->tstamp_enabled = tstamp;
-+ event->tstamp_running = tstamp;
-+ event->tstamp_stopped = tstamp;
-+}
-+
-+static void task_ctx_sched_out(struct perf_event_context *ctx);
-+static void
-+ctx_sched_in(struct perf_event_context *ctx,
-+ struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type,
-+ struct task_struct *task);
-+
-+static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
-+ struct perf_event_context *ctx,
-+ struct task_struct *task)
-+{
-+ cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task);
-+ if (ctx)
-+ ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task);
-+ cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task);
-+ if (ctx)
-+ ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
-+}
-+
-+/*
-+ * Cross CPU call to install and enable a performance event
-+ *
-+ * Must be called with ctx->mutex held
-+ */
-+static int __perf_install_in_context(void *info)
-+{
-+ struct perf_event *event = info;
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+ struct perf_event_context *task_ctx = cpuctx->task_ctx;
-+ struct task_struct *task = current;
-+
-+ perf_ctx_lock(cpuctx, task_ctx);
-+ perf_pmu_disable(cpuctx->ctx.pmu);
-+
-+ /*
-+ * If there was an active task_ctx schedule it out.
-+ */
-+ if (task_ctx)
-+ task_ctx_sched_out(task_ctx);
-+
-+ /*
-+ * If the context we're installing events in is not the
-+ * active task_ctx, flip them.
-+ */
-+ if (ctx->task && task_ctx != ctx) {
-+ if (task_ctx)
-+ raw_spin_unlock(&task_ctx->lock);
-+ raw_spin_lock(&ctx->lock);
-+ task_ctx = ctx;
-+ }
-+
-+ if (task_ctx) {
-+ cpuctx->task_ctx = task_ctx;
-+ task = task_ctx->task;
-+ }
-+
-+ cpu_ctx_sched_out(cpuctx, EVENT_ALL);
-+
-+ update_context_time(ctx);
-+ /*
-+ * update cgrp time only if current cgrp
-+ * matches event->cgrp. Must be done before
-+ * calling add_event_to_ctx()
-+ */
-+ update_cgrp_time_from_event(event);
-+
-+ add_event_to_ctx(event, ctx);
-+
-+ /*
-+ * Schedule everything back in
-+ */
-+ perf_event_sched_in(cpuctx, task_ctx, task);
-+
-+ perf_pmu_enable(cpuctx->ctx.pmu);
-+ perf_ctx_unlock(cpuctx, task_ctx);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Attach a performance event to a context
-+ *
-+ * First we add the event to the list with the hardware enable bit
-+ * in event->hw_config cleared.
-+ *
-+ * If the event is attached to a task which is on a CPU we use a smp
-+ * call to enable it in the task context. The task might have been
-+ * scheduled away, but we check this in the smp call again.
-+ */
-+static void
-+perf_install_in_context(struct perf_event_context *ctx,
-+ struct perf_event *event,
-+ int cpu)
-+{
-+ struct task_struct *task = ctx->task;
-+
-+ lockdep_assert_held(&ctx->mutex);
-+
-+ event->ctx = ctx;
-+ if (event->cpu != -1)
-+ event->cpu = cpu;
-+
-+ if (!task) {
-+ /*
-+ * Per cpu events are installed via an smp call and
-+ * the install is always successful.
-+ */
-+ cpu_function_call(cpu, __perf_install_in_context, event);
-+ return;
-+ }
-+
-+retry:
-+ if (!task_function_call(task, __perf_install_in_context, event))
-+ return;
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+ /*
-+ * If we failed to find a running task, but find the context active now
-+ * that we've acquired the ctx->lock, retry.
-+ */
-+ if (ctx->is_active) {
-+ raw_spin_unlock_irq(&ctx->lock);
-+ /*
-+ * Reload the task pointer, it might have been changed by
-+ * a concurrent perf_event_context_sched_out().
-+ */
-+ task = ctx->task;
-+ goto retry;
-+ }
-+
-+ /*
-+ * Since the task isn't running, its safe to add the event, us holding
-+ * the ctx->lock ensures the task won't get scheduled in.
-+ */
-+ add_event_to_ctx(event, ctx);
-+ raw_spin_unlock_irq(&ctx->lock);
-+}
-+
-+/*
-+ * Put a event into inactive state and update time fields.
-+ * Enabling the leader of a group effectively enables all
-+ * the group members that aren't explicitly disabled, so we
-+ * have to update their ->tstamp_enabled also.
-+ * Note: this works for group members as well as group leaders
-+ * since the non-leader members' sibling_lists will be empty.
-+ */
-+static void __perf_event_mark_enabled(struct perf_event *event)
-+{
-+ struct perf_event *sub;
-+ u64 tstamp = perf_event_time(event);
-+
-+ event->state = PERF_EVENT_STATE_INACTIVE;
-+ event->tstamp_enabled = tstamp - event->total_time_enabled;
-+ list_for_each_entry(sub, &event->sibling_list, group_entry) {
-+ if (sub->state >= PERF_EVENT_STATE_INACTIVE)
-+ sub->tstamp_enabled = tstamp - sub->total_time_enabled;
-+ }
-+}
-+
-+/*
-+ * Cross CPU call to enable a performance event
-+ */
-+static int __perf_event_enable(void *info)
-+{
-+ struct perf_event *event = info;
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_event *leader = event->group_leader;
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+ int err;
-+
-+ /*
-+ * There's a time window between 'ctx->is_active' check
-+ * in perf_event_enable function and this place having:
-+ * - IRQs on
-+ * - ctx->lock unlocked
-+ *
-+ * where the task could be killed and 'ctx' deactivated
-+ * by perf_event_exit_task.
-+ */
-+ if (!ctx->is_active)
-+ return -EINVAL;
-+
-+ raw_spin_lock(&ctx->lock);
-+ update_context_time(ctx);
-+
-+ if (event->state >= PERF_EVENT_STATE_INACTIVE)
-+ goto unlock;
-+
-+ /*
-+ * set current task's cgroup time reference point
-+ */
-+ perf_cgroup_set_timestamp(current, ctx);
-+
-+ __perf_event_mark_enabled(event);
-+
-+ if (!event_filter_match(event)) {
-+ if (is_cgroup_event(event))
-+ perf_cgroup_defer_enabled(event);
-+ goto unlock;
-+ }
-+
-+ /*
-+ * If the event is in a group and isn't the group leader,
-+ * then don't put it on unless the group is on.
-+ */
-+ if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE)
-+ goto unlock;
-+
-+ if (!group_can_go_on(event, cpuctx, 1)) {
-+ err = -EEXIST;
-+ } else {
-+ if (event == leader)
-+ err = group_sched_in(event, cpuctx, ctx);
-+ else
-+ err = event_sched_in(event, cpuctx, ctx);
-+ }
-+
-+ if (err) {
-+ /*
-+ * If this event can't go on and it's part of a
-+ * group, then the whole group has to come off.
-+ */
-+ if (leader != event) {
-+ group_sched_out(leader, cpuctx, ctx);
-+ perf_cpu_hrtimer_restart(cpuctx);
-+ }
-+ if (leader->attr.pinned) {
-+ update_group_times(leader);
-+ leader->state = PERF_EVENT_STATE_ERROR;
-+ }
-+ }
-+
-+unlock:
-+ raw_spin_unlock(&ctx->lock);
-+
-+ return 0;
-+}
-+
-+/*
-+ * Enable a event.
-+ *
-+ * If event->ctx is a cloned context, callers must make sure that
-+ * every task struct that event->ctx->task could possibly point to
-+ * remains valid. This condition is satisfied when called through
-+ * perf_event_for_each_child or perf_event_for_each as described
-+ * for perf_event_disable.
-+ */
-+void perf_event_enable(struct perf_event *event)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ struct task_struct *task = ctx->task;
-+
-+ if (!task) {
-+ /*
-+ * Enable the event on the cpu that it's on
-+ */
-+ cpu_function_call(event->cpu, __perf_event_enable, event);
-+ return;
-+ }
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+ if (event->state >= PERF_EVENT_STATE_INACTIVE)
-+ goto out;
-+
-+ /*
-+ * If the event is in error state, clear that first.
-+ * That way, if we see the event in error state below, we
-+ * know that it has gone back into error state, as distinct
-+ * from the task having been scheduled away before the
-+ * cross-call arrived.
-+ */
-+ if (event->state == PERF_EVENT_STATE_ERROR)
-+ event->state = PERF_EVENT_STATE_OFF;
-+
-+retry:
-+ if (!ctx->is_active) {
-+ __perf_event_mark_enabled(event);
-+ goto out;
-+ }
-+
-+ raw_spin_unlock_irq(&ctx->lock);
-+
-+ if (!task_function_call(task, __perf_event_enable, event))
-+ return;
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+
-+ /*
-+ * If the context is active and the event is still off,
-+ * we need to retry the cross-call.
-+ */
-+ if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) {
-+ /*
-+ * task could have been flipped by a concurrent
-+ * perf_event_context_sched_out()
-+ */
-+ task = ctx->task;
-+ goto retry;
-+ }
-+
-+out:
-+ raw_spin_unlock_irq(&ctx->lock);
-+}
-+EXPORT_SYMBOL_GPL(perf_event_enable);
-+
-+int perf_event_refresh(struct perf_event *event, int refresh)
-+{
-+ /*
-+ * not supported on inherited events
-+ */
-+ if (event->attr.inherit || !is_sampling_event(event))
-+ return -EINVAL;
-+
-+ atomic_add(refresh, &event->event_limit);
-+ perf_event_enable(event);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(perf_event_refresh);
-+
-+static void ctx_sched_out(struct perf_event_context *ctx,
-+ struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type)
-+{
-+ struct perf_event *event;
-+ int is_active = ctx->is_active;
-+
-+ ctx->is_active &= ~event_type;
-+ if (likely(!ctx->nr_events))
-+ return;
-+
-+ update_context_time(ctx);
-+ update_cgrp_time_from_cpuctx(cpuctx);
-+ if (!ctx->nr_active)
-+ return;
-+
-+ perf_pmu_disable(ctx->pmu);
-+ if ((is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) {
-+ list_for_each_entry(event, &ctx->pinned_groups, group_entry)
-+ group_sched_out(event, cpuctx, ctx);
-+ }
-+
-+ if ((is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) {
-+ list_for_each_entry(event, &ctx->flexible_groups, group_entry)
-+ group_sched_out(event, cpuctx, ctx);
-+ }
-+ perf_pmu_enable(ctx->pmu);
-+}
-+
-+/*
-+ * Test whether two contexts are equivalent, i.e. whether they have both been
-+ * cloned from the same version of the same context.
-+ *
-+ * Equivalence is measured using a generation number in the context that is
-+ * incremented on each modification to it; see unclone_ctx(), list_add_event()
-+ * and list_del_event().
-+ */
-+static int context_equiv(struct perf_event_context *ctx1,
-+ struct perf_event_context *ctx2)
-+{
-+ lockdep_assert_held(&ctx1->lock);
-+ lockdep_assert_held(&ctx2->lock);
-+
-+ /* Pinning disables the swap optimization */
-+ if (ctx1->pin_count || ctx2->pin_count)
-+ return 0;
-+
-+ /* If ctx1 is the parent of ctx2 */
-+ if (ctx1 == ctx2->parent_ctx && ctx1->generation == ctx2->parent_gen)
-+ return 1;
-+
-+ /* If ctx2 is the parent of ctx1 */
-+ if (ctx1->parent_ctx == ctx2 && ctx1->parent_gen == ctx2->generation)
-+ return 1;
-+
-+ /*
-+ * If ctx1 and ctx2 have the same parent; we flatten the parent
-+ * hierarchy, see perf_event_init_context().
-+ */
-+ if (ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx &&
-+ ctx1->parent_gen == ctx2->parent_gen)
-+ return 1;
-+
-+ /* Unmatched */
-+ return 0;
-+}
-+
-+static void __perf_event_sync_stat(struct perf_event *event,
-+ struct perf_event *next_event)
-+{
-+ u64 value;
-+
-+ if (!event->attr.inherit_stat)
-+ return;
-+
-+ /*
-+ * Update the event value, we cannot use perf_event_read()
-+ * because we're in the middle of a context switch and have IRQs
-+ * disabled, which upsets smp_call_function_single(), however
-+ * we know the event must be on the current CPU, therefore we
-+ * don't need to use it.
-+ */
-+ switch (event->state) {
-+ case PERF_EVENT_STATE_ACTIVE:
-+ event->pmu->read(event);
-+ /* fall-through */
-+
-+ case PERF_EVENT_STATE_INACTIVE:
-+ update_event_times(event);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ /*
-+ * In order to keep per-task stats reliable we need to flip the event
-+ * values when we flip the contexts.
-+ */
-+ value = local64_read(&next_event->count);
-+ value = local64_xchg(&event->count, value);
-+ local64_set(&next_event->count, value);
-+
-+ swap(event->total_time_enabled, next_event->total_time_enabled);
-+ swap(event->total_time_running, next_event->total_time_running);
-+
-+ /*
-+ * Since we swizzled the values, update the user visible data too.
-+ */
-+ perf_event_update_userpage(event);
-+ perf_event_update_userpage(next_event);
-+}
-+
-+static void perf_event_sync_stat(struct perf_event_context *ctx,
-+ struct perf_event_context *next_ctx)
-+{
-+ struct perf_event *event, *next_event;
-+
-+ if (!ctx->nr_stat)
-+ return;
-+
-+ update_context_time(ctx);
-+
-+ event = list_first_entry(&ctx->event_list,
-+ struct perf_event, event_entry);
-+
-+ next_event = list_first_entry(&next_ctx->event_list,
-+ struct perf_event, event_entry);
-+
-+ while (&event->event_entry != &ctx->event_list &&
-+ &next_event->event_entry != &next_ctx->event_list) {
-+
-+ __perf_event_sync_stat(event, next_event);
-+
-+ event = list_next_entry(event, event_entry);
-+ next_event = list_next_entry(next_event, event_entry);
-+ }
-+}
-+
-+static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
-+ struct task_struct *next)
-+{
-+ struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
-+ struct perf_event_context *next_ctx;
-+ struct perf_event_context *parent, *next_parent;
-+ struct perf_cpu_context *cpuctx;
-+ int do_switch = 1;
-+
-+ if (likely(!ctx))
-+ return;
-+
-+ cpuctx = __get_cpu_context(ctx);
-+ if (!cpuctx->task_ctx)
-+ return;
-+
-+ rcu_read_lock();
-+ next_ctx = next->perf_event_ctxp[ctxn];
-+ if (!next_ctx)
-+ goto unlock;
-+
-+ parent = rcu_dereference(ctx->parent_ctx);
-+ next_parent = rcu_dereference(next_ctx->parent_ctx);
-+
-+ /* If neither context have a parent context; they cannot be clones. */
-+ if (!parent && !next_parent)
-+ goto unlock;
-+
-+ if (next_parent == ctx || next_ctx == parent || next_parent == parent) {
-+ /*
-+ * Looks like the two contexts are clones, so we might be
-+ * able to optimize the context switch. We lock both
-+ * contexts and check that they are clones under the
-+ * lock (including re-checking that neither has been
-+ * uncloned in the meantime). It doesn't matter which
-+ * order we take the locks because no other cpu could
-+ * be trying to lock both of these tasks.
-+ */
-+ raw_spin_lock(&ctx->lock);
-+ raw_spin_lock_nested(&next_ctx->lock, SINGLE_DEPTH_NESTING);
-+ if (context_equiv(ctx, next_ctx)) {
-+ /*
-+ * XXX do we need a memory barrier of sorts
-+ * wrt to rcu_dereference() of perf_event_ctxp
-+ */
-+ task->perf_event_ctxp[ctxn] = next_ctx;
-+ next->perf_event_ctxp[ctxn] = ctx;
-+ ctx->task = next;
-+ next_ctx->task = task;
-+ do_switch = 0;
-+
-+ perf_event_sync_stat(ctx, next_ctx);
-+ }
-+ raw_spin_unlock(&next_ctx->lock);
-+ raw_spin_unlock(&ctx->lock);
-+ }
-+unlock:
-+ rcu_read_unlock();
-+
-+ if (do_switch) {
-+ raw_spin_lock(&ctx->lock);
-+ ctx_sched_out(ctx, cpuctx, EVENT_ALL);
-+ cpuctx->task_ctx = NULL;
-+ raw_spin_unlock(&ctx->lock);
-+ }
-+}
-+
-+#define for_each_task_context_nr(ctxn) \
-+ for ((ctxn) = 0; (ctxn) < perf_nr_task_contexts; (ctxn)++)
-+
-+/*
-+ * Called from scheduler to remove the events of the current task,
-+ * with interrupts disabled.
-+ *
-+ * We stop each event and update the event value in event->count.
-+ *
-+ * This does not protect us against NMI, but disable()
-+ * sets the disabled bit in the control field of event _before_
-+ * accessing the event control register. If a NMI hits, then it will
-+ * not restart the event.
-+ */
-+void __perf_event_task_sched_out(struct task_struct *task,
-+ struct task_struct *next)
-+{
-+ int ctxn;
-+
-+ for_each_task_context_nr(ctxn)
-+ perf_event_context_sched_out(task, ctxn, next);
-+
-+ /*
-+ * if cgroup events exist on this CPU, then we need
-+ * to check if we have to switch out PMU state.
-+ * cgroup event are system-wide mode only
-+ */
-+ if (atomic_read(this_cpu_ptr(&perf_cgroup_events)))
-+ perf_cgroup_sched_out(task, next);
-+}
-+
-+static void task_ctx_sched_out(struct perf_event_context *ctx)
-+{
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+
-+ if (!cpuctx->task_ctx)
-+ return;
-+
-+ if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
-+ return;
-+
-+ ctx_sched_out(ctx, cpuctx, EVENT_ALL);
-+ cpuctx->task_ctx = NULL;
-+}
-+
-+/*
-+ * Called with IRQs disabled
-+ */
-+static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type)
-+{
-+ ctx_sched_out(&cpuctx->ctx, cpuctx, event_type);
-+}
-+
-+static void
-+ctx_pinned_sched_in(struct perf_event_context *ctx,
-+ struct perf_cpu_context *cpuctx)
-+{
-+ struct perf_event *event;
-+
-+ list_for_each_entry(event, &ctx->pinned_groups, group_entry) {
-+ if (event->state <= PERF_EVENT_STATE_OFF)
-+ continue;
-+ if (!event_filter_match(event))
-+ continue;
-+
-+ /* may need to reset tstamp_enabled */
-+ if (is_cgroup_event(event))
-+ perf_cgroup_mark_enabled(event, ctx);
-+
-+ if (group_can_go_on(event, cpuctx, 1))
-+ group_sched_in(event, cpuctx, ctx);
-+
-+ /*
-+ * If this pinned group hasn't been scheduled,
-+ * put it in error state.
-+ */
-+ if (event->state == PERF_EVENT_STATE_INACTIVE) {
-+ update_group_times(event);
-+ event->state = PERF_EVENT_STATE_ERROR;
-+ }
-+ }
-+}
-+
-+static void
-+ctx_flexible_sched_in(struct perf_event_context *ctx,
-+ struct perf_cpu_context *cpuctx)
-+{
-+ struct perf_event *event;
-+ int can_add_hw = 1;
-+
-+ list_for_each_entry(event, &ctx->flexible_groups, group_entry) {
-+ /* Ignore events in OFF or ERROR state */
-+ if (event->state <= PERF_EVENT_STATE_OFF)
-+ continue;
-+ /*
-+ * Listen to the 'cpu' scheduling filter constraint
-+ * of events:
-+ */
-+ if (!event_filter_match(event))
-+ continue;
-+
-+ /* may need to reset tstamp_enabled */
-+ if (is_cgroup_event(event))
-+ perf_cgroup_mark_enabled(event, ctx);
-+
-+ if (group_can_go_on(event, cpuctx, can_add_hw)) {
-+ if (group_sched_in(event, cpuctx, ctx))
-+ can_add_hw = 0;
-+ }
-+ }
-+}
-+
-+static void
-+ctx_sched_in(struct perf_event_context *ctx,
-+ struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type,
-+ struct task_struct *task)
-+{
-+ u64 now;
-+ int is_active = ctx->is_active;
-+
-+ ctx->is_active |= event_type;
-+ if (likely(!ctx->nr_events))
-+ return;
-+
-+ now = perf_clock();
-+ ctx->timestamp = now;
-+ perf_cgroup_set_timestamp(task, ctx);
-+ /*
-+ * First go through the list and put on any pinned groups
-+ * in order to give them the best chance of going on.
-+ */
-+ if (!(is_active & EVENT_PINNED) && (event_type & EVENT_PINNED))
-+ ctx_pinned_sched_in(ctx, cpuctx);
-+
-+ /* Then walk through the lower prio flexible groups */
-+ if (!(is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE))
-+ ctx_flexible_sched_in(ctx, cpuctx);
-+}
-+
-+static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
-+ enum event_type_t event_type,
-+ struct task_struct *task)
-+{
-+ struct perf_event_context *ctx = &cpuctx->ctx;
-+
-+ ctx_sched_in(ctx, cpuctx, event_type, task);
-+}
-+
-+static void perf_event_context_sched_in(struct perf_event_context *ctx,
-+ struct task_struct *task)
-+{
-+ struct perf_cpu_context *cpuctx;
-+
-+ cpuctx = __get_cpu_context(ctx);
-+ if (cpuctx->task_ctx == ctx)
-+ return;
-+
-+ perf_ctx_lock(cpuctx, ctx);
-+ perf_pmu_disable(ctx->pmu);
-+ /*
-+ * We want to keep the following priority order:
-+ * cpu pinned (that don't need to move), task pinned,
-+ * cpu flexible, task flexible.
-+ */
-+ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
-+
-+ if (ctx->nr_events)
-+ cpuctx->task_ctx = ctx;
-+
-+ perf_event_sched_in(cpuctx, cpuctx->task_ctx, task);
-+
-+ perf_pmu_enable(ctx->pmu);
-+ perf_ctx_unlock(cpuctx, ctx);
-+
-+ /*
-+ * Since these rotations are per-cpu, we need to ensure the
-+ * cpu-context we got scheduled on is actually rotating.
-+ */
-+ perf_pmu_rotate_start(ctx->pmu);
-+}
-+
-+/*
-+ * When sampling the branck stack in system-wide, it may be necessary
-+ * to flush the stack on context switch. This happens when the branch
-+ * stack does not tag its entries with the pid of the current task.
-+ * Otherwise it becomes impossible to associate a branch entry with a
-+ * task. This ambiguity is more likely to appear when the branch stack
-+ * supports priv level filtering and the user sets it to monitor only
-+ * at the user level (which could be a useful measurement in system-wide
-+ * mode). In that case, the risk is high of having a branch stack with
-+ * branch from multiple tasks. Flushing may mean dropping the existing
-+ * entries or stashing them somewhere in the PMU specific code layer.
-+ *
-+ * This function provides the context switch callback to the lower code
-+ * layer. It is invoked ONLY when there is at least one system-wide context
-+ * with at least one active event using taken branch sampling.
-+ */
-+static void perf_branch_stack_sched_in(struct task_struct *prev,
-+ struct task_struct *task)
-+{
-+ struct perf_cpu_context *cpuctx;
-+ struct pmu *pmu;
-+ unsigned long flags;
-+
-+ /* no need to flush branch stack if not changing task */
-+ if (prev == task)
-+ return;
-+
-+ local_irq_save(flags);
-+
-+ rcu_read_lock();
-+
-+ list_for_each_entry_rcu(pmu, &pmus, entry) {
-+ cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
-+
-+ /*
-+ * check if the context has at least one
-+ * event using PERF_SAMPLE_BRANCH_STACK
-+ */
-+ if (cpuctx->ctx.nr_branch_stack > 0
-+ && pmu->flush_branch_stack) {
-+
-+ perf_ctx_lock(cpuctx, cpuctx->task_ctx);
-+
-+ perf_pmu_disable(pmu);
-+
-+ pmu->flush_branch_stack();
-+
-+ perf_pmu_enable(pmu);
-+
-+ perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-+ }
-+ }
-+
-+ rcu_read_unlock();
-+
-+ local_irq_restore(flags);
-+}
-+
-+/*
-+ * Called from scheduler to add the events of the current task
-+ * with interrupts disabled.
-+ *
-+ * We restore the event value and then enable it.
-+ *
-+ * This does not protect us against NMI, but enable()
-+ * sets the enabled bit in the control field of event _before_
-+ * accessing the event control register. If a NMI hits, then it will
-+ * keep the event running.
-+ */
-+void __perf_event_task_sched_in(struct task_struct *prev,
-+ struct task_struct *task)
-+{
-+ struct perf_event_context *ctx;
-+ int ctxn;
-+
-+ for_each_task_context_nr(ctxn) {
-+ ctx = task->perf_event_ctxp[ctxn];
-+ if (likely(!ctx))
-+ continue;
-+
-+ perf_event_context_sched_in(ctx, task);
-+ }
-+ /*
-+ * if cgroup events exist on this CPU, then we need
-+ * to check if we have to switch in PMU state.
-+ * cgroup event are system-wide mode only
-+ */
-+ if (atomic_read(this_cpu_ptr(&perf_cgroup_events)))
-+ perf_cgroup_sched_in(prev, task);
-+
-+ /* check for system-wide branch_stack events */
-+ if (atomic_read(this_cpu_ptr(&perf_branch_stack_events)))
-+ perf_branch_stack_sched_in(prev, task);
-+}
-+
-+static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
-+{
-+ u64 frequency = event->attr.sample_freq;
-+ u64 sec = NSEC_PER_SEC;
-+ u64 divisor, dividend;
-+
-+ int count_fls, nsec_fls, frequency_fls, sec_fls;
-+
-+ count_fls = fls64(count);
-+ nsec_fls = fls64(nsec);
-+ frequency_fls = fls64(frequency);
-+ sec_fls = 30;
-+
-+ /*
-+ * We got @count in @nsec, with a target of sample_freq HZ
-+ * the target period becomes:
-+ *
-+ * @count * 10^9
-+ * period = -------------------
-+ * @nsec * sample_freq
-+ *
-+ */
-+
-+ /*
-+ * Reduce accuracy by one bit such that @a and @b converge
-+ * to a similar magnitude.
-+ */
-+#define REDUCE_FLS(a, b) \
-+do { \
-+ if (a##_fls > b##_fls) { \
-+ a >>= 1; \
-+ a##_fls--; \
-+ } else { \
-+ b >>= 1; \
-+ b##_fls--; \
-+ } \
-+} while (0)
-+
-+ /*
-+ * Reduce accuracy until either term fits in a u64, then proceed with
-+ * the other, so that finally we can do a u64/u64 division.
-+ */
-+ while (count_fls + sec_fls > 64 && nsec_fls + frequency_fls > 64) {
-+ REDUCE_FLS(nsec, frequency);
-+ REDUCE_FLS(sec, count);
-+ }
-+
-+ if (count_fls + sec_fls > 64) {
-+ divisor = nsec * frequency;
-+
-+ while (count_fls + sec_fls > 64) {
-+ REDUCE_FLS(count, sec);
-+ divisor >>= 1;
-+ }
-+
-+ dividend = count * sec;
-+ } else {
-+ dividend = count * sec;
-+
-+ while (nsec_fls + frequency_fls > 64) {
-+ REDUCE_FLS(nsec, frequency);
-+ dividend >>= 1;
-+ }
-+
-+ divisor = nsec * frequency;
-+ }
-+
-+ if (!divisor)
-+ return dividend;
-+
-+ return div64_u64(dividend, divisor);
-+}
-+
-+static DEFINE_PER_CPU(int, perf_throttled_count);
-+static DEFINE_PER_CPU(u64, perf_throttled_seq);
-+
-+static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bool disable)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+ s64 period, sample_period;
-+ s64 delta;
-+
-+ period = perf_calculate_period(event, nsec, count);
-+
-+ delta = (s64)(period - hwc->sample_period);
-+ delta = (delta + 7) / 8; /* low pass filter */
-+
-+ sample_period = hwc->sample_period + delta;
-+
-+ if (!sample_period)
-+ sample_period = 1;
-+
-+ hwc->sample_period = sample_period;
-+
-+ if (local64_read(&hwc->period_left) > 8*sample_period) {
-+ if (disable)
-+ event->pmu->stop(event, PERF_EF_UPDATE);
-+
-+ local64_set(&hwc->period_left, 0);
-+
-+ if (disable)
-+ event->pmu->start(event, PERF_EF_RELOAD);
-+ }
-+}
-+
-+/*
-+ * combine freq adjustment with unthrottling to avoid two passes over the
-+ * events. At the same time, make sure, having freq events does not change
-+ * the rate of unthrottling as that would introduce bias.
-+ */
-+static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
-+ int needs_unthr)
-+{
-+ struct perf_event *event;
-+ struct hw_perf_event *hwc;
-+ u64 now, period = TICK_NSEC;
-+ s64 delta;
-+
-+ /*
-+ * only need to iterate over all events iff:
-+ * - context have events in frequency mode (needs freq adjust)
-+ * - there are events to unthrottle on this cpu
-+ */
-+ if (!(ctx->nr_freq || needs_unthr))
-+ return;
-+
-+ raw_spin_lock(&ctx->lock);
-+ perf_pmu_disable(ctx->pmu);
-+
-+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
-+ if (event->state != PERF_EVENT_STATE_ACTIVE)
-+ continue;
-+
-+ if (!event_filter_match(event))
-+ continue;
-+
-+ perf_pmu_disable(event->pmu);
-+
-+ hwc = &event->hw;
-+
-+ if (hwc->interrupts == MAX_INTERRUPTS) {
-+ hwc->interrupts = 0;
-+ perf_log_throttle(event, 1);
-+ event->pmu->start(event, 0);
-+ }
-+
-+ if (!event->attr.freq || !event->attr.sample_freq)
-+ goto next;
-+
-+ /*
-+ * stop the event and update event->count
-+ */
-+ event->pmu->stop(event, PERF_EF_UPDATE);
-+
-+ now = local64_read(&event->count);
-+ delta = now - hwc->freq_count_stamp;
-+ hwc->freq_count_stamp = now;
-+
-+ /*
-+ * restart the event
-+ * reload only if value has changed
-+ * we have stopped the event so tell that
-+ * to perf_adjust_period() to avoid stopping it
-+ * twice.
-+ */
-+ if (delta > 0)
-+ perf_adjust_period(event, period, delta, false);
-+
-+ event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
-+ next:
-+ perf_pmu_enable(event->pmu);
-+ }
-+
-+ perf_pmu_enable(ctx->pmu);
-+ raw_spin_unlock(&ctx->lock);
-+}
-+
-+/*
-+ * Round-robin a context's events:
-+ */
-+static void rotate_ctx(struct perf_event_context *ctx)
-+{
-+ /*
-+ * Rotate the first entry last of non-pinned groups. Rotation might be
-+ * disabled by the inheritance code.
-+ */
-+ if (!ctx->rotate_disable)
-+ list_rotate_left(&ctx->flexible_groups);
-+}
-+
-+/*
-+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized
-+ * because they're strictly cpu affine and rotate_start is called with IRQs
-+ * disabled, while rotate_context is called from IRQ context.
-+ */
-+static int perf_rotate_context(struct perf_cpu_context *cpuctx)
-+{
-+ struct perf_event_context *ctx = NULL;
-+ int rotate = 0, remove = 1;
-+
-+ if (cpuctx->ctx.nr_events) {
-+ remove = 0;
-+ if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
-+ rotate = 1;
-+ }
-+
-+ ctx = cpuctx->task_ctx;
-+ if (ctx && ctx->nr_events) {
-+ remove = 0;
-+ if (ctx->nr_events != ctx->nr_active)
-+ rotate = 1;
-+ }
-+
-+ if (!rotate)
-+ goto done;
-+
-+ perf_ctx_lock(cpuctx, cpuctx->task_ctx);
-+ perf_pmu_disable(cpuctx->ctx.pmu);
-+
-+ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
-+ if (ctx)
-+ ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
-+
-+ rotate_ctx(&cpuctx->ctx);
-+ if (ctx)
-+ rotate_ctx(ctx);
-+
-+ perf_event_sched_in(cpuctx, ctx, current);
-+
-+ perf_pmu_enable(cpuctx->ctx.pmu);
-+ perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-+done:
-+ if (remove)
-+ list_del_init(&cpuctx->rotation_list);
-+
-+ return rotate;
-+}
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+bool perf_event_can_stop_tick(void)
-+{
-+ if (atomic_read(&nr_freq_events) ||
-+ __this_cpu_read(perf_throttled_count))
-+ return false;
-+ else
-+ return true;
-+}
-+#endif
-+
-+void perf_event_task_tick(void)
-+{
-+ struct list_head *head = this_cpu_ptr(&rotation_list);
-+ struct perf_cpu_context *cpuctx, *tmp;
-+ struct perf_event_context *ctx;
-+ int throttled;
-+
-+ WARN_ON(!irqs_disabled());
-+
-+ __this_cpu_inc(perf_throttled_seq);
-+ throttled = __this_cpu_xchg(perf_throttled_count, 0);
-+
-+ list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
-+ ctx = &cpuctx->ctx;
-+ perf_adjust_freq_unthr_context(ctx, throttled);
-+
-+ ctx = cpuctx->task_ctx;
-+ if (ctx)
-+ perf_adjust_freq_unthr_context(ctx, throttled);
-+ }
-+}
-+
-+static int event_enable_on_exec(struct perf_event *event,
-+ struct perf_event_context *ctx)
-+{
-+ if (!event->attr.enable_on_exec)
-+ return 0;
-+
-+ event->attr.enable_on_exec = 0;
-+ if (event->state >= PERF_EVENT_STATE_INACTIVE)
-+ return 0;
-+
-+ __perf_event_mark_enabled(event);
-+
-+ return 1;
-+}
-+
-+/*
-+ * Enable all of a task's events that have been marked enable-on-exec.
-+ * This expects task == current.
-+ */
-+static void perf_event_enable_on_exec(struct perf_event_context *ctx)
-+{
-+ struct perf_event_context *clone_ctx = NULL;
-+ struct perf_event *event;
-+ unsigned long flags;
-+ int enabled = 0;
-+ int ret;
-+
-+ local_irq_save(flags);
-+ if (!ctx || !ctx->nr_events)
-+ goto out;
-+
-+ /*
-+ * We must ctxsw out cgroup events to avoid conflict
-+ * when invoking perf_task_event_sched_in() later on
-+ * in this function. Otherwise we end up trying to
-+ * ctxswin cgroup events which are already scheduled
-+ * in.
-+ */
-+ perf_cgroup_sched_out(current, NULL);
-+
-+ raw_spin_lock(&ctx->lock);
-+ task_ctx_sched_out(ctx);
-+
-+ list_for_each_entry(event, &ctx->event_list, event_entry) {
-+ ret = event_enable_on_exec(event, ctx);
-+ if (ret)
-+ enabled = 1;
-+ }
-+
-+ /*
-+ * Unclone this context if we enabled any event.
-+ */
-+ if (enabled)
-+ clone_ctx = unclone_ctx(ctx);
-+
-+ raw_spin_unlock(&ctx->lock);
-+
-+ /*
-+ * Also calls ctxswin for cgroup events, if any:
-+ */
-+ perf_event_context_sched_in(ctx, ctx->task);
-+out:
-+ local_irq_restore(flags);
-+
-+ if (clone_ctx)
-+ put_ctx(clone_ctx);
-+}
-+
-+void perf_event_exec(void)
-+{
-+ struct perf_event_context *ctx;
-+ int ctxn;
-+
-+ rcu_read_lock();
-+ for_each_task_context_nr(ctxn) {
-+ ctx = current->perf_event_ctxp[ctxn];
-+ if (!ctx)
-+ continue;
-+
-+ perf_event_enable_on_exec(ctx);
-+ }
-+ rcu_read_unlock();
-+}
-+
-+/*
-+ * Cross CPU call to read the hardware event
-+ */
-+static void __perf_event_read(void *info)
-+{
-+ struct perf_event *event = info;
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
-+
-+ /*
-+ * If this is a task context, we need to check whether it is
-+ * the current task context of this cpu. If not it has been
-+ * scheduled out before the smp call arrived. In that case
-+ * event->count would have been updated to a recent sample
-+ * when the event was scheduled out.
-+ */
-+ if (ctx->task && cpuctx->task_ctx != ctx)
-+ return;
-+
-+ raw_spin_lock(&ctx->lock);
-+ if (ctx->is_active) {
-+ update_context_time(ctx);
-+ update_cgrp_time_from_event(event);
-+ }
-+ update_event_times(event);
-+ if (event->state == PERF_EVENT_STATE_ACTIVE)
-+ event->pmu->read(event);
-+ raw_spin_unlock(&ctx->lock);
-+}
-+
-+static inline u64 perf_event_count(struct perf_event *event)
-+{
-+ return local64_read(&event->count) + atomic64_read(&event->child_count);
-+}
-+
-+static u64 perf_event_read(struct perf_event *event)
-+{
-+ /*
-+ * If event is enabled and currently active on a CPU, update the
-+ * value in the event structure:
-+ */
-+ if (event->state == PERF_EVENT_STATE_ACTIVE) {
-+ smp_call_function_single(event->oncpu,
-+ __perf_event_read, event, 1);
-+ } else if (event->state == PERF_EVENT_STATE_INACTIVE) {
-+ struct perf_event_context *ctx = event->ctx;
-+ unsigned long flags;
-+
-+ raw_spin_lock_irqsave(&ctx->lock, flags);
-+ /*
-+ * may read while context is not active
-+ * (e.g., thread is blocked), in that case
-+ * we cannot update context time
-+ */
-+ if (ctx->is_active) {
-+ update_context_time(ctx);
-+ update_cgrp_time_from_event(event);
-+ }
-+ update_event_times(event);
-+ raw_spin_unlock_irqrestore(&ctx->lock, flags);
-+ }
-+
-+ return perf_event_count(event);
-+}
-+
-+/*
-+ * Initialize the perf_event context in a task_struct:
-+ */
-+static void __perf_event_init_context(struct perf_event_context *ctx)
-+{
-+ raw_spin_lock_init(&ctx->lock);
-+ mutex_init(&ctx->mutex);
-+ INIT_LIST_HEAD(&ctx->pinned_groups);
-+ INIT_LIST_HEAD(&ctx->flexible_groups);
-+ INIT_LIST_HEAD(&ctx->event_list);
-+ atomic_set(&ctx->refcount, 1);
-+ INIT_DELAYED_WORK(&ctx->orphans_remove, orphans_remove_work);
-+}
-+
-+static struct perf_event_context *
-+alloc_perf_context(struct pmu *pmu, struct task_struct *task)
-+{
-+ struct perf_event_context *ctx;
-+
-+ ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL);
-+ if (!ctx)
-+ return NULL;
-+
-+ __perf_event_init_context(ctx);
-+ if (task) {
-+ ctx->task = task;
-+ get_task_struct(task);
-+ }
-+ ctx->pmu = pmu;
-+
-+ return ctx;
-+}
-+
-+static struct task_struct *
-+find_lively_task_by_vpid(pid_t vpid)
-+{
-+ struct task_struct *task;
-+ int err;
-+
-+ rcu_read_lock();
-+ if (!vpid)
-+ task = current;
-+ else
-+ task = find_task_by_vpid(vpid);
-+ if (task)
-+ get_task_struct(task);
-+ rcu_read_unlock();
-+
-+ if (!task)
-+ return ERR_PTR(-ESRCH);
-+
-+ /* Reuse ptrace permission checks for now. */
-+ err = -EACCES;
-+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
-+ goto errout;
-+
-+ return task;
-+errout:
-+ put_task_struct(task);
-+ return ERR_PTR(err);
-+
-+}
-+
-+/*
-+ * Returns a matching context with refcount and pincount.
-+ */
-+static struct perf_event_context *
-+find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
-+{
-+ struct perf_event_context *ctx, *clone_ctx = NULL;
-+ struct perf_cpu_context *cpuctx;
-+ unsigned long flags;
-+ int ctxn, err;
-+
-+ if (!task) {
-+ /* Must be root to operate on a CPU event: */
-+ if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
-+ return ERR_PTR(-EACCES);
-+
-+ /*
-+ * We could be clever and allow to attach a event to an
-+ * offline CPU and activate it when the CPU comes up, but
-+ * that's for later.
-+ */
-+ if (!cpu_online(cpu))
-+ return ERR_PTR(-ENODEV);
-+
-+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
-+ ctx = &cpuctx->ctx;
-+ get_ctx(ctx);
-+ ++ctx->pin_count;
-+
-+ return ctx;
-+ }
-+
-+ err = -EINVAL;
-+ ctxn = pmu->task_ctx_nr;
-+ if (ctxn < 0)
-+ goto errout;
-+
-+retry:
-+ ctx = perf_lock_task_context(task, ctxn, &flags);
-+ if (ctx) {
-+ clone_ctx = unclone_ctx(ctx);
-+ ++ctx->pin_count;
-+ raw_spin_unlock_irqrestore(&ctx->lock, flags);
-+
-+ if (clone_ctx)
-+ put_ctx(clone_ctx);
-+ } else {
-+ ctx = alloc_perf_context(pmu, task);
-+ err = -ENOMEM;
-+ if (!ctx)
-+ goto errout;
-+
-+ err = 0;
-+ mutex_lock(&task->perf_event_mutex);
-+ /*
-+ * If it has already passed perf_event_exit_task().
-+ * we must see PF_EXITING, it takes this mutex too.
-+ */
-+ if (task->flags & PF_EXITING)
-+ err = -ESRCH;
-+ else if (task->perf_event_ctxp[ctxn])
-+ err = -EAGAIN;
-+ else {
-+ get_ctx(ctx);
-+ ++ctx->pin_count;
-+ rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx);
-+ }
-+ mutex_unlock(&task->perf_event_mutex);
-+
-+ if (unlikely(err)) {
-+ put_ctx(ctx);
-+
-+ if (err == -EAGAIN)
-+ goto retry;
-+ goto errout;
-+ }
-+ }
-+
-+ return ctx;
-+
-+errout:
-+ return ERR_PTR(err);
-+}
-+
-+static void perf_event_free_filter(struct perf_event *event);
-+
-+static void free_event_rcu(struct rcu_head *head)
-+{
-+ struct perf_event *event;
-+
-+ event = container_of(head, struct perf_event, rcu_head);
-+ if (event->ns)
-+ put_pid_ns(event->ns);
-+ perf_event_free_filter(event);
-+ kfree(event);
-+}
-+
-+static void ring_buffer_put(struct ring_buffer *rb);
-+static void ring_buffer_attach(struct perf_event *event,
-+ struct ring_buffer *rb);
-+
-+static void unaccount_event_cpu(struct perf_event *event, int cpu)
-+{
-+ if (event->parent)
-+ return;
-+
-+ if (has_branch_stack(event)) {
-+ if (!(event->attach_state & PERF_ATTACH_TASK))
-+ atomic_dec(&per_cpu(perf_branch_stack_events, cpu));
-+ }
-+ if (is_cgroup_event(event))
-+ atomic_dec(&per_cpu(perf_cgroup_events, cpu));
-+}
-+
-+static void unaccount_event(struct perf_event *event)
-+{
-+ if (event->parent)
-+ return;
-+
-+ if (event->attach_state & PERF_ATTACH_TASK)
-+ static_key_slow_dec_deferred(&perf_sched_events);
-+ if (event->attr.mmap || event->attr.mmap_data)
-+ atomic_dec(&nr_mmap_events);
-+ if (event->attr.comm)
-+ atomic_dec(&nr_comm_events);
-+ if (event->attr.task)
-+ atomic_dec(&nr_task_events);
-+ if (event->attr.freq)
-+ atomic_dec(&nr_freq_events);
-+ if (is_cgroup_event(event))
-+ static_key_slow_dec_deferred(&perf_sched_events);
-+ if (has_branch_stack(event))
-+ static_key_slow_dec_deferred(&perf_sched_events);
-+
-+ unaccount_event_cpu(event, event->cpu);
-+}
-+
-+static void __free_event(struct perf_event *event)
-+{
-+ if (!event->parent) {
-+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
-+ put_callchain_buffers();
-+ }
-+
-+ if (event->destroy)
-+ event->destroy(event);
-+
-+ if (event->ctx)
-+ put_ctx(event->ctx);
-+
-+ if (event->pmu)
-+ module_put(event->pmu->module);
-+
-+ call_rcu(&event->rcu_head, free_event_rcu);
-+}
-+
-+static void _free_event(struct perf_event *event)
-+{
-+ irq_work_sync(&event->pending);
-+
-+ unaccount_event(event);
-+
-+ if (event->rb) {
-+ /*
-+ * Can happen when we close an event with re-directed output.
-+ *
-+ * Since we have a 0 refcount, perf_mmap_close() will skip
-+ * over us; possibly making our ring_buffer_put() the last.
-+ */
-+ mutex_lock(&event->mmap_mutex);
-+ ring_buffer_attach(event, NULL);
-+ mutex_unlock(&event->mmap_mutex);
-+ }
-+
-+ if (is_cgroup_event(event))
-+ perf_detach_cgroup(event);
-+
-+ __free_event(event);
-+}
-+
-+/*
-+ * Used to free events which have a known refcount of 1, such as in error paths
-+ * where the event isn't exposed yet and inherited events.
-+ */
-+static void free_event(struct perf_event *event)
-+{
-+ if (WARN(atomic_long_cmpxchg(&event->refcount, 1, 0) != 1,
-+ "unexpected event refcount: %ld; ptr=%p\n",
-+ atomic_long_read(&event->refcount), event)) {
-+ /* leak to avoid use-after-free */
-+ return;
-+ }
-+
-+ _free_event(event);
-+}
-+
-+/*
-+ * Remove user event from the owner task.
-+ */
-+static void perf_remove_from_owner(struct perf_event *event)
-+{
-+ struct task_struct *owner;
-+
-+ rcu_read_lock();
-+ owner = ACCESS_ONCE(event->owner);
-+ /*
-+ * Matches the smp_wmb() in perf_event_exit_task(). If we observe
-+ * !owner it means the list deletion is complete and we can indeed
-+ * free this event, otherwise we need to serialize on
-+ * owner->perf_event_mutex.
-+ */
-+ smp_read_barrier_depends();
-+ if (owner) {
-+ /*
-+ * Since delayed_put_task_struct() also drops the last
-+ * task reference we can safely take a new reference
-+ * while holding the rcu_read_lock().
-+ */
-+ get_task_struct(owner);
-+ }
-+ rcu_read_unlock();
-+
-+ if (owner) {
-+ mutex_lock(&owner->perf_event_mutex);
-+ /*
-+ * We have to re-check the event->owner field, if it is cleared
-+ * we raced with perf_event_exit_task(), acquiring the mutex
-+ * ensured they're done, and we can proceed with freeing the
-+ * event.
-+ */
-+ if (event->owner)
-+ list_del_init(&event->owner_entry);
-+ mutex_unlock(&owner->perf_event_mutex);
-+ put_task_struct(owner);
-+ }
-+}
-+
-+/*
-+ * Called when the last reference to the file is gone.
-+ */
-+static void put_event(struct perf_event *event)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+
-+ if (!atomic_long_dec_and_test(&event->refcount))
-+ return;
-+
-+ if (!is_kernel_event(event))
-+ perf_remove_from_owner(event);
-+
-+ WARN_ON_ONCE(ctx->parent_ctx);
-+ /*
-+ * There are two ways this annotation is useful:
-+ *
-+ * 1) there is a lock recursion from perf_event_exit_task
-+ * see the comment there.
-+ *
-+ * 2) there is a lock-inversion with mmap_sem through
-+ * perf_event_read_group(), which takes faults while
-+ * holding ctx->mutex, however this is called after
-+ * the last filedesc died, so there is no possibility
-+ * to trigger the AB-BA case.
-+ */
-+ mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
-+ perf_remove_from_context(event, true);
-+ mutex_unlock(&ctx->mutex);
-+
-+ _free_event(event);
-+}
-+
-+int perf_event_release_kernel(struct perf_event *event)
-+{
-+ put_event(event);
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(perf_event_release_kernel);
-+
-+static int perf_release(struct inode *inode, struct file *file)
-+{
-+ put_event(file->private_data);
-+ return 0;
-+}
-+
-+/*
-+ * Remove all orphanes events from the context.
-+ */
-+static void orphans_remove_work(struct work_struct *work)
-+{
-+ struct perf_event_context *ctx;
-+ struct perf_event *event, *tmp;
-+
-+ ctx = container_of(work, struct perf_event_context,
-+ orphans_remove.work);
-+
-+ mutex_lock(&ctx->mutex);
-+ list_for_each_entry_safe(event, tmp, &ctx->event_list, event_entry) {
-+ struct perf_event *parent_event = event->parent;
-+
-+ if (!is_orphaned_child(event))
-+ continue;
-+
-+ perf_remove_from_context(event, true);
-+
-+ mutex_lock(&parent_event->child_mutex);
-+ list_del_init(&event->child_list);
-+ mutex_unlock(&parent_event->child_mutex);
-+
-+ free_event(event);
-+ put_event(parent_event);
-+ }
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+ ctx->orphans_remove_sched = false;
-+ raw_spin_unlock_irq(&ctx->lock);
-+ mutex_unlock(&ctx->mutex);
-+
-+ put_ctx(ctx);
-+}
-+
-+u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
-+{
-+ struct perf_event *child;
-+ u64 total = 0;
-+
-+ *enabled = 0;
-+ *running = 0;
-+
-+ mutex_lock(&event->child_mutex);
-+ total += perf_event_read(event);
-+ *enabled += event->total_time_enabled +
-+ atomic64_read(&event->child_total_time_enabled);
-+ *running += event->total_time_running +
-+ atomic64_read(&event->child_total_time_running);
-+
-+ list_for_each_entry(child, &event->child_list, child_list) {
-+ total += perf_event_read(child);
-+ *enabled += child->total_time_enabled;
-+ *running += child->total_time_running;
-+ }
-+ mutex_unlock(&event->child_mutex);
-+
-+ return total;
-+}
-+EXPORT_SYMBOL_GPL(perf_event_read_value);
-+
-+static int perf_event_read_group(struct perf_event *event,
-+ u64 read_format, char __user *buf)
-+{
-+ struct perf_event *leader = event->group_leader, *sub;
-+ int n = 0, size = 0, ret = -EFAULT;
-+ struct perf_event_context *ctx = leader->ctx;
-+ u64 values[5];
-+ u64 count, enabled, running;
-+
-+ mutex_lock(&ctx->mutex);
-+ count = perf_event_read_value(leader, &enabled, &running);
-+
-+ values[n++] = 1 + leader->nr_siblings;
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-+ values[n++] = enabled;
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-+ values[n++] = running;
-+ values[n++] = count;
-+ if (read_format & PERF_FORMAT_ID)
-+ values[n++] = primary_event_id(leader);
-+
-+ size = n * sizeof(u64);
-+
-+ if (copy_to_user(buf, values, size))
-+ goto unlock;
-+
-+ ret = size;
-+
-+ list_for_each_entry(sub, &leader->sibling_list, group_entry) {
-+ n = 0;
-+
-+ values[n++] = perf_event_read_value(sub, &enabled, &running);
-+ if (read_format & PERF_FORMAT_ID)
-+ values[n++] = primary_event_id(sub);
-+
-+ size = n * sizeof(u64);
-+
-+ if (copy_to_user(buf + ret, values, size)) {
-+ ret = -EFAULT;
-+ goto unlock;
-+ }
-+
-+ ret += size;
-+ }
-+unlock:
-+ mutex_unlock(&ctx->mutex);
-+
-+ return ret;
-+}
-+
-+static int perf_event_read_one(struct perf_event *event,
-+ u64 read_format, char __user *buf)
-+{
-+ u64 enabled, running;
-+ u64 values[4];
-+ int n = 0;
-+
-+ values[n++] = perf_event_read_value(event, &enabled, &running);
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-+ values[n++] = enabled;
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-+ values[n++] = running;
-+ if (read_format & PERF_FORMAT_ID)
-+ values[n++] = primary_event_id(event);
-+
-+ if (copy_to_user(buf, values, n * sizeof(u64)))
-+ return -EFAULT;
-+
-+ return n * sizeof(u64);
-+}
-+
-+static bool is_event_hup(struct perf_event *event)
-+{
-+ bool no_children;
-+
-+ if (event->state != PERF_EVENT_STATE_EXIT)
-+ return false;
-+
-+ mutex_lock(&event->child_mutex);
-+ no_children = list_empty(&event->child_list);
-+ mutex_unlock(&event->child_mutex);
-+ return no_children;
-+}
-+
-+/*
-+ * Read the performance event - simple non blocking version for now
-+ */
-+static ssize_t
-+perf_read_hw(struct perf_event *event, char __user *buf, size_t count)
-+{
-+ u64 read_format = event->attr.read_format;
-+ int ret;
-+
-+ /*
-+ * Return end-of-file for a read on a event that is in
-+ * error state (i.e. because it was pinned but it couldn't be
-+ * scheduled on to the CPU at some point).
-+ */
-+ if (event->state == PERF_EVENT_STATE_ERROR)
-+ return 0;
-+
-+ if (count < event->read_size)
-+ return -ENOSPC;
-+
-+ WARN_ON_ONCE(event->ctx->parent_ctx);
-+ if (read_format & PERF_FORMAT_GROUP)
-+ ret = perf_event_read_group(event, read_format, buf);
-+ else
-+ ret = perf_event_read_one(event, read_format, buf);
-+
-+ return ret;
-+}
-+
-+static ssize_t
-+perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-+{
-+ struct perf_event *event = file->private_data;
-+
-+ return perf_read_hw(event, buf, count);
-+}
-+
-+static unsigned int perf_poll(struct file *file, poll_table *wait)
-+{
-+ struct perf_event *event = file->private_data;
-+ struct ring_buffer *rb;
-+ unsigned int events = POLLHUP;
-+
-+ poll_wait(file, &event->waitq, wait);
-+
-+ if (is_event_hup(event))
-+ return events;
-+
-+ /*
-+ * Pin the event->rb by taking event->mmap_mutex; otherwise
-+ * perf_event_set_output() can swizzle our rb and make us miss wakeups.
-+ */
-+ mutex_lock(&event->mmap_mutex);
-+ rb = event->rb;
-+ if (rb)
-+ events = atomic_xchg(&rb->poll, 0);
-+ mutex_unlock(&event->mmap_mutex);
-+ return events;
-+}
-+
-+static void perf_event_reset(struct perf_event *event)
-+{
-+ (void)perf_event_read(event);
-+ local64_set(&event->count, 0);
-+ perf_event_update_userpage(event);
-+}
-+
-+/*
-+ * Holding the top-level event's child_mutex means that any
-+ * descendant process that has inherited this event will block
-+ * in sync_child_event if it goes to exit, thus satisfying the
-+ * task existence requirements of perf_event_enable/disable.
-+ */
-+static void perf_event_for_each_child(struct perf_event *event,
-+ void (*func)(struct perf_event *))
-+{
-+ struct perf_event *child;
-+
-+ WARN_ON_ONCE(event->ctx->parent_ctx);
-+ mutex_lock(&event->child_mutex);
-+ func(event);
-+ list_for_each_entry(child, &event->child_list, child_list)
-+ func(child);
-+ mutex_unlock(&event->child_mutex);
-+}
-+
-+static void perf_event_for_each(struct perf_event *event,
-+ void (*func)(struct perf_event *))
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ struct perf_event *sibling;
-+
-+ WARN_ON_ONCE(ctx->parent_ctx);
-+ mutex_lock(&ctx->mutex);
-+ event = event->group_leader;
-+
-+ perf_event_for_each_child(event, func);
-+ list_for_each_entry(sibling, &event->sibling_list, group_entry)
-+ perf_event_for_each_child(sibling, func);
-+ mutex_unlock(&ctx->mutex);
-+}
-+
-+static int perf_event_period(struct perf_event *event, u64 __user *arg)
-+{
-+ struct perf_event_context *ctx = event->ctx;
-+ int ret = 0, active;
-+ u64 value;
-+
-+ if (!is_sampling_event(event))
-+ return -EINVAL;
-+
-+ if (copy_from_user(&value, arg, sizeof(value)))
-+ return -EFAULT;
-+
-+ if (!value)
-+ return -EINVAL;
-+
-+ raw_spin_lock_irq(&ctx->lock);
-+ if (event->attr.freq) {
-+ if (value > sysctl_perf_event_sample_rate) {
-+ ret = -EINVAL;
-+ goto unlock;
-+ }
-+
-+ event->attr.sample_freq = value;
-+ } else {
-+ event->attr.sample_period = value;
-+ event->hw.sample_period = value;
-+ }
-+
-+ active = (event->state == PERF_EVENT_STATE_ACTIVE);
-+ if (active) {
-+ perf_pmu_disable(ctx->pmu);
-+ event->pmu->stop(event, PERF_EF_UPDATE);
-+ }
-+
-+ local64_set(&event->hw.period_left, 0);
-+
-+ if (active) {
-+ event->pmu->start(event, PERF_EF_RELOAD);
-+ perf_pmu_enable(ctx->pmu);
-+ }
-+
-+unlock:
-+ raw_spin_unlock_irq(&ctx->lock);
-+
-+ return ret;
-+}
-+
-+static const struct file_operations perf_fops;
-+
-+static inline int perf_fget_light(int fd, struct fd *p)
-+{
-+ struct fd f = fdget(fd);
-+ if (!f.file)
-+ return -EBADF;
-+
-+ if (f.file->f_op != &perf_fops) {
-+ fdput(f);
-+ return -EBADF;
-+ }
-+ *p = f;
-+ return 0;
-+}
-+
-+static int perf_event_set_output(struct perf_event *event,
-+ struct perf_event *output_event);
-+static int perf_event_set_filter(struct perf_event *event, void __user *arg);
-+
-+static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ struct perf_event *event = file->private_data;
-+ void (*func)(struct perf_event *);
-+ u32 flags = arg;
-+
-+ switch (cmd) {
-+ case PERF_EVENT_IOC_ENABLE:
-+ func = perf_event_enable;
-+ break;
-+ case PERF_EVENT_IOC_DISABLE:
-+ func = perf_event_disable;
-+ break;
-+ case PERF_EVENT_IOC_RESET:
-+ func = perf_event_reset;
-+ break;
-+
-+ case PERF_EVENT_IOC_REFRESH:
-+ return perf_event_refresh(event, arg);
-+
-+ case PERF_EVENT_IOC_PERIOD:
-+ return perf_event_period(event, (u64 __user *)arg);
-+
-+ case PERF_EVENT_IOC_ID:
-+ {
-+ u64 id = primary_event_id(event);
-+
-+ if (copy_to_user((void __user *)arg, &id, sizeof(id)))
-+ return -EFAULT;
-+ return 0;
-+ }
-+
-+ case PERF_EVENT_IOC_SET_OUTPUT:
-+ {
-+ int ret;
-+ if (arg != -1) {
-+ struct perf_event *output_event;
-+ struct fd output;
-+ ret = perf_fget_light(arg, &output);
-+ if (ret)
-+ return ret;
-+ output_event = output.file->private_data;
-+ ret = perf_event_set_output(event, output_event);
-+ fdput(output);
-+ } else {
-+ ret = perf_event_set_output(event, NULL);
-+ }
-+ return ret;
-+ }
-+
-+ case PERF_EVENT_IOC_SET_FILTER:
-+ return perf_event_set_filter(event, (void __user *)arg);
-+
-+ default:
-+ return -ENOTTY;
-+ }
-+
-+ if (flags & PERF_IOC_FLAG_GROUP)
-+ perf_event_for_each(event, func);
-+ else
-+ perf_event_for_each_child(event, func);
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_COMPAT
-+static long perf_compat_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ switch (_IOC_NR(cmd)) {
-+ case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
-+ case _IOC_NR(PERF_EVENT_IOC_ID):
-+ /* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
-+ if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
-+ cmd &= ~IOCSIZE_MASK;
-+ cmd |= sizeof(void *) << IOCSIZE_SHIFT;
-+ }
-+ break;
-+ }
-+ return perf_ioctl(file, cmd, arg);
-+}
-+#else
-+# define perf_compat_ioctl NULL
-+#endif
-+
-+int perf_event_task_enable(void)
-+{
-+ struct perf_event *event;
-+
-+ mutex_lock(&current->perf_event_mutex);
-+ list_for_each_entry(event, &current->perf_event_list, owner_entry)
-+ perf_event_for_each_child(event, perf_event_enable);
-+ mutex_unlock(&current->perf_event_mutex);
-+
-+ return 0;
-+}
-+
-+int perf_event_task_disable(void)
-+{
-+ struct perf_event *event;
-+
-+ mutex_lock(&current->perf_event_mutex);
-+ list_for_each_entry(event, &current->perf_event_list, owner_entry)
-+ perf_event_for_each_child(event, perf_event_disable);
-+ mutex_unlock(&current->perf_event_mutex);
-+
-+ return 0;
-+}
-+
-+static int perf_event_index(struct perf_event *event)
-+{
-+ if (event->hw.state & PERF_HES_STOPPED)
-+ return 0;
-+
-+ if (event->state != PERF_EVENT_STATE_ACTIVE)
-+ return 0;
-+
-+ return event->pmu->event_idx(event);
-+}
-+
-+static void calc_timer_values(struct perf_event *event,
-+ u64 *now,
-+ u64 *enabled,
-+ u64 *running)
-+{
-+ u64 ctx_time;
-+
-+ *now = perf_clock();
-+ ctx_time = event->shadow_ctx_time + *now;
-+ *enabled = ctx_time - event->tstamp_enabled;
-+ *running = ctx_time - event->tstamp_running;
-+}
-+
-+static void perf_event_init_userpage(struct perf_event *event)
-+{
-+ struct perf_event_mmap_page *userpg;
-+ struct ring_buffer *rb;
-+
-+ rcu_read_lock();
-+ rb = rcu_dereference(event->rb);
-+ if (!rb)
-+ goto unlock;
-+
-+ userpg = rb->user_page;
-+
-+ /* Allow new userspace to detect that bit 0 is deprecated */
-+ userpg->cap_bit0_is_deprecated = 1;
-+ userpg->size = offsetof(struct perf_event_mmap_page, __reserved);
-+
-+unlock:
-+ rcu_read_unlock();
-+}
-+
-+void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
-+{
-+}
-+
-+/*
-+ * Callers need to ensure there can be no nesting of this function, otherwise
-+ * the seqlock logic goes bad. We can not serialize this because the arch
-+ * code calls this from NMI context.
-+ */
-+void perf_event_update_userpage(struct perf_event *event)
-+{
-+ struct perf_event_mmap_page *userpg;
-+ struct ring_buffer *rb;
-+ u64 enabled, running, now;
-+
-+ rcu_read_lock();
-+ rb = rcu_dereference(event->rb);
-+ if (!rb)
-+ goto unlock;
-+
-+ /*
-+ * compute total_time_enabled, total_time_running
-+ * based on snapshot values taken when the event
-+ * was last scheduled in.
-+ *
-+ * we cannot simply called update_context_time()
-+ * because of locking issue as we can be called in
-+ * NMI context
-+ */
-+ calc_timer_values(event, &now, &enabled, &running);
-+
-+ userpg = rb->user_page;
-+ /*
-+ * Disable preemption so as to not let the corresponding user-space
-+ * spin too long if we get preempted.
-+ */
-+ preempt_disable();
-+ ++userpg->lock;
-+ barrier();
-+ userpg->index = perf_event_index(event);
-+ userpg->offset = perf_event_count(event);
-+ if (userpg->index)
-+ userpg->offset -= local64_read(&event->hw.prev_count);
-+
-+ userpg->time_enabled = enabled +
-+ atomic64_read(&event->child_total_time_enabled);
-+
-+ userpg->time_running = running +
-+ atomic64_read(&event->child_total_time_running);
-+
-+ arch_perf_update_userpage(userpg, now);
-+
-+ barrier();
-+ ++userpg->lock;
-+ preempt_enable();
-+unlock:
-+ rcu_read_unlock();
-+}
-+
-+static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+ struct perf_event *event = vma->vm_file->private_data;
-+ struct ring_buffer *rb;
-+ int ret = VM_FAULT_SIGBUS;
-+
-+ if (vmf->flags & FAULT_FLAG_MKWRITE) {
-+ if (vmf->pgoff == 0)
-+ ret = 0;
-+ return ret;
-+ }
-+
-+ rcu_read_lock();
-+ rb = rcu_dereference(event->rb);
-+ if (!rb)
-+ goto unlock;
-+
-+ if (vmf->pgoff && (vmf->flags & FAULT_FLAG_WRITE))
-+ goto unlock;
-+
-+ vmf->page = perf_mmap_to_page(rb, vmf->pgoff);
-+ if (!vmf->page)
-+ goto unlock;
-+
-+ get_page(vmf->page);
-+ vmf->page->mapping = vma->vm_file->f_mapping;
-+ vmf->page->index = vmf->pgoff;
-+
-+ ret = 0;
-+unlock:
-+ rcu_read_unlock();
-+
-+ return ret;
-+}
-+
-+static void ring_buffer_attach(struct perf_event *event,
-+ struct ring_buffer *rb)
-+{
-+ struct ring_buffer *old_rb = NULL;
-+ unsigned long flags;
-+
-+ if (event->rb) {
-+ /*
-+ * Should be impossible, we set this when removing
-+ * event->rb_entry and wait/clear when adding event->rb_entry.
-+ */
-+ WARN_ON_ONCE(event->rcu_pending);
-+
-+ old_rb = event->rb;
-+ event->rcu_batches = get_state_synchronize_rcu();
-+ event->rcu_pending = 1;
-+
-+ spin_lock_irqsave(&old_rb->event_lock, flags);
-+ list_del_rcu(&event->rb_entry);
-+ spin_unlock_irqrestore(&old_rb->event_lock, flags);
-+ }
-+
-+ if (event->rcu_pending && rb) {
-+ cond_synchronize_rcu(event->rcu_batches);
-+ event->rcu_pending = 0;
-+ }
-+
-+ if (rb) {
-+ spin_lock_irqsave(&rb->event_lock, flags);
-+ list_add_rcu(&event->rb_entry, &rb->event_list);
-+ spin_unlock_irqrestore(&rb->event_lock, flags);
-+ }
-+
-+ rcu_assign_pointer(event->rb, rb);
-+
-+ if (old_rb) {
-+ ring_buffer_put(old_rb);
-+ /*
-+ * Since we detached before setting the new rb, so that we
-+ * could attach the new rb, we could have missed a wakeup.
-+ * Provide it now.
-+ */
-+ wake_up_all(&event->waitq);
-+ }
-+}
-+
-+static void ring_buffer_wakeup(struct perf_event *event)
-+{
-+ struct ring_buffer *rb;
-+
-+ rcu_read_lock();
-+ rb = rcu_dereference(event->rb);
-+ if (rb) {
-+ list_for_each_entry_rcu(event, &rb->event_list, rb_entry)
-+ wake_up_all(&event->waitq);
-+ }
-+ rcu_read_unlock();
-+}
-+
-+static void rb_free_rcu(struct rcu_head *rcu_head)
-+{
-+ struct ring_buffer *rb;
-+
-+ rb = container_of(rcu_head, struct ring_buffer, rcu_head);
-+ rb_free(rb);
-+}
-+
-+static struct ring_buffer *ring_buffer_get(struct perf_event *event)
-+{
-+ struct ring_buffer *rb;
-+
-+ rcu_read_lock();
-+ rb = rcu_dereference(event->rb);
-+ if (rb) {
-+ if (!atomic_inc_not_zero(&rb->refcount))
-+ rb = NULL;
-+ }
-+ rcu_read_unlock();
-+
-+ return rb;
-+}
-+
-+static void ring_buffer_put(struct ring_buffer *rb)
-+{
-+ if (!atomic_dec_and_test(&rb->refcount))
-+ return;
-+
-+ WARN_ON_ONCE(!list_empty(&rb->event_list));
-+
-+ call_rcu(&rb->rcu_head, rb_free_rcu);
-+}
-+
-+static void perf_mmap_open(struct vm_area_struct *vma)
-+{
-+ struct perf_event *event = vma->vm_file->private_data;
-+
-+ atomic_inc(&event->mmap_count);
-+ atomic_inc(&event->rb->mmap_count);
-+}
-+
-+/*
-+ * A buffer can be mmap()ed multiple times; either directly through the same
-+ * event, or through other events by use of perf_event_set_output().
-+ *
-+ * In order to undo the VM accounting done by perf_mmap() we need to destroy
-+ * the buffer here, where we still have a VM context. This means we need
-+ * to detach all events redirecting to us.
-+ */
-+static void perf_mmap_close(struct vm_area_struct *vma)
-+{
-+ struct perf_event *event = vma->vm_file->private_data;
-+
-+ struct ring_buffer *rb = ring_buffer_get(event);
-+ struct user_struct *mmap_user = rb->mmap_user;
-+ int mmap_locked = rb->mmap_locked;
-+ unsigned long size = perf_data_size(rb);
-+
-+ atomic_dec(&rb->mmap_count);
-+
-+ if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex))
-+ goto out_put;
-+
-+ ring_buffer_attach(event, NULL);
-+ mutex_unlock(&event->mmap_mutex);
-+
-+ /* If there's still other mmap()s of this buffer, we're done. */
-+ if (atomic_read(&rb->mmap_count))
-+ goto out_put;
-+
-+ /*
-+ * No other mmap()s, detach from all other events that might redirect
-+ * into the now unreachable buffer. Somewhat complicated by the
-+ * fact that rb::event_lock otherwise nests inside mmap_mutex.
-+ */
-+again:
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(event, &rb->event_list, rb_entry) {
-+ if (!atomic_long_inc_not_zero(&event->refcount)) {
-+ /*
-+ * This event is en-route to free_event() which will
-+ * detach it and remove it from the list.
-+ */
-+ continue;
-+ }
-+ rcu_read_unlock();
-+
-+ mutex_lock(&event->mmap_mutex);
-+ /*
-+ * Check we didn't race with perf_event_set_output() which can
-+ * swizzle the rb from under us while we were waiting to
-+ * acquire mmap_mutex.
-+ *
-+ * If we find a different rb; ignore this event, a next
-+ * iteration will no longer find it on the list. We have to
-+ * still restart the iteration to make sure we're not now
-+ * iterating the wrong list.
-+ */
-+ if (event->rb == rb)
-+ ring_buffer_attach(event, NULL);
-+
-+ mutex_unlock(&event->mmap_mutex);
-+ put_event(event);
-+
-+ /*
-+ * Restart the iteration; either we're on the wrong list or
-+ * destroyed its integrity by doing a deletion.
-+ */
-+ goto again;
-+ }
-+ rcu_read_unlock();
-+
-+ /*
-+ * It could be there's still a few 0-ref events on the list; they'll
-+ * get cleaned up by free_event() -- they'll also still have their
-+ * ref on the rb and will free it whenever they are done with it.
-+ *
-+ * Aside from that, this buffer is 'fully' detached and unmapped,
-+ * undo the VM accounting.
-+ */
-+
-+ atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm);
-+ vma->vm_mm->pinned_vm -= mmap_locked;
-+ free_uid(mmap_user);
-+
-+out_put:
-+ ring_buffer_put(rb); /* could be last */
-+}
-+
-+static const struct vm_operations_struct perf_mmap_vmops = {
-+ .open = perf_mmap_open,
-+ .close = perf_mmap_close,
-+ .fault = perf_mmap_fault,
-+ .page_mkwrite = perf_mmap_fault,
-+};
-+
-+static int perf_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ struct perf_event *event = file->private_data;
-+ unsigned long user_locked, user_lock_limit;
-+ struct user_struct *user = current_user();
-+ unsigned long locked, lock_limit;
-+ struct ring_buffer *rb;
-+ unsigned long vma_size;
-+ unsigned long nr_pages;
-+ long user_extra, extra;
-+ int ret = 0, flags = 0;
-+
-+ /*
-+ * Don't allow mmap() of inherited per-task counters. This would
-+ * create a performance issue due to all children writing to the
-+ * same rb.
-+ */
-+ if (event->cpu == -1 && event->attr.inherit)
-+ return -EINVAL;
-+
-+ if (!(vma->vm_flags & VM_SHARED))
-+ return -EINVAL;
-+
-+ vma_size = vma->vm_end - vma->vm_start;
-+ nr_pages = (vma_size / PAGE_SIZE) - 1;
-+
-+ /*
-+ * If we have rb pages ensure they're a power-of-two number, so we
-+ * can do bitmasks instead of modulo.
-+ */
-+ if (nr_pages != 0 && !is_power_of_2(nr_pages))
-+ return -EINVAL;
-+
-+ if (vma_size != PAGE_SIZE * (1 + nr_pages))
-+ return -EINVAL;
-+
-+ if (vma->vm_pgoff != 0)
-+ return -EINVAL;
-+
-+ WARN_ON_ONCE(event->ctx->parent_ctx);
-+again:
-+ mutex_lock(&event->mmap_mutex);
-+ if (event->rb) {
-+ if (event->rb->nr_pages != nr_pages) {
-+ ret = -EINVAL;
-+ goto unlock;
-+ }
-+
-+ if (!atomic_inc_not_zero(&event->rb->mmap_count)) {
-+ /*
-+ * Raced against perf_mmap_close() through
-+ * perf_event_set_output(). Try again, hope for better
-+ * luck.
-+ */
-+ mutex_unlock(&event->mmap_mutex);
-+ goto again;
-+ }
-+
-+ goto unlock;
-+ }
-+
-+ user_extra = nr_pages + 1;
-+ user_lock_limit = sysctl_perf_event_mlock >> (PAGE_SHIFT - 10);
-+
-+ /*
-+ * Increase the limit linearly with more CPUs:
-+ */
-+ user_lock_limit *= num_online_cpus();
-+
-+ user_locked = atomic_long_read(&user->locked_vm) + user_extra;
-+
-+ extra = 0;
-+ if (user_locked > user_lock_limit)
-+ extra = user_locked - user_lock_limit;
-+
-+ lock_limit = rlimit(RLIMIT_MEMLOCK);
-+ lock_limit >>= PAGE_SHIFT;
-+ locked = vma->vm_mm->pinned_vm + extra;
-+
-+ if ((locked > lock_limit) && perf_paranoid_tracepoint_raw() &&
-+ !capable(CAP_IPC_LOCK)) {
-+ ret = -EPERM;
-+ goto unlock;
-+ }
-+
-+ WARN_ON(event->rb);
-+
-+ if (vma->vm_flags & VM_WRITE)
-+ flags |= RING_BUFFER_WRITABLE;
-+
-+ rb = rb_alloc(nr_pages,
-+ event->attr.watermark ? event->attr.wakeup_watermark : 0,
-+ event->cpu, flags);
-+
-+ if (!rb) {
-+ ret = -ENOMEM;
-+ goto unlock;
-+ }
-+
-+ atomic_set(&rb->mmap_count, 1);
-+ rb->mmap_locked = extra;
-+ rb->mmap_user = get_current_user();
-+
-+ atomic_long_add(user_extra, &user->locked_vm);
-+ vma->vm_mm->pinned_vm += extra;
-+
-+ ring_buffer_attach(event, rb);
-+
-+ perf_event_init_userpage(event);
-+ perf_event_update_userpage(event);
-+
-+unlock:
-+ if (!ret)
-+ atomic_inc(&event->mmap_count);
-+ mutex_unlock(&event->mmap_mutex);
-+
-+ /*
-+ * Since pinned accounting is per vm we cannot allow fork() to copy our
-+ * vma.
-+ */
-+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP;
-+ vma->vm_ops = &perf_mmap_vmops;
-+
-+ return ret;
-+}
-+
-+static int perf_fasync(int fd, struct file *filp, int on)
-+{
-+ struct inode *inode = file_inode(filp);
-+ struct perf_event *event = filp->private_data;
-+ int retval;
-+
-+ mutex_lock(&inode->i_mutex);
-+ retval = fasync_helper(fd, filp, on, &event->fasync);
-+ mutex_unlock(&inode->i_mutex);
-+
-+ if (retval < 0)
-+ return retval;
-+
-+ return 0;
-+}
-+
-+static const struct file_operations perf_fops = {
-+ .llseek = no_llseek,
-+ .release = perf_release,
-+ .read = perf_read,
-+ .poll = perf_poll,
-+ .unlocked_ioctl = perf_ioctl,
-+ .compat_ioctl = perf_compat_ioctl,
-+ .mmap = perf_mmap,
-+ .fasync = perf_fasync,
-+};
-+
-+/*
-+ * Perf event wakeup
-+ *
-+ * If there's data, ensure we set the poll() state and publish everything
-+ * to user-space before waking everybody up.
-+ */
-+
-+void perf_event_wakeup(struct perf_event *event)
-+{
-+ ring_buffer_wakeup(event);
-+
-+ if (event->pending_kill) {
-+ kill_fasync(&event->fasync, SIGIO, event->pending_kill);
-+ event->pending_kill = 0;
-+ }
-+}
-+
-+static void perf_pending_event(struct irq_work *entry)
-+{
-+ struct perf_event *event = container_of(entry,
-+ struct perf_event, pending);
-+ int rctx;
-+
-+ rctx = perf_swevent_get_recursion_context();
-+ /*
-+ * If we 'fail' here, that's OK, it means recursion is already disabled
-+ * and we won't recurse 'further'.
-+ */
-+
-+ if (event->pending_disable) {
-+ event->pending_disable = 0;
-+ __perf_event_disable(event);
-+ }
-+
-+ if (event->pending_wakeup) {
-+ event->pending_wakeup = 0;
-+ perf_event_wakeup(event);
-+ }
-+
-+ if (rctx >= 0)
-+ perf_swevent_put_recursion_context(rctx);
-+}
-+
-+/*
-+ * We assume there is only KVM supporting the callbacks.
-+ * Later on, we might change it to a list if there is
-+ * another virtualization implementation supporting the callbacks.
-+ */
-+struct perf_guest_info_callbacks *perf_guest_cbs;
-+
-+int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs)
-+{
-+ perf_guest_cbs = cbs;
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(perf_register_guest_info_callbacks);
-+
-+int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs)
-+{
-+ perf_guest_cbs = NULL;
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks);
-+
-+static void
-+perf_output_sample_regs(struct perf_output_handle *handle,
-+ struct pt_regs *regs, u64 mask)
-+{
-+ int bit;
-+
-+ for_each_set_bit(bit, (const unsigned long *) &mask,
-+ sizeof(mask) * BITS_PER_BYTE) {
-+ u64 val;
-+
-+ val = perf_reg_value(regs, bit);
-+ perf_output_put(handle, val);
-+ }
-+}
-+
-+static void perf_sample_regs_user(struct perf_regs_user *regs_user,
-+ struct pt_regs *regs)
-+{
-+ if (!user_mode(regs)) {
-+ if (current->mm)
-+ regs = task_pt_regs(current);
-+ else
-+ regs = NULL;
-+ }
-+
-+ if (regs) {
-+ regs_user->regs = regs;
-+ regs_user->abi = perf_reg_abi(current);
-+ }
-+}
-+
-+/*
-+ * Get remaining task size from user stack pointer.
-+ *
-+ * It'd be better to take stack vma map and limit this more
-+ * precisly, but there's no way to get it safely under interrupt,
-+ * so using TASK_SIZE as limit.
-+ */
-+static u64 perf_ustack_task_size(struct pt_regs *regs)
-+{
-+ unsigned long addr = perf_user_stack_pointer(regs);
-+
-+ if (!addr || addr >= TASK_SIZE)
-+ return 0;
-+
-+ return TASK_SIZE - addr;
-+}
-+
-+static u16
-+perf_sample_ustack_size(u16 stack_size, u16 header_size,
-+ struct pt_regs *regs)
-+{
-+ u64 task_size;
-+
-+ /* No regs, no stack pointer, no dump. */
-+ if (!regs)
-+ return 0;
-+
-+ /*
-+ * Check if we fit in with the requested stack size into the:
-+ * - TASK_SIZE
-+ * If we don't, we limit the size to the TASK_SIZE.
-+ *
-+ * - remaining sample size
-+ * If we don't, we customize the stack size to
-+ * fit in to the remaining sample size.
-+ */
-+
-+ task_size = min((u64) USHRT_MAX, perf_ustack_task_size(regs));
-+ stack_size = min(stack_size, (u16) task_size);
-+
-+ /* Current header size plus static size and dynamic size. */
-+ header_size += 2 * sizeof(u64);
-+
-+ /* Do we fit in with the current stack dump size? */
-+ if ((u16) (header_size + stack_size) < header_size) {
-+ /*
-+ * If we overflow the maximum size for the sample,
-+ * we customize the stack dump size to fit in.
-+ */
-+ stack_size = USHRT_MAX - header_size - sizeof(u64);
-+ stack_size = round_up(stack_size, sizeof(u64));
-+ }
-+
-+ return stack_size;
-+}
-+
-+static void
-+perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size,
-+ struct pt_regs *regs)
-+{
-+ /* Case of a kernel thread, nothing to dump */
-+ if (!regs) {
-+ u64 size = 0;
-+ perf_output_put(handle, size);
-+ } else {
-+ unsigned long sp;
-+ unsigned int rem;
-+ u64 dyn_size;
-+
-+ /*
-+ * We dump:
-+ * static size
-+ * - the size requested by user or the best one we can fit
-+ * in to the sample max size
-+ * data
-+ * - user stack dump data
-+ * dynamic size
-+ * - the actual dumped size
-+ */
-+
-+ /* Static size. */
-+ perf_output_put(handle, dump_size);
-+
-+ /* Data. */
-+ sp = perf_user_stack_pointer(regs);
-+ rem = __output_copy_user(handle, (void *) sp, dump_size);
-+ dyn_size = dump_size - rem;
-+
-+ perf_output_skip(handle, rem);
-+
-+ /* Dynamic size. */
-+ perf_output_put(handle, dyn_size);
-+ }
-+}
-+
-+static void __perf_event_header__init_id(struct perf_event_header *header,
-+ struct perf_sample_data *data,
-+ struct perf_event *event)
-+{
-+ u64 sample_type = event->attr.sample_type;
-+
-+ data->type = sample_type;
-+ header->size += event->id_header_size;
-+
-+ if (sample_type & PERF_SAMPLE_TID) {
-+ /* namespace issues */
-+ data->tid_entry.pid = perf_event_pid(event, current);
-+ data->tid_entry.tid = perf_event_tid(event, current);
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_TIME)
-+ data->time = perf_clock();
-+
-+ if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER))
-+ data->id = primary_event_id(event);
-+
-+ if (sample_type & PERF_SAMPLE_STREAM_ID)
-+ data->stream_id = event->id;
-+
-+ if (sample_type & PERF_SAMPLE_CPU) {
-+ data->cpu_entry.cpu = raw_smp_processor_id();
-+ data->cpu_entry.reserved = 0;
-+ }
-+}
-+
-+void perf_event_header__init_id(struct perf_event_header *header,
-+ struct perf_sample_data *data,
-+ struct perf_event *event)
-+{
-+ if (event->attr.sample_id_all)
-+ __perf_event_header__init_id(header, data, event);
-+}
-+
-+static void __perf_event__output_id_sample(struct perf_output_handle *handle,
-+ struct perf_sample_data *data)
-+{
-+ u64 sample_type = data->type;
-+
-+ if (sample_type & PERF_SAMPLE_TID)
-+ perf_output_put(handle, data->tid_entry);
-+
-+ if (sample_type & PERF_SAMPLE_TIME)
-+ perf_output_put(handle, data->time);
-+
-+ if (sample_type & PERF_SAMPLE_ID)
-+ perf_output_put(handle, data->id);
-+
-+ if (sample_type & PERF_SAMPLE_STREAM_ID)
-+ perf_output_put(handle, data->stream_id);
-+
-+ if (sample_type & PERF_SAMPLE_CPU)
-+ perf_output_put(handle, data->cpu_entry);
-+
-+ if (sample_type & PERF_SAMPLE_IDENTIFIER)
-+ perf_output_put(handle, data->id);
-+}
-+
-+void perf_event__output_id_sample(struct perf_event *event,
-+ struct perf_output_handle *handle,
-+ struct perf_sample_data *sample)
-+{
-+ if (event->attr.sample_id_all)
-+ __perf_event__output_id_sample(handle, sample);
-+}
-+
-+static void perf_output_read_one(struct perf_output_handle *handle,
-+ struct perf_event *event,
-+ u64 enabled, u64 running)
-+{
-+ u64 read_format = event->attr.read_format;
-+ u64 values[4];
-+ int n = 0;
-+
-+ values[n++] = perf_event_count(event);
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
-+ values[n++] = enabled +
-+ atomic64_read(&event->child_total_time_enabled);
-+ }
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
-+ values[n++] = running +
-+ atomic64_read(&event->child_total_time_running);
-+ }
-+ if (read_format & PERF_FORMAT_ID)
-+ values[n++] = primary_event_id(event);
-+
-+ __output_copy(handle, values, n * sizeof(u64));
-+}
-+
-+/*
-+ * XXX PERF_FORMAT_GROUP vs inherited events seems difficult.
-+ */
-+static void perf_output_read_group(struct perf_output_handle *handle,
-+ struct perf_event *event,
-+ u64 enabled, u64 running)
-+{
-+ struct perf_event *leader = event->group_leader, *sub;
-+ u64 read_format = event->attr.read_format;
-+ u64 values[5];
-+ int n = 0;
-+
-+ values[n++] = 1 + leader->nr_siblings;
-+
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-+ values[n++] = enabled;
-+
-+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-+ values[n++] = running;
-+
-+ if (leader != event)
-+ leader->pmu->read(leader);
-+
-+ values[n++] = perf_event_count(leader);
-+ if (read_format & PERF_FORMAT_ID)
-+ values[n++] = primary_event_id(leader);
-+
-+ __output_copy(handle, values, n * sizeof(u64));
-+
-+ list_for_each_entry(sub, &leader->sibling_list, group_entry) {
-+ n = 0;
-+
-+ if ((sub != event) &&
-+ (sub->state == PERF_EVENT_STATE_ACTIVE))
-+ sub->pmu->read(sub);
-+
-+ values[n++] = perf_event_count(sub);
-+ if (read_format & PERF_FORMAT_ID)
-+ values[n++] = primary_event_id(sub);
-+
-+ __output_copy(handle, values, n * sizeof(u64));
-+ }
-+}
-+
-+#define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\
-+ PERF_FORMAT_TOTAL_TIME_RUNNING)
-+
-+static void perf_output_read(struct perf_output_handle *handle,
-+ struct perf_event *event)
-+{
-+ u64 enabled = 0, running = 0, now;
-+ u64 read_format = event->attr.read_format;
-+
-+ /*
-+ * compute total_time_enabled, total_time_running
-+ * based on snapshot values taken when the event
-+ * was last scheduled in.
-+ *
-+ * we cannot simply called update_context_time()
-+ * because of locking issue as we are called in
-+ * NMI context
-+ */
-+ if (read_format & PERF_FORMAT_TOTAL_TIMES)
-+ calc_timer_values(event, &now, &enabled, &running);
-+
-+ if (event->attr.read_format & PERF_FORMAT_GROUP)
-+ perf_output_read_group(handle, event, enabled, running);
-+ else
-+ perf_output_read_one(handle, event, enabled, running);
-+}
-+
-+void perf_output_sample(struct perf_output_handle *handle,
-+ struct perf_event_header *header,
-+ struct perf_sample_data *data,
-+ struct perf_event *event)
-+{
-+ u64 sample_type = data->type;
-+
-+ perf_output_put(handle, *header);
-+
-+ if (sample_type & PERF_SAMPLE_IDENTIFIER)
-+ perf_output_put(handle, data->id);
-+
-+ if (sample_type & PERF_SAMPLE_IP)
-+ perf_output_put(handle, data->ip);
-+
-+ if (sample_type & PERF_SAMPLE_TID)
-+ perf_output_put(handle, data->tid_entry);
-+
-+ if (sample_type & PERF_SAMPLE_TIME)
-+ perf_output_put(handle, data->time);
-+
-+ if (sample_type & PERF_SAMPLE_ADDR)
-+ perf_output_put(handle, data->addr);
-+
-+ if (sample_type & PERF_SAMPLE_ID)
-+ perf_output_put(handle, data->id);
-+
-+ if (sample_type & PERF_SAMPLE_STREAM_ID)
-+ perf_output_put(handle, data->stream_id);
-+
-+ if (sample_type & PERF_SAMPLE_CPU)
-+ perf_output_put(handle, data->cpu_entry);
-+
-+ if (sample_type & PERF_SAMPLE_PERIOD)
-+ perf_output_put(handle, data->period);
-+
-+ if (sample_type & PERF_SAMPLE_READ)
-+ perf_output_read(handle, event);
-+
-+ if (sample_type & PERF_SAMPLE_CALLCHAIN) {
-+ if (data->callchain) {
-+ int size = 1;
-+
-+ if (data->callchain)
-+ size += data->callchain->nr;
-+
-+ size *= sizeof(u64);
-+
-+ __output_copy(handle, data->callchain, size);
-+ } else {
-+ u64 nr = 0;
-+ perf_output_put(handle, nr);
-+ }
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_RAW) {
-+ if (data->raw) {
-+ perf_output_put(handle, data->raw->size);
-+ __output_copy(handle, data->raw->data,
-+ data->raw->size);
-+ } else {
-+ struct {
-+ u32 size;
-+ u32 data;
-+ } raw = {
-+ .size = sizeof(u32),
-+ .data = 0,
-+ };
-+ perf_output_put(handle, raw);
-+ }
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
-+ if (data->br_stack) {
-+ size_t size;
-+
-+ size = data->br_stack->nr
-+ * sizeof(struct perf_branch_entry);
-+
-+ perf_output_put(handle, data->br_stack->nr);
-+ perf_output_copy(handle, data->br_stack->entries, size);
-+ } else {
-+ /*
-+ * we always store at least the value of nr
-+ */
-+ u64 nr = 0;
-+ perf_output_put(handle, nr);
-+ }
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_REGS_USER) {
-+ u64 abi = data->regs_user.abi;
-+
-+ /*
-+ * If there are no regs to dump, notice it through
-+ * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE).
-+ */
-+ perf_output_put(handle, abi);
-+
-+ if (abi) {
-+ u64 mask = event->attr.sample_regs_user;
-+ perf_output_sample_regs(handle,
-+ data->regs_user.regs,
-+ mask);
-+ }
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_STACK_USER) {
-+ perf_output_sample_ustack(handle,
-+ data->stack_user_size,
-+ data->regs_user.regs);
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_WEIGHT)
-+ perf_output_put(handle, data->weight);
-+
-+ if (sample_type & PERF_SAMPLE_DATA_SRC)
-+ perf_output_put(handle, data->data_src.val);
-+
-+ if (sample_type & PERF_SAMPLE_TRANSACTION)
-+ perf_output_put(handle, data->txn);
-+
-+ if (!event->attr.watermark) {
-+ int wakeup_events = event->attr.wakeup_events;
-+
-+ if (wakeup_events) {
-+ struct ring_buffer *rb = handle->rb;
-+ int events = local_inc_return(&rb->events);
-+
-+ if (events >= wakeup_events) {
-+ local_sub(wakeup_events, &rb->events);
-+ local_inc(&rb->wakeup);
-+ }
-+ }
-+ }
-+}
-+
-+void perf_prepare_sample(struct perf_event_header *header,
-+ struct perf_sample_data *data,
-+ struct perf_event *event,
-+ struct pt_regs *regs)
-+{
-+ u64 sample_type = event->attr.sample_type;
-+
-+ header->type = PERF_RECORD_SAMPLE;
-+ header->size = sizeof(*header) + event->header_size;
-+
-+ header->misc = 0;
-+ header->misc |= perf_misc_flags(regs);
-+
-+ __perf_event_header__init_id(header, data, event);
-+
-+ if (sample_type & PERF_SAMPLE_IP)
-+ data->ip = perf_instruction_pointer(regs);
-+
-+ if (sample_type & PERF_SAMPLE_CALLCHAIN) {
-+ int size = 1;
-+
-+ data->callchain = perf_callchain(event, regs);
-+
-+ if (data->callchain)
-+ size += data->callchain->nr;
-+
-+ header->size += size * sizeof(u64);
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_RAW) {
-+ int size = sizeof(u32);
-+
-+ if (data->raw)
-+ size += data->raw->size;
-+ else
-+ size += sizeof(u32);
-+
-+ WARN_ON_ONCE(size & (sizeof(u64)-1));
-+ header->size += size;
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
-+ int size = sizeof(u64); /* nr */
-+ if (data->br_stack) {
-+ size += data->br_stack->nr
-+ * sizeof(struct perf_branch_entry);
-+ }
-+ header->size += size;
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_REGS_USER) {
-+ /* regs dump ABI info */
-+ int size = sizeof(u64);
-+
-+ perf_sample_regs_user(&data->regs_user, regs);
-+
-+ if (data->regs_user.regs) {
-+ u64 mask = event->attr.sample_regs_user;
-+ size += hweight64(mask) * sizeof(u64);
-+ }
-+
-+ header->size += size;
-+ }
-+
-+ if (sample_type & PERF_SAMPLE_STACK_USER) {
-+ /*
-+ * Either we need PERF_SAMPLE_STACK_USER bit to be allways
-+ * processed as the last one or have additional check added
-+ * in case new sample type is added, because we could eat
-+ * up the rest of the sample size.
-+ */
-+ struct perf_regs_user *uregs = &data->regs_user;
-+ u16 stack_size = event->attr.sample_stack_user;
-+ u16 size = sizeof(u64);
-+
-+ if (!uregs->abi)
-+ perf_sample_regs_user(uregs, regs);
-+
-+ stack_size = perf_sample_ustack_size(stack_size, header->size,
-+ uregs->regs);
-+
-+ /*
-+ * If there is something to dump, add space for the dump
-+ * itself and for the field that tells the dynamic size,
-+ * which is how many have been actually dumped.
-+ */
-+ if (stack_size)
-+ size += sizeof(u64) + stack_size;
-+
-+ data->stack_user_size = stack_size;
-+ header->size += size;
-+ }
-+}
-+
-+static void perf_event_output(struct perf_event *event,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ struct perf_output_handle handle;
-+ struct perf_event_header header;
-+
-+ /* protect the callchain buffers */
-+ rcu_read_lock();
-+
-+ perf_prepare_sample(&header, data, event, regs);
-+
-+ if (perf_output_begin(&handle, event, header.size))
-+ goto exit;
-+
-+ perf_output_sample(&handle, &header, data, event);
-+
-+ perf_output_end(&handle);
-+
-+exit:
-+ rcu_read_unlock();
-+}
-+
-+/*
-+ * read event_id
-+ */
-+
-+struct perf_read_event {
-+ struct perf_event_header header;
-+
-+ u32 pid;
-+ u32 tid;
-+};
-+
-+static void
-+perf_event_read_event(struct perf_event *event,
-+ struct task_struct *task)
-+{
-+ struct perf_output_handle handle;
-+ struct perf_sample_data sample;
-+ struct perf_read_event read_event = {
-+ .header = {
-+ .type = PERF_RECORD_READ,
-+ .misc = 0,
-+ .size = sizeof(read_event) + event->read_size,
-+ },
-+ .pid = perf_event_pid(event, task),
-+ .tid = perf_event_tid(event, task),
-+ };
-+ int ret;
-+
-+ perf_event_header__init_id(&read_event.header, &sample, event);
-+ ret = perf_output_begin(&handle, event, read_event.header.size);
-+ if (ret)
-+ return;
-+
-+ perf_output_put(&handle, read_event);
-+ perf_output_read(&handle, event);
-+ perf_event__output_id_sample(event, &handle, &sample);
-+
-+ perf_output_end(&handle);
-+}
-+
-+typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data);
-+
-+static void
-+perf_event_aux_ctx(struct perf_event_context *ctx,
-+ perf_event_aux_output_cb output,
-+ void *data)
-+{
-+ struct perf_event *event;
-+
-+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
-+ if (event->state < PERF_EVENT_STATE_INACTIVE)
-+ continue;
-+ if (!event_filter_match(event))
-+ continue;
-+ output(event, data);
-+ }
-+}
-+
-+static void
-+perf_event_aux(perf_event_aux_output_cb output, void *data,
-+ struct perf_event_context *task_ctx)
-+{
-+ struct perf_cpu_context *cpuctx;
-+ struct perf_event_context *ctx;
-+ struct pmu *pmu;
-+ int ctxn;
-+
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(pmu, &pmus, entry) {
-+ cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
-+ if (cpuctx->unique_pmu != pmu)
-+ goto next;
-+ perf_event_aux_ctx(&cpuctx->ctx, output, data);
-+ if (task_ctx)
-+ goto next;
-+ ctxn = pmu->task_ctx_nr;
-+ if (ctxn < 0)
-+ goto next;
-+ ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
-+ if (ctx)
-+ perf_event_aux_ctx(ctx, output, data);
-+next:
-+ put_cpu_ptr(pmu->pmu_cpu_context);
-+ }
-+
-+ if (task_ctx) {
-+ preempt_disable();
-+ perf_event_aux_ctx(task_ctx, output, data);
-+ preempt_enable();
-+ }
-+ rcu_read_unlock();
-+}
-+
-+/*
-+ * task tracking -- fork/exit
-+ *
-+ * enabled by: attr.comm | attr.mmap | attr.mmap2 | attr.mmap_data | attr.task
-+ */
-+
-+struct perf_task_event {
-+ struct task_struct *task;
-+ struct perf_event_context *task_ctx;
-+
-+ struct {
-+ struct perf_event_header header;
-+
-+ u32 pid;
-+ u32 ppid;
-+ u32 tid;
-+ u32 ptid;
-+ u64 time;
-+ } event_id;
-+};
-+
-+static int perf_event_task_match(struct perf_event *event)
-+{
-+ return event->attr.comm || event->attr.mmap ||
-+ event->attr.mmap2 || event->attr.mmap_data ||
-+ event->attr.task;
-+}
-+
-+static void perf_event_task_output(struct perf_event *event,
-+ void *data)
-+{
-+ struct perf_task_event *task_event = data;
-+ struct perf_output_handle handle;
-+ struct perf_sample_data sample;
-+ struct task_struct *task = task_event->task;
-+ int ret, size = task_event->event_id.header.size;
-+
-+ if (!perf_event_task_match(event))
-+ return;
-+
-+ perf_event_header__init_id(&task_event->event_id.header, &sample, event);
-+
-+ ret = perf_output_begin(&handle, event,
-+ task_event->event_id.header.size);
-+ if (ret)
-+ goto out;
-+
-+ task_event->event_id.pid = perf_event_pid(event, task);
-+ task_event->event_id.ppid = perf_event_pid(event, current);
-+
-+ task_event->event_id.tid = perf_event_tid(event, task);
-+ task_event->event_id.ptid = perf_event_tid(event, current);
-+
-+ perf_output_put(&handle, task_event->event_id);
-+
-+ perf_event__output_id_sample(event, &handle, &sample);
-+
-+ perf_output_end(&handle);
-+out:
-+ task_event->event_id.header.size = size;
-+}
-+
-+static void perf_event_task(struct task_struct *task,
-+ struct perf_event_context *task_ctx,
-+ int new)
-+{
-+ struct perf_task_event task_event;
-+
-+ if (!atomic_read(&nr_comm_events) &&
-+ !atomic_read(&nr_mmap_events) &&
-+ !atomic_read(&nr_task_events))
-+ return;
-+
-+ task_event = (struct perf_task_event){
-+ .task = task,
-+ .task_ctx = task_ctx,
-+ .event_id = {
-+ .header = {
-+ .type = new ? PERF_RECORD_FORK : PERF_RECORD_EXIT,
-+ .misc = 0,
-+ .size = sizeof(task_event.event_id),
-+ },
-+ /* .pid */
-+ /* .ppid */
-+ /* .tid */
-+ /* .ptid */
-+ .time = perf_clock(),
-+ },
-+ };
-+
-+ perf_event_aux(perf_event_task_output,
-+ &task_event,
-+ task_ctx);
-+}
-+
-+void perf_event_fork(struct task_struct *task)
-+{
-+ perf_event_task(task, NULL, 1);
-+}
-+
-+/*
-+ * comm tracking
-+ */
-+
-+struct perf_comm_event {
-+ struct task_struct *task;
-+ char *comm;
-+ int comm_size;
-+
-+ struct {
-+ struct perf_event_header header;
-+
-+ u32 pid;
-+ u32 tid;
-+ } event_id;
-+};
-+
-+static int perf_event_comm_match(struct perf_event *event)
-+{
-+ return event->attr.comm;
-+}
-+
-+static void perf_event_comm_output(struct perf_event *event,
-+ void *data)
-+{
-+ struct perf_comm_event *comm_event = data;
-+ struct perf_output_handle handle;
-+ struct perf_sample_data sample;
-+ int size = comm_event->event_id.header.size;
-+ int ret;
-+
-+ if (!perf_event_comm_match(event))
-+ return;
-+
-+ perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
-+ ret = perf_output_begin(&handle, event,
-+ comm_event->event_id.header.size);
-+
-+ if (ret)
-+ goto out;
-+
-+ comm_event->event_id.pid = perf_event_pid(event, comm_event->task);
-+ comm_event->event_id.tid = perf_event_tid(event, comm_event->task);
-+
-+ perf_output_put(&handle, comm_event->event_id);
-+ __output_copy(&handle, comm_event->comm,
-+ comm_event->comm_size);
-+
-+ perf_event__output_id_sample(event, &handle, &sample);
-+
-+ perf_output_end(&handle);
-+out:
-+ comm_event->event_id.header.size = size;
-+}
-+
-+static void perf_event_comm_event(struct perf_comm_event *comm_event)
-+{
-+ char comm[TASK_COMM_LEN];
-+ unsigned int size;
-+
-+ memset(comm, 0, sizeof(comm));
-+ strlcpy(comm, comm_event->task->comm, sizeof(comm));
-+ size = ALIGN(strlen(comm)+1, sizeof(u64));
-+
-+ comm_event->comm = comm;
-+ comm_event->comm_size = size;
-+
-+ comm_event->event_id.header.size = sizeof(comm_event->event_id) + size;
-+
-+ perf_event_aux(perf_event_comm_output,
-+ comm_event,
-+ NULL);
-+}
-+
-+void perf_event_comm(struct task_struct *task, bool exec)
-+{
-+ struct perf_comm_event comm_event;
-+
-+ if (!atomic_read(&nr_comm_events))
-+ return;
-+
-+ comm_event = (struct perf_comm_event){
-+ .task = task,
-+ /* .comm */
-+ /* .comm_size */
-+ .event_id = {
-+ .header = {
-+ .type = PERF_RECORD_COMM,
-+ .misc = exec ? PERF_RECORD_MISC_COMM_EXEC : 0,
-+ /* .size */
-+ },
-+ /* .pid */
-+ /* .tid */
-+ },
-+ };
-+
-+ perf_event_comm_event(&comm_event);
-+}
-+
-+/*
-+ * mmap tracking
-+ */
-+
-+struct perf_mmap_event {
-+ struct vm_area_struct *vma;
-+
-+ const char *file_name;
-+ int file_size;
-+ int maj, min;
-+ u64 ino;
-+ u64 ino_generation;
-+ u32 prot, flags;
-+
-+ struct {
-+ struct perf_event_header header;
-+
-+ u32 pid;
-+ u32 tid;
-+ u64 start;
-+ u64 len;
-+ u64 pgoff;
-+ } event_id;
-+};
-+
-+static int perf_event_mmap_match(struct perf_event *event,
-+ void *data)
-+{
-+ struct perf_mmap_event *mmap_event = data;
-+ struct vm_area_struct *vma = mmap_event->vma;
-+ int executable = vma->vm_flags & VM_EXEC;
-+
-+ return (!executable && event->attr.mmap_data) ||
-+ (executable && (event->attr.mmap || event->attr.mmap2));
-+}
-+
-+static void perf_event_mmap_output(struct perf_event *event,
-+ void *data)
-+{
-+ struct perf_mmap_event *mmap_event = data;
-+ struct perf_output_handle handle;
-+ struct perf_sample_data sample;
-+ int size = mmap_event->event_id.header.size;
-+ int ret;
-+
-+ if (!perf_event_mmap_match(event, data))
-+ return;
-+
-+ if (event->attr.mmap2) {
-+ mmap_event->event_id.header.type = PERF_RECORD_MMAP2;
-+ mmap_event->event_id.header.size += sizeof(mmap_event->maj);
-+ mmap_event->event_id.header.size += sizeof(mmap_event->min);
-+ mmap_event->event_id.header.size += sizeof(mmap_event->ino);
-+ mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
-+ mmap_event->event_id.header.size += sizeof(mmap_event->prot);
-+ mmap_event->event_id.header.size += sizeof(mmap_event->flags);
-+ }
-+
-+ perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
-+ ret = perf_output_begin(&handle, event,
-+ mmap_event->event_id.header.size);
-+ if (ret)
-+ goto out;
-+
-+ mmap_event->event_id.pid = perf_event_pid(event, current);
-+ mmap_event->event_id.tid = perf_event_tid(event, current);
-+
-+ perf_output_put(&handle, mmap_event->event_id);
-+
-+ if (event->attr.mmap2) {
-+ perf_output_put(&handle, mmap_event->maj);
-+ perf_output_put(&handle, mmap_event->min);
-+ perf_output_put(&handle, mmap_event->ino);
-+ perf_output_put(&handle, mmap_event->ino_generation);
-+ perf_output_put(&handle, mmap_event->prot);
-+ perf_output_put(&handle, mmap_event->flags);
-+ }
-+
-+ __output_copy(&handle, mmap_event->file_name,
-+ mmap_event->file_size);
-+
-+ perf_event__output_id_sample(event, &handle, &sample);
-+
-+ perf_output_end(&handle);
-+out:
-+ mmap_event->event_id.header.size = size;
-+}
-+
-+static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
-+{
-+ struct vm_area_struct *vma = mmap_event->vma;
-+ struct file *file = vma->vm_file;
-+ int maj = 0, min = 0;
-+ u64 ino = 0, gen = 0;
-+ u32 prot = 0, flags = 0;
-+ unsigned int size;
-+ char tmp[16];
-+ char *buf = NULL;
-+ char *name;
-+
-+ if (file) {
-+ struct inode *inode;
-+ dev_t dev;
-+
-+ buf = kmalloc(PATH_MAX, GFP_KERNEL);
-+ if (!buf) {
-+ name = "//enomem";
-+ goto cpy_name;
-+ }
-+ /*
-+ * d_path() works from the end of the rb backwards, so we
-+ * need to add enough zero bytes after the string to handle
-+ * the 64bit alignment we do later.
-+ */
-+ name = d_path(&file->f_path, buf, PATH_MAX - sizeof(u64));
-+ if (IS_ERR(name)) {
-+ name = "//toolong";
-+ goto cpy_name;
-+ }
-+ inode = file_inode(vma->vm_file);
-+ dev = inode->i_sb->s_dev;
-+ ino = inode->i_ino;
-+ gen = inode->i_generation;
-+ maj = MAJOR(dev);
-+ min = MINOR(dev);
-+
-+ if (vma->vm_flags & VM_READ)
-+ prot |= PROT_READ;
-+ if (vma->vm_flags & VM_WRITE)
-+ prot |= PROT_WRITE;
-+ if (vma->vm_flags & VM_EXEC)
-+ prot |= PROT_EXEC;
-+
-+ if (vma->vm_flags & VM_MAYSHARE)
-+ flags = MAP_SHARED;
-+ else
-+ flags = MAP_PRIVATE;
-+
-+ if (vma->vm_flags & VM_DENYWRITE)
-+ flags |= MAP_DENYWRITE;
-+ if (vma->vm_flags & VM_MAYEXEC)
-+ flags |= MAP_EXECUTABLE;
-+ if (vma->vm_flags & VM_LOCKED)
-+ flags |= MAP_LOCKED;
-+ if (vma->vm_flags & VM_HUGETLB)
-+ flags |= MAP_HUGETLB;
-+
-+ goto got_name;
-+ } else {
-+ if (vma->vm_ops && vma->vm_ops->name) {
-+ name = (char *) vma->vm_ops->name(vma);
-+ if (name)
-+ goto cpy_name;
-+ }
-+
-+ name = (char *)arch_vma_name(vma);
-+ if (name)
-+ goto cpy_name;
-+
-+ if (vma->vm_start <= vma->vm_mm->start_brk &&
-+ vma->vm_end >= vma->vm_mm->brk) {
-+ name = "[heap]";
-+ goto cpy_name;
-+ }
-+ if (vma->vm_start <= vma->vm_mm->start_stack &&
-+ vma->vm_end >= vma->vm_mm->start_stack) {
-+ name = "[stack]";
-+ goto cpy_name;
-+ }
-+
-+ name = "//anon";
-+ goto cpy_name;
-+ }
-+
-+cpy_name:
-+ strlcpy(tmp, name, sizeof(tmp));
-+ name = tmp;
-+got_name:
-+ /*
-+ * Since our buffer works in 8 byte units we need to align our string
-+ * size to a multiple of 8. However, we must guarantee the tail end is
-+ * zero'd out to avoid leaking random bits to userspace.
-+ */
-+ size = strlen(name)+1;
-+ while (!IS_ALIGNED(size, sizeof(u64)))
-+ name[size++] = '\0';
-+
-+ mmap_event->file_name = name;
-+ mmap_event->file_size = size;
-+ mmap_event->maj = maj;
-+ mmap_event->min = min;
-+ mmap_event->ino = ino;
-+ mmap_event->ino_generation = gen;
-+ mmap_event->prot = prot;
-+ mmap_event->flags = flags;
-+
-+ if (!(vma->vm_flags & VM_EXEC))
-+ mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
-+
-+ mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size;
-+
-+ perf_event_aux(perf_event_mmap_output,
-+ mmap_event,
-+ NULL);
-+
-+ kfree(buf);
-+}
-+
-+void perf_event_mmap(struct vm_area_struct *vma)
-+{
-+ struct perf_mmap_event mmap_event;
-+
-+ if (!atomic_read(&nr_mmap_events))
-+ return;
-+
-+ mmap_event = (struct perf_mmap_event){
-+ .vma = vma,
-+ /* .file_name */
-+ /* .file_size */
-+ .event_id = {
-+ .header = {
-+ .type = PERF_RECORD_MMAP,
-+ .misc = PERF_RECORD_MISC_USER,
-+ /* .size */
-+ },
-+ /* .pid */
-+ /* .tid */
-+ .start = vma->vm_start,
-+ .len = vma->vm_end - vma->vm_start,
-+ .pgoff = (u64)vma->vm_pgoff << PAGE_SHIFT,
-+ },
-+ /* .maj (attr_mmap2 only) */
-+ /* .min (attr_mmap2 only) */
-+ /* .ino (attr_mmap2 only) */
-+ /* .ino_generation (attr_mmap2 only) */
-+ /* .prot (attr_mmap2 only) */
-+ /* .flags (attr_mmap2 only) */
-+ };
-+
-+ perf_event_mmap_event(&mmap_event);
-+}
-+
-+/*
-+ * IRQ throttle logging
-+ */
-+
-+static void perf_log_throttle(struct perf_event *event, int enable)
-+{
-+ struct perf_output_handle handle;
-+ struct perf_sample_data sample;
-+ int ret;
-+
-+ struct {
-+ struct perf_event_header header;
-+ u64 time;
-+ u64 id;
-+ u64 stream_id;
-+ } throttle_event = {
-+ .header = {
-+ .type = PERF_RECORD_THROTTLE,
-+ .misc = 0,
-+ .size = sizeof(throttle_event),
-+ },
-+ .time = perf_clock(),
-+ .id = primary_event_id(event),
-+ .stream_id = event->id,
-+ };
-+
-+ if (enable)
-+ throttle_event.header.type = PERF_RECORD_UNTHROTTLE;
-+
-+ perf_event_header__init_id(&throttle_event.header, &sample, event);
-+
-+ ret = perf_output_begin(&handle, event,
-+ throttle_event.header.size);
-+ if (ret)
-+ return;
-+
-+ perf_output_put(&handle, throttle_event);
-+ perf_event__output_id_sample(event, &handle, &sample);
-+ perf_output_end(&handle);
-+}
-+
-+/*
-+ * Generic event overflow handling, sampling.
-+ */
-+
-+static int __perf_event_overflow(struct perf_event *event,
-+ int throttle, struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ int events = atomic_read(&event->event_limit);
-+ struct hw_perf_event *hwc = &event->hw;
-+ u64 seq;
-+ int ret = 0;
-+
-+ /*
-+ * Non-sampling counters might still use the PMI to fold short
-+ * hardware counters, ignore those.
-+ */
-+ if (unlikely(!is_sampling_event(event)))
-+ return 0;
-+
-+ seq = __this_cpu_read(perf_throttled_seq);
-+ if (seq != hwc->interrupts_seq) {
-+ hwc->interrupts_seq = seq;
-+ hwc->interrupts = 1;
-+ } else {
-+ hwc->interrupts++;
-+ if (unlikely(throttle
-+ && hwc->interrupts >= max_samples_per_tick)) {
-+ __this_cpu_inc(perf_throttled_count);
-+ hwc->interrupts = MAX_INTERRUPTS;
-+ perf_log_throttle(event, 0);
-+ tick_nohz_full_kick();
-+ ret = 1;
-+ }
-+ }
-+
-+ if (event->attr.freq) {
-+ u64 now = perf_clock();
-+ s64 delta = now - hwc->freq_time_stamp;
-+
-+ hwc->freq_time_stamp = now;
-+
-+ if (delta > 0 && delta < 2*TICK_NSEC)
-+ perf_adjust_period(event, delta, hwc->last_period, true);
-+ }
-+
-+ /*
-+ * XXX event_limit might not quite work as expected on inherited
-+ * events
-+ */
-+
-+ event->pending_kill = POLL_IN;
-+ if (events && atomic_dec_and_test(&event->event_limit)) {
-+ ret = 1;
-+ event->pending_kill = POLL_HUP;
-+ event->pending_disable = 1;
-+ irq_work_queue(&event->pending);
-+ }
-+
-+ if (event->overflow_handler)
-+ event->overflow_handler(event, data, regs);
-+ else
-+ perf_event_output(event, data, regs);
-+
-+ if (event->fasync && event->pending_kill) {
-+ event->pending_wakeup = 1;
-+ irq_work_queue(&event->pending);
-+ }
-+
-+ return ret;
-+}
-+
-+int perf_event_overflow(struct perf_event *event,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ return __perf_event_overflow(event, 1, data, regs);
-+}
-+
-+/*
-+ * Generic software event infrastructure
-+ */
-+
-+struct swevent_htable {
-+ struct swevent_hlist *swevent_hlist;
-+ struct mutex hlist_mutex;
-+ int hlist_refcount;
-+
-+ /* Recursion avoidance in each contexts */
-+ int recursion[PERF_NR_CONTEXTS];
-+
-+ /* Keeps track of cpu being initialized/exited */
-+ bool online;
-+};
-+
-+static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
-+
-+/*
-+ * We directly increment event->count and keep a second value in
-+ * event->hw.period_left to count intervals. This period event
-+ * is kept in the range [-sample_period, 0] so that we can use the
-+ * sign as trigger.
-+ */
-+
-+u64 perf_swevent_set_period(struct perf_event *event)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+ u64 period = hwc->last_period;
-+ u64 nr, offset;
-+ s64 old, val;
-+
-+ hwc->last_period = hwc->sample_period;
-+
-+again:
-+ old = val = local64_read(&hwc->period_left);
-+ if (val < 0)
-+ return 0;
-+
-+ nr = div64_u64(period + val, period);
-+ offset = nr * period;
-+ val -= offset;
-+ if (local64_cmpxchg(&hwc->period_left, old, val) != old)
-+ goto again;
-+
-+ return nr;
-+}
-+
-+static void perf_swevent_overflow(struct perf_event *event, u64 overflow,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+ int throttle = 0;
-+
-+ if (!overflow)
-+ overflow = perf_swevent_set_period(event);
-+
-+ if (hwc->interrupts == MAX_INTERRUPTS)
-+ return;
-+
-+ for (; overflow; overflow--) {
-+ if (__perf_event_overflow(event, throttle,
-+ data, regs)) {
-+ /*
-+ * We inhibit the overflow from happening when
-+ * hwc->interrupts == MAX_INTERRUPTS.
-+ */
-+ break;
-+ }
-+ throttle = 1;
-+ }
-+}
-+
-+static void perf_swevent_event(struct perf_event *event, u64 nr,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+
-+ local64_add(nr, &event->count);
-+
-+ if (!regs)
-+ return;
-+
-+ if (!is_sampling_event(event))
-+ return;
-+
-+ if ((event->attr.sample_type & PERF_SAMPLE_PERIOD) && !event->attr.freq) {
-+ data->period = nr;
-+ return perf_swevent_overflow(event, 1, data, regs);
-+ } else
-+ data->period = event->hw.last_period;
-+
-+ if (nr == 1 && hwc->sample_period == 1 && !event->attr.freq)
-+ return perf_swevent_overflow(event, 1, data, regs);
-+
-+ if (local64_add_negative(nr, &hwc->period_left))
-+ return;
-+
-+ perf_swevent_overflow(event, 0, data, regs);
-+}
-+
-+static int perf_exclude_event(struct perf_event *event,
-+ struct pt_regs *regs)
-+{
-+ if (event->hw.state & PERF_HES_STOPPED)
-+ return 1;
-+
-+ if (regs) {
-+ if (event->attr.exclude_user && user_mode(regs))
-+ return 1;
-+
-+ if (event->attr.exclude_kernel && !user_mode(regs))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int perf_swevent_match(struct perf_event *event,
-+ enum perf_type_id type,
-+ u32 event_id,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ if (event->attr.type != type)
-+ return 0;
-+
-+ if (event->attr.config != event_id)
-+ return 0;
-+
-+ if (perf_exclude_event(event, regs))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+static inline u64 swevent_hash(u64 type, u32 event_id)
-+{
-+ u64 val = event_id | (type << 32);
-+
-+ return hash_64(val, SWEVENT_HLIST_BITS);
-+}
-+
-+static inline struct hlist_head *
-+__find_swevent_head(struct swevent_hlist *hlist, u64 type, u32 event_id)
-+{
-+ u64 hash = swevent_hash(type, event_id);
-+
-+ return &hlist->heads[hash];
-+}
-+
-+/* For the read side: events when they trigger */
-+static inline struct hlist_head *
-+find_swevent_head_rcu(struct swevent_htable *swhash, u64 type, u32 event_id)
-+{
-+ struct swevent_hlist *hlist;
-+
-+ hlist = rcu_dereference(swhash->swevent_hlist);
-+ if (!hlist)
-+ return NULL;
-+
-+ return __find_swevent_head(hlist, type, event_id);
-+}
-+
-+/* For the event head insertion and removal in the hlist */
-+static inline struct hlist_head *
-+find_swevent_head(struct swevent_htable *swhash, struct perf_event *event)
-+{
-+ struct swevent_hlist *hlist;
-+ u32 event_id = event->attr.config;
-+ u64 type = event->attr.type;
-+
-+ /*
-+ * Event scheduling is always serialized against hlist allocation
-+ * and release. Which makes the protected version suitable here.
-+ * The context lock guarantees that.
-+ */
-+ hlist = rcu_dereference_protected(swhash->swevent_hlist,
-+ lockdep_is_held(&event->ctx->lock));
-+ if (!hlist)
-+ return NULL;
-+
-+ return __find_swevent_head(hlist, type, event_id);
-+}
-+
-+static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
-+ u64 nr,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable);
-+ struct perf_event *event;
-+ struct hlist_head *head;
-+
-+ rcu_read_lock();
-+ head = find_swevent_head_rcu(swhash, type, event_id);
-+ if (!head)
-+ goto end;
-+
-+ hlist_for_each_entry_rcu(event, head, hlist_entry) {
-+ if (perf_swevent_match(event, type, event_id, data, regs))
-+ perf_swevent_event(event, nr, data, regs);
-+ }
-+end:
-+ rcu_read_unlock();
-+}
-+
-+int perf_swevent_get_recursion_context(void)
-+{
-+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable);
-+
-+ return get_recursion_context(swhash->recursion);
-+}
-+EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context);
-+
-+inline void perf_swevent_put_recursion_context(int rctx)
-+{
-+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable);
-+
-+ put_recursion_context(swhash->recursion, rctx);
-+}
-+
-+void __perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
-+{
-+ struct perf_sample_data data;
-+ int rctx;
-+
-+ preempt_disable_notrace();
-+ rctx = perf_swevent_get_recursion_context();
-+ if (rctx < 0)
-+ return;
-+
-+ perf_sample_data_init(&data, addr, 0);
-+
-+ do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, &data, regs);
-+
-+ perf_swevent_put_recursion_context(rctx);
-+ preempt_enable_notrace();
-+}
-+
-+static void perf_swevent_read(struct perf_event *event)
-+{
-+}
-+
-+static int perf_swevent_add(struct perf_event *event, int flags)
-+{
-+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable);
-+ struct hw_perf_event *hwc = &event->hw;
-+ struct hlist_head *head;
-+
-+ if (is_sampling_event(event)) {
-+ hwc->last_period = hwc->sample_period;
-+ perf_swevent_set_period(event);
-+ }
-+
-+ hwc->state = !(flags & PERF_EF_START);
-+
-+ head = find_swevent_head(swhash, event);
-+ if (!head) {
-+ /*
-+ * We can race with cpu hotplug code. Do not
-+ * WARN if the cpu just got unplugged.
-+ */
-+ WARN_ON_ONCE(swhash->online);
-+ return -EINVAL;
-+ }
-+
-+ hlist_add_head_rcu(&event->hlist_entry, head);
-+
-+ return 0;
-+}
-+
-+static void perf_swevent_del(struct perf_event *event, int flags)
-+{
-+ hlist_del_rcu(&event->hlist_entry);
-+}
-+
-+static void perf_swevent_start(struct perf_event *event, int flags)
-+{
-+ event->hw.state = 0;
-+}
-+
-+static void perf_swevent_stop(struct perf_event *event, int flags)
-+{
-+ event->hw.state = PERF_HES_STOPPED;
-+}
-+
-+/* Deref the hlist from the update side */
-+static inline struct swevent_hlist *
-+swevent_hlist_deref(struct swevent_htable *swhash)
-+{
-+ return rcu_dereference_protected(swhash->swevent_hlist,
-+ lockdep_is_held(&swhash->hlist_mutex));
-+}
-+
-+static void swevent_hlist_release(struct swevent_htable *swhash)
-+{
-+ struct swevent_hlist *hlist = swevent_hlist_deref(swhash);
-+
-+ if (!hlist)
-+ return;
-+
-+ RCU_INIT_POINTER(swhash->swevent_hlist, NULL);
-+ kfree_rcu(hlist, rcu_head);
-+}
-+
-+static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
-+{
-+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-+
-+ mutex_lock(&swhash->hlist_mutex);
-+
-+ if (!--swhash->hlist_refcount)
-+ swevent_hlist_release(swhash);
-+
-+ mutex_unlock(&swhash->hlist_mutex);
-+}
-+
-+static void swevent_hlist_put(struct perf_event *event)
-+{
-+ int cpu;
-+
-+ for_each_possible_cpu(cpu)
-+ swevent_hlist_put_cpu(event, cpu);
-+}
-+
-+static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
-+{
-+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-+ int err = 0;
-+
-+ mutex_lock(&swhash->hlist_mutex);
-+
-+ if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
-+ struct swevent_hlist *hlist;
-+
-+ hlist = kzalloc(sizeof(*hlist), GFP_KERNEL);
-+ if (!hlist) {
-+ err = -ENOMEM;
-+ goto exit;
-+ }
-+ rcu_assign_pointer(swhash->swevent_hlist, hlist);
-+ }
-+ swhash->hlist_refcount++;
-+exit:
-+ mutex_unlock(&swhash->hlist_mutex);
-+
-+ return err;
-+}
-+
-+static int swevent_hlist_get(struct perf_event *event)
-+{
-+ int err;
-+ int cpu, failed_cpu;
-+
-+ get_online_cpus();
-+ for_each_possible_cpu(cpu) {
-+ err = swevent_hlist_get_cpu(event, cpu);
-+ if (err) {
-+ failed_cpu = cpu;
-+ goto fail;
-+ }
-+ }
-+ put_online_cpus();
-+
-+ return 0;
-+fail:
-+ for_each_possible_cpu(cpu) {
-+ if (cpu == failed_cpu)
-+ break;
-+ swevent_hlist_put_cpu(event, cpu);
-+ }
-+
-+ put_online_cpus();
-+ return err;
-+}
-+
-+struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX];
-+
-+static void sw_perf_event_destroy(struct perf_event *event)
-+{
-+ u64 event_id = event->attr.config;
-+
-+ WARN_ON(event->parent);
-+
-+ static_key_slow_dec(&perf_swevent_enabled[event_id]);
-+ swevent_hlist_put(event);
-+}
-+
-+static int perf_swevent_init(struct perf_event *event)
-+{
-+ u64 event_id = event->attr.config;
-+
-+ if (event->attr.type != PERF_TYPE_SOFTWARE)
-+ return -ENOENT;
-+
-+ /*
-+ * no branch sampling for software events
-+ */
-+ if (has_branch_stack(event))
-+ return -EOPNOTSUPP;
-+
-+ switch (event_id) {
-+ case PERF_COUNT_SW_CPU_CLOCK:
-+ case PERF_COUNT_SW_TASK_CLOCK:
-+ return -ENOENT;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (event_id >= PERF_COUNT_SW_MAX)
-+ return -ENOENT;
-+
-+ if (!event->parent) {
-+ int err;
-+
-+ err = swevent_hlist_get(event);
-+ if (err)
-+ return err;
-+
-+ static_key_slow_inc(&perf_swevent_enabled[event_id]);
-+ event->destroy = sw_perf_event_destroy;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct pmu perf_swevent = {
-+ .task_ctx_nr = perf_sw_context,
-+
-+ .event_init = perf_swevent_init,
-+ .add = perf_swevent_add,
-+ .del = perf_swevent_del,
-+ .start = perf_swevent_start,
-+ .stop = perf_swevent_stop,
-+ .read = perf_swevent_read,
-+};
-+
-+#ifdef CONFIG_EVENT_TRACING
-+
-+static int perf_tp_filter_match(struct perf_event *event,
-+ struct perf_sample_data *data)
-+{
-+ void *record = data->raw->data;
-+
-+ if (likely(!event->filter) || filter_match_preds(event->filter, record))
-+ return 1;
-+ return 0;
-+}
-+
-+static int perf_tp_event_match(struct perf_event *event,
-+ struct perf_sample_data *data,
-+ struct pt_regs *regs)
-+{
-+ if (event->hw.state & PERF_HES_STOPPED)
-+ return 0;
-+ /*
-+ * All tracepoints are from kernel-space.
-+ */
-+ if (event->attr.exclude_kernel)
-+ return 0;
-+
-+ if (!perf_tp_filter_match(event, data))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+void perf_tp_event(u64 addr, u64 count, void *record, int entry_size,
-+ struct pt_regs *regs, struct hlist_head *head, int rctx,
-+ struct task_struct *task)
-+{
-+ struct perf_sample_data data;
-+ struct perf_event *event;
-+
-+ struct perf_raw_record raw = {
-+ .size = entry_size,
-+ .data = record,
-+ };
-+
-+ perf_sample_data_init(&data, addr, 0);
-+ data.raw = &raw;
-+
-+ hlist_for_each_entry_rcu(event, head, hlist_entry) {
-+ if (perf_tp_event_match(event, &data, regs))
-+ perf_swevent_event(event, count, &data, regs);
-+ }
-+
-+ /*
-+ * If we got specified a target task, also iterate its context and
-+ * deliver this event there too.
-+ */
-+ if (task && task != current) {
-+ struct perf_event_context *ctx;
-+ struct trace_entry *entry = record;
-+
-+ rcu_read_lock();
-+ ctx = rcu_dereference(task->perf_event_ctxp[perf_sw_context]);
-+ if (!ctx)
-+ goto unlock;
-+
-+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
-+ if (event->attr.type != PERF_TYPE_TRACEPOINT)
-+ continue;
-+ if (event->attr.config != entry->type)
-+ continue;
-+ if (perf_tp_event_match(event, &data, regs))
-+ perf_swevent_event(event, count, &data, regs);
-+ }
-+unlock:
-+ rcu_read_unlock();
-+ }
-+
-+ perf_swevent_put_recursion_context(rctx);
-+}
-+EXPORT_SYMBOL_GPL(perf_tp_event);
-+
-+static void tp_perf_event_destroy(struct perf_event *event)
-+{
-+ perf_trace_destroy(event);
-+}
-+
-+static int perf_tp_event_init(struct perf_event *event)
-+{
-+ int err;
-+
-+ if (event->attr.type != PERF_TYPE_TRACEPOINT)
-+ return -ENOENT;
-+
-+ /*
-+ * no branch sampling for tracepoint events
-+ */
-+ if (has_branch_stack(event))
-+ return -EOPNOTSUPP;
-+
-+ err = perf_trace_init(event);
-+ if (err)
-+ return err;
-+
-+ event->destroy = tp_perf_event_destroy;
-+
-+ return 0;
-+}
-+
-+static struct pmu perf_tracepoint = {
-+ .task_ctx_nr = perf_sw_context,
-+
-+ .event_init = perf_tp_event_init,
-+ .add = perf_trace_add,
-+ .del = perf_trace_del,
-+ .start = perf_swevent_start,
-+ .stop = perf_swevent_stop,
-+ .read = perf_swevent_read,
-+};
-+
-+static inline void perf_tp_register(void)
-+{
-+ perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
-+}
-+
-+static int perf_event_set_filter(struct perf_event *event, void __user *arg)
-+{
-+ char *filter_str;
-+ int ret;
-+
-+ if (event->attr.type != PERF_TYPE_TRACEPOINT)
-+ return -EINVAL;
-+
-+ filter_str = strndup_user(arg, PAGE_SIZE);
-+ if (IS_ERR(filter_str))
-+ return PTR_ERR(filter_str);
-+
-+ ret = ftrace_profile_set_filter(event, event->attr.config, filter_str);
-+
-+ kfree(filter_str);
-+ return ret;
-+}
-+
-+static void perf_event_free_filter(struct perf_event *event)
-+{
-+ ftrace_profile_free_filter(event);
-+}
-+
-+#else
-+
-+static inline void perf_tp_register(void)
-+{
-+}
-+
-+static int perf_event_set_filter(struct perf_event *event, void __user *arg)
-+{
-+ return -ENOENT;
-+}
-+
-+static void perf_event_free_filter(struct perf_event *event)
-+{
-+}
-+
-+#endif /* CONFIG_EVENT_TRACING */
-+
-+#ifdef CONFIG_HAVE_HW_BREAKPOINT
-+void perf_bp_event(struct perf_event *bp, void *data)
-+{
-+ struct perf_sample_data sample;
-+ struct pt_regs *regs = data;
-+
-+ perf_sample_data_init(&sample, bp->attr.bp_addr, 0);
-+
-+ if (!bp->hw.state && !perf_exclude_event(bp, regs))
-+ perf_swevent_event(bp, 1, &sample, regs);
-+}
-+#endif
-+
-+/*
-+ * hrtimer based swevent callback
-+ */
-+
-+static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
-+{
-+ enum hrtimer_restart ret = HRTIMER_RESTART;
-+ struct perf_sample_data data;
-+ struct pt_regs *regs;
-+ struct perf_event *event;
-+ u64 period;
-+
-+ event = container_of(hrtimer, struct perf_event, hw.hrtimer);
-+
-+ if (event->state != PERF_EVENT_STATE_ACTIVE)
-+ return HRTIMER_NORESTART;
-+
-+ event->pmu->read(event);
-+
-+ perf_sample_data_init(&data, 0, event->hw.last_period);
-+ regs = get_irq_regs();
-+
-+ if (regs && !perf_exclude_event(event, regs)) {
-+ if (!(event->attr.exclude_idle && is_idle_task(current)))
-+ if (__perf_event_overflow(event, 1, &data, regs))
-+ ret = HRTIMER_NORESTART;
-+ }
-+
-+ period = max_t(u64, 10000, event->hw.sample_period);
-+ hrtimer_forward_now(hrtimer, ns_to_ktime(period));
-+
-+ return ret;
-+}
-+
-+static void perf_swevent_start_hrtimer(struct perf_event *event)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+ s64 period;
-+
-+ if (!is_sampling_event(event))
-+ return;
-+
-+ period = local64_read(&hwc->period_left);
-+ if (period) {
-+ if (period < 0)
-+ period = 10000;
-+
-+ local64_set(&hwc->period_left, 0);
-+ } else {
-+ period = max_t(u64, 10000, hwc->sample_period);
-+ }
-+ __hrtimer_start_range_ns(&hwc->hrtimer,
-+ ns_to_ktime(period), 0,
-+ HRTIMER_MODE_REL_PINNED, 0);
-+}
-+
-+static void perf_swevent_cancel_hrtimer(struct perf_event *event)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+
-+ if (is_sampling_event(event)) {
-+ ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
-+ local64_set(&hwc->period_left, ktime_to_ns(remaining));
-+
-+ hrtimer_cancel(&hwc->hrtimer);
-+ }
-+}
-+
-+static void perf_swevent_init_hrtimer(struct perf_event *event)
-+{
-+ struct hw_perf_event *hwc = &event->hw;
-+
-+ if (!is_sampling_event(event))
-+ return;
-+
-+ hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-+ hwc->hrtimer.function = perf_swevent_hrtimer;
-+
-+ /*
-+ * Since hrtimers have a fixed rate, we can do a static freq->period
-+ * mapping and avoid the whole period adjust feedback stuff.
-+ */
-+ if (event->attr.freq) {
-+ long freq = event->attr.sample_freq;
-+
-+ event->attr.sample_period = NSEC_PER_SEC / freq;
-+ hwc->sample_period = event->attr.sample_period;
-+ local64_set(&hwc->period_left, hwc->sample_period);
-+ hwc->last_period = hwc->sample_period;
-+ event->attr.freq = 0;
-+ }
-+}
-+
-+/*
-+ * Software event: cpu wall time clock
-+ */
-+
-+static void cpu_clock_event_update(struct perf_event *event)
-+{
-+ s64 prev;
-+ u64 now;
-+
-+ now = local_clock();
-+ prev = local64_xchg(&event->hw.prev_count, now);
-+ local64_add(now - prev, &event->count);
-+}
-+
-+static void cpu_clock_event_start(struct perf_event *event, int flags)
-+{
-+ local64_set(&event->hw.prev_count, local_clock());
-+ perf_swevent_start_hrtimer(event);
-+}
-+
-+static void cpu_clock_event_stop(struct perf_event *event, int flags)
-+{
-+ perf_swevent_cancel_hrtimer(event);
-+ cpu_clock_event_update(event);
-+}
-+
-+static int cpu_clock_event_add(struct perf_event *event, int flags)
-+{
-+ if (flags & PERF_EF_START)
-+ cpu_clock_event_start(event, flags);
-+
-+ return 0;
-+}
-+
-+static void cpu_clock_event_del(struct perf_event *event, int flags)
-+{
-+ cpu_clock_event_stop(event, flags);
-+}
-+
-+static void cpu_clock_event_read(struct perf_event *event)
-+{
-+ cpu_clock_event_update(event);
-+}
-+
-+static int cpu_clock_event_init(struct perf_event *event)
-+{
-+ if (event->attr.type != PERF_TYPE_SOFTWARE)
-+ return -ENOENT;
-+
-+ if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK)
-+ return -ENOENT;
-+
-+ /*
-+ * no branch sampling for software events
-+ */
-+ if (has_branch_stack(event))
-+ return -EOPNOTSUPP;
-+
-+ perf_swevent_init_hrtimer(event);
-+
-+ return 0;
-+}
-+
-+static struct pmu perf_cpu_clock = {
-+ .task_ctx_nr = perf_sw_context,
-+
-+ .event_init = cpu_clock_event_init,
-+ .add = cpu_clock_event_add,
-+ .del = cpu_clock_event_del,
-+ .start = cpu_clock_event_start,
-+ .stop = cpu_clock_event_stop,
-+ .read = cpu_clock_event_read,
-+};
-+
-+/*
-+ * Software event: task time clock
-+ */
-+
-+static void task_clock_event_update(struct perf_event *event, u64 now)
-+{
-+ u64 prev;
-+ s64 delta;
-+
-+ prev = local64_xchg(&event->hw.prev_count, now);
-+ delta = now - prev;
-+ local64_add(delta, &event->count);
-+}
-+
-+static void task_clock_event_start(struct perf_event *event, int flags)
-+{
-+ local64_set(&event->hw.prev_count, event->ctx->time);
-+ perf_swevent_start_hrtimer(event);
-+}
-+
-+static void task_clock_event_stop(struct perf_event *event, int flags)
-+{
-+ perf_swevent_cancel_hrtimer(event);
-+ task_clock_event_update(event, event->ctx->time);
-+}
-+
-+static int task_clock_event_add(struct perf_event *event, int flags)
-+{
-+ if (flags & PERF_EF_START)
-+ task_clock_event_start(event, flags);
-+
-+ return 0;
-+}
-+
-+static void task_clock_event_del(struct perf_event *event, int flags)
-+{
-+ task_clock_event_stop(event, PERF_EF_UPDATE);
-+}
-+
-+static void task_clock_event_read(struct perf_event *event)
-+{
-+ u64 now = perf_clock();
-+ u64 delta = now - event->ctx->timestamp;
-+ u64 time = event->ctx->time + delta;
-+
-+ task_clock_event_update(event, time);
-+}
-+
-+static int task_clock_event_init(struct perf_event *event)
-+{
-+ if (event->attr.type != PERF_TYPE_SOFTWARE)
-+ return -ENOENT;
-+
-+ if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK)
-+ return -ENOENT;
-+
-+ /*
-+ * no branch sampling for software events
-+ */
-+ if (has_branch_stack(event))
-+ return -EOPNOTSUPP;
-+
-+ perf_swevent_init_hrtimer(event);
-+
-+ return 0;
-+}
-+
-+static struct pmu perf_task_clock = {
-+ .task_ctx_nr = perf_sw_context,
-+
-+ .event_init = task_clock_event_init,
-+ .add = task_clock_event_add,
-+ .del = task_clock_event_del,
-+ .start = task_clock_event_start,
-+ .stop = task_clock_event_stop,
-+ .read = task_clock_event_read,
-+};
-+
-+static void perf_pmu_nop_void(struct pmu *pmu)
-+{
-+}
-+
-+static int perf_pmu_nop_int(struct pmu *pmu)
-+{
-+ return 0;
-+}
-+
-+static void perf_pmu_start_txn(struct pmu *pmu)
-+{
-+ perf_pmu_disable(pmu);
-+}
-+
-+static int perf_pmu_commit_txn(struct pmu *pmu)
-+{
-+ perf_pmu_enable(pmu);
-+ return 0;
-+}
-+
-+static void perf_pmu_cancel_txn(struct pmu *pmu)
-+{
-+ perf_pmu_enable(pmu);
-+}
-+
-+static int perf_event_idx_default(struct perf_event *event)
-+{
-+ return 0;
-+}
-+
-+/*
-+ * Ensures all contexts with the same task_ctx_nr have the same
-+ * pmu_cpu_context too.
-+ */
-+static struct perf_cpu_context __percpu *find_pmu_context(int ctxn)
-+{
-+ struct pmu *pmu;
-+
-+ if (ctxn < 0)
-+ return NULL;
-+
-+ list_for_each_entry(pmu, &pmus, entry) {
-+ if (pmu->task_ctx_nr == ctxn)
-+ return pmu->pmu_cpu_context;
-+ }
-+
-+ return NULL;
-+}
-+
-+static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
-+{
-+ int cpu;
-+
-+ for_each_possible_cpu(cpu) {
-+ struct perf_cpu_context *cpuctx;
-+
-+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
-+
-+ if (cpuctx->unique_pmu == old_pmu)
-+ cpuctx->unique_pmu = pmu;
-+ }
-+}
-+
-+static void free_pmu_context(struct pmu *pmu)
-+{
-+ struct pmu *i;
-+
-+ mutex_lock(&pmus_lock);
-+ /*
-+ * Like a real lame refcount.
-+ */
-+ list_for_each_entry(i, &pmus, entry) {
-+ if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
-+ update_pmu_context(i, pmu);
-+ goto out;
-+ }
-+ }
-+
-+ free_percpu(pmu->pmu_cpu_context);
-+out:
-+ mutex_unlock(&pmus_lock);
-+}
-+static struct idr pmu_idr;
-+
-+static ssize_t
-+type_show(struct device *dev, struct device_attribute *attr, char *page)
-+{
-+ struct pmu *pmu = dev_get_drvdata(dev);
-+
-+ return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
-+}
-+static DEVICE_ATTR_RO(type);
-+
-+static ssize_t
-+perf_event_mux_interval_ms_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *page)
-+{
-+ struct pmu *pmu = dev_get_drvdata(dev);
-+
-+ return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->hrtimer_interval_ms);
-+}
-+
-+static ssize_t
-+perf_event_mux_interval_ms_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct pmu *pmu = dev_get_drvdata(dev);
-+ int timer, cpu, ret;
-+
-+ ret = kstrtoint(buf, 0, &timer);
-+ if (ret)
-+ return ret;
-+
-+ if (timer < 1)
-+ return -EINVAL;
-+
-+ /* same value, noting to do */
-+ if (timer == pmu->hrtimer_interval_ms)
-+ return count;
-+
-+ pmu->hrtimer_interval_ms = timer;
-+
-+ /* update all cpuctx for this PMU */
-+ for_each_possible_cpu(cpu) {
-+ struct perf_cpu_context *cpuctx;
-+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
-+ cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer);
-+
-+ if (hrtimer_active(&cpuctx->hrtimer))
-+ hrtimer_forward_now(&cpuctx->hrtimer, cpuctx->hrtimer_interval);
-+ }
-+
-+ return count;
-+}
-+static DEVICE_ATTR_RW(perf_event_mux_interval_ms);
-+
-+static struct attribute *pmu_dev_attrs[] = {
-+ &dev_attr_type.attr,
-+ &dev_attr_perf_event_mux_interval_ms.attr,
-+ NULL,
-+};
-+ATTRIBUTE_GROUPS(pmu_dev);
-+
-+static int pmu_bus_running;
-+static struct bus_type pmu_bus = {
-+ .name = "event_source",
-+ .dev_groups = pmu_dev_groups,
-+};
-+
-+static void pmu_dev_release(struct device *dev)
-+{
-+ kfree(dev);
-+}
-+
-+static int pmu_dev_alloc(struct pmu *pmu)
-+{
-+ int ret = -ENOMEM;
-+
-+ pmu->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-+ if (!pmu->dev)
-+ goto out;
-+
-+ pmu->dev->groups = pmu->attr_groups;
-+ device_initialize(pmu->dev);
-+ ret = dev_set_name(pmu->dev, "%s", pmu->name);
-+ if (ret)
-+ goto free_dev;
-+
-+ dev_set_drvdata(pmu->dev, pmu);
-+ pmu->dev->bus = &pmu_bus;
-+ pmu->dev->release = pmu_dev_release;
-+ ret = device_add(pmu->dev);
-+ if (ret)
-+ goto free_dev;
-+
-+out:
-+ return ret;
-+
-+free_dev:
-+ put_device(pmu->dev);
-+ goto out;
-+}
-+
-+static struct lock_class_key cpuctx_mutex;
-+static struct lock_class_key cpuctx_lock;
-+
-+int perf_pmu_register(struct pmu *pmu, const char *name, int type)
-+{
-+ int cpu, ret;
-+
-+ mutex_lock(&pmus_lock);
-+ ret = -ENOMEM;
-+ pmu->pmu_disable_count = alloc_percpu(int);
-+ if (!pmu->pmu_disable_count)
-+ goto unlock;
-+
-+ pmu->type = -1;
-+ if (!name)
-+ goto skip_type;
-+ pmu->name = name;
-+
-+ if (type < 0) {
-+ type = idr_alloc(&pmu_idr, pmu, PERF_TYPE_MAX, 0, GFP_KERNEL);
-+ if (type < 0) {
-+ ret = type;
-+ goto free_pdc;
-+ }
-+ }
-+ pmu->type = type;
-+
-+ if (pmu_bus_running) {
-+ ret = pmu_dev_alloc(pmu);
-+ if (ret)
-+ goto free_idr;
-+ }
-+
-+skip_type:
-+ pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
-+ if (pmu->pmu_cpu_context)
-+ goto got_cpu_context;
-+
-+ ret = -ENOMEM;
-+ pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
-+ if (!pmu->pmu_cpu_context)
-+ goto free_dev;
-+
-+ for_each_possible_cpu(cpu) {
-+ struct perf_cpu_context *cpuctx;
-+
-+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
-+ __perf_event_init_context(&cpuctx->ctx);
-+ lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex);
-+ lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock);
-+ cpuctx->ctx.type = cpu_context;
-+ cpuctx->ctx.pmu = pmu;
-+
-+ __perf_cpu_hrtimer_init(cpuctx, cpu);
-+
-+ INIT_LIST_HEAD(&cpuctx->rotation_list);
-+ cpuctx->unique_pmu = pmu;
-+ }
-+
-+got_cpu_context:
-+ if (!pmu->start_txn) {
-+ if (pmu->pmu_enable) {
-+ /*
-+ * If we have pmu_enable/pmu_disable calls, install
-+ * transaction stubs that use that to try and batch
-+ * hardware accesses.
-+ */
-+ pmu->start_txn = perf_pmu_start_txn;
-+ pmu->commit_txn = perf_pmu_commit_txn;
-+ pmu->cancel_txn = perf_pmu_cancel_txn;
-+ } else {
-+ pmu->start_txn = perf_pmu_nop_void;
-+ pmu->commit_txn = perf_pmu_nop_int;
-+ pmu->cancel_txn = perf_pmu_nop_void;
-+ }
-+ }
-+
-+ if (!pmu->pmu_enable) {
-+ pmu->pmu_enable = perf_pmu_nop_void;
-+ pmu->pmu_disable = perf_pmu_nop_void;
-+ }
-+
-+ if (!pmu->event_idx)
-+ pmu->event_idx = perf_event_idx_default;
-+
-+ list_add_rcu(&pmu->entry, &pmus);
-+ ret = 0;
-+unlock:
-+ mutex_unlock(&pmus_lock);
-+
-+ return ret;
-+
-+free_dev:
-+ device_del(pmu->dev);
-+ put_device(pmu->dev);
-+
-+free_idr:
-+ if (pmu->type >= PERF_TYPE_MAX)
-+ idr_remove(&pmu_idr, pmu->type);
-+
-+free_pdc:
-+ free_percpu(pmu->pmu_disable_count);
-+ goto unlock;
-+}
-+EXPORT_SYMBOL_GPL(perf_pmu_register);
-+
-+void perf_pmu_unregister(struct pmu *pmu)
-+{
-+ mutex_lock(&pmus_lock);
-+ list_del_rcu(&pmu->entry);
-+ mutex_unlock(&pmus_lock);
-+
-+ /*
-+ * We dereference the pmu list under both SRCU and regular RCU, so
-+ * synchronize against both of those.
-+ */
-+ synchronize_srcu(&pmus_srcu);
-+ synchronize_rcu();
-+
-+ free_percpu(pmu->pmu_disable_count);
-+ if (pmu->type >= PERF_TYPE_MAX)
-+ idr_remove(&pmu_idr, pmu->type);
-+ device_del(pmu->dev);
-+ put_device(pmu->dev);
-+ free_pmu_context(pmu);
-+}
-+EXPORT_SYMBOL_GPL(perf_pmu_unregister);
-+
-+struct pmu *perf_init_event(struct perf_event *event)
-+{
-+ struct pmu *pmu = NULL;
-+ int idx;
-+ int ret;
-+
-+ idx = srcu_read_lock(&pmus_srcu);
-+
-+ rcu_read_lock();
-+ pmu = idr_find(&pmu_idr, event->attr.type);
-+ rcu_read_unlock();
-+ if (pmu) {
-+ if (!try_module_get(pmu->module)) {
-+ pmu = ERR_PTR(-ENODEV);
-+ goto unlock;
-+ }
-+ event->pmu = pmu;
-+ ret = pmu->event_init(event);
-+ if (ret)
-+ pmu = ERR_PTR(ret);
-+ goto unlock;
-+ }
-+
-+ list_for_each_entry_rcu(pmu, &pmus, entry) {
-+ if (!try_module_get(pmu->module)) {
-+ pmu = ERR_PTR(-ENODEV);
-+ goto unlock;
-+ }
-+ event->pmu = pmu;
-+ ret = pmu->event_init(event);
-+ if (!ret)
-+ goto unlock;
-+
-+ if (ret != -ENOENT) {
-+ pmu = ERR_PTR(ret);
-+ goto unlock;
-+ }
-+ }
-+ pmu = ERR_PTR(-ENOENT);
-+unlock:
-+ srcu_read_unlock(&pmus_srcu, idx);
-+
-+ return pmu;
-+}
-+
-+static void account_event_cpu(struct perf_event *event, int cpu)
-+{
-+ if (event->parent)
-+ return;
-+
-+ if (has_branch_stack(event)) {
-+ if (!(event->attach_state & PERF_ATTACH_TASK))
-+ atomic_inc(&per_cpu(perf_branch_stack_events, cpu));
-+ }
-+ if (is_cgroup_event(event))
-+ atomic_inc(&per_cpu(perf_cgroup_events, cpu));
-+}
-+
-+static void account_event(struct perf_event *event)
-+{
-+ if (event->parent)
-+ return;
-+
-+ if (event->attach_state & PERF_ATTACH_TASK)
-+ static_key_slow_inc(&perf_sched_events.key);
-+ if (event->attr.mmap || event->attr.mmap_data)
-+ atomic_inc(&nr_mmap_events);
-+ if (event->attr.comm)
-+ atomic_inc(&nr_comm_events);
-+ if (event->attr.task)
-+ atomic_inc(&nr_task_events);
-+ if (event->attr.freq) {
-+ if (atomic_inc_return(&nr_freq_events) == 1)
-+ tick_nohz_full_kick_all();
-+ }
-+ if (has_branch_stack(event))
-+ static_key_slow_inc(&perf_sched_events.key);
-+ if (is_cgroup_event(event))
-+ static_key_slow_inc(&perf_sched_events.key);
-+
-+ account_event_cpu(event, event->cpu);
-+}
-+
-+/*
-+ * Allocate and initialize a event structure
-+ */
-+static struct perf_event *
-+perf_event_alloc(struct perf_event_attr *attr, int cpu,
-+ struct task_struct *task,
-+ struct perf_event *group_leader,
-+ struct perf_event *parent_event,
-+ perf_overflow_handler_t overflow_handler,
-+ void *context)
-+{
-+ struct pmu *pmu;
-+ struct perf_event *event;
-+ struct hw_perf_event *hwc;
-+ long err = -EINVAL;
-+
-+ if ((unsigned)cpu >= nr_cpu_ids) {
-+ if (!task || cpu != -1)
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ event = kzalloc(sizeof(*event), GFP_KERNEL);
-+ if (!event)
-+ return ERR_PTR(-ENOMEM);
-+
-+ /*
-+ * Single events are their own group leaders, with an
-+ * empty sibling list:
-+ */
-+ if (!group_leader)
-+ group_leader = event;
-+
-+ mutex_init(&event->child_mutex);
-+ INIT_LIST_HEAD(&event->child_list);
-+
-+ INIT_LIST_HEAD(&event->group_entry);
-+ INIT_LIST_HEAD(&event->event_entry);
-+ INIT_LIST_HEAD(&event->sibling_list);
-+ INIT_LIST_HEAD(&event->rb_entry);
-+ INIT_LIST_HEAD(&event->active_entry);
-+ INIT_HLIST_NODE(&event->hlist_entry);
-+
-+
-+ init_waitqueue_head(&event->waitq);
-+ init_irq_work(&event->pending, perf_pending_event);
-+
-+ mutex_init(&event->mmap_mutex);
-+
-+ atomic_long_set(&event->refcount, 1);
-+ event->cpu = cpu;
-+ event->attr = *attr;
-+ event->group_leader = group_leader;
-+ event->pmu = NULL;
-+ event->oncpu = -1;
-+
-+ event->parent = parent_event;
-+
-+ event->ns = get_pid_ns(task_active_pid_ns(current));
-+ event->id = atomic64_inc_return(&perf_event_id);
-+
-+ event->state = PERF_EVENT_STATE_INACTIVE;
-+
-+ if (task) {
-+ event->attach_state = PERF_ATTACH_TASK;
-+
-+ if (attr->type == PERF_TYPE_TRACEPOINT)
-+ event->hw.tp_target = task;
-+#ifdef CONFIG_HAVE_HW_BREAKPOINT
-+ /*
-+ * hw_breakpoint is a bit difficult here..
-+ */
-+ else if (attr->type == PERF_TYPE_BREAKPOINT)
-+ event->hw.bp_target = task;
-+#endif
-+ }
-+
-+ if (!overflow_handler && parent_event) {
-+ overflow_handler = parent_event->overflow_handler;
-+ context = parent_event->overflow_handler_context;
-+ }
-+
-+ event->overflow_handler = overflow_handler;
-+ event->overflow_handler_context = context;
-+
-+ perf_event__state_init(event);
-+
-+ pmu = NULL;
-+
-+ hwc = &event->hw;
-+ hwc->sample_period = attr->sample_period;
-+ if (attr->freq && attr->sample_freq)
-+ hwc->sample_period = 1;
-+ hwc->last_period = hwc->sample_period;
-+
-+ local64_set(&hwc->period_left, hwc->sample_period);
-+
-+ /*
-+ * we currently do not support PERF_FORMAT_GROUP on inherited events
-+ */
-+ if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
-+ goto err_ns;
-+
-+ pmu = perf_init_event(event);
-+ if (!pmu)
-+ goto err_ns;
-+ else if (IS_ERR(pmu)) {
-+ err = PTR_ERR(pmu);
-+ goto err_ns;
-+ }
-+
-+ if (!event->parent) {
-+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
-+ err = get_callchain_buffers();
-+ if (err)
-+ goto err_pmu;
-+ }
-+ }
-+
-+ return event;
-+
-+err_pmu:
-+ if (event->destroy)
-+ event->destroy(event);
-+ module_put(pmu->module);
-+err_ns:
-+ if (event->ns)
-+ put_pid_ns(event->ns);
-+ kfree(event);
-+
-+ return ERR_PTR(err);
-+}
-+
-+static int perf_copy_attr(struct perf_event_attr __user *uattr,
-+ struct perf_event_attr *attr)
-+{
-+ u32 size;
-+ int ret;
-+
-+ if (!access_ok(VERIFY_WRITE, uattr, PERF_ATTR_SIZE_VER0))
-+ return -EFAULT;
-+
-+ /*
-+ * zero the full structure, so that a short copy will be nice.
-+ */
-+ memset(attr, 0, sizeof(*attr));
-+
-+ ret = get_user(size, &uattr->size);
-+ if (ret)
-+ return ret;
-+
-+ if (size > PAGE_SIZE) /* silly large */
-+ goto err_size;
-+
-+ if (!size) /* abi compat */
-+ size = PERF_ATTR_SIZE_VER0;
-+
-+ if (size < PERF_ATTR_SIZE_VER0)
-+ goto err_size;
-+
-+ /*
-+ * If we're handed a bigger struct than we know of,
-+ * ensure all the unknown bits are 0 - i.e. new
-+ * user-space does not rely on any kernel feature
-+ * extensions we dont know about yet.
-+ */
-+ if (size > sizeof(*attr)) {
-+ unsigned char __user *addr;
-+ unsigned char __user *end;
-+ unsigned char val;
-+
-+ addr = (void __user *)uattr + sizeof(*attr);
-+ end = (void __user *)uattr + size;
-+
-+ for (; addr < end; addr++) {
-+ ret = get_user(val, addr);
-+ if (ret)
-+ return ret;
-+ if (val)
-+ goto err_size;
-+ }
-+ size = sizeof(*attr);
-+ }
-+
-+ ret = copy_from_user(attr, uattr, size);
-+ if (ret)
-+ return -EFAULT;
-+
-+ if (attr->__reserved_1)
-+ return -EINVAL;
-+
-+ if (attr->sample_type & ~(PERF_SAMPLE_MAX-1))
-+ return -EINVAL;
-+
-+ if (attr->read_format & ~(PERF_FORMAT_MAX-1))
-+ return -EINVAL;
-+
-+ if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK) {
-+ u64 mask = attr->branch_sample_type;
-+
-+ /* only using defined bits */
-+ if (mask & ~(PERF_SAMPLE_BRANCH_MAX-1))
-+ return -EINVAL;
-+
-+ /* at least one branch bit must be set */
-+ if (!(mask & ~PERF_SAMPLE_BRANCH_PLM_ALL))
-+ return -EINVAL;
-+
-+ /* propagate priv level, when not set for branch */
-+ if (!(mask & PERF_SAMPLE_BRANCH_PLM_ALL)) {
-+
-+ /* exclude_kernel checked on syscall entry */
-+ if (!attr->exclude_kernel)
-+ mask |= PERF_SAMPLE_BRANCH_KERNEL;
-+
-+ if (!attr->exclude_user)
-+ mask |= PERF_SAMPLE_BRANCH_USER;
-+
-+ if (!attr->exclude_hv)
-+ mask |= PERF_SAMPLE_BRANCH_HV;
-+ /*
-+ * adjust user setting (for HW filter setup)
-+ */
-+ attr->branch_sample_type = mask;
-+ }
-+ /* privileged levels capture (kernel, hv): check permissions */
-+ if ((mask & PERF_SAMPLE_BRANCH_PERM_PLM)
-+ && perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN))
-+ return -EACCES;
-+ }
-+
-+ if (attr->sample_type & PERF_SAMPLE_REGS_USER) {
-+ ret = perf_reg_validate(attr->sample_regs_user);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ if (attr->sample_type & PERF_SAMPLE_STACK_USER) {
-+ if (!arch_perf_have_user_stack_dump())
-+ return -ENOSYS;
-+
-+ /*
-+ * We have __u32 type for the size, but so far
-+ * we can only use __u16 as maximum due to the
-+ * __u16 sample size limit.
-+ */
-+ if (attr->sample_stack_user >= USHRT_MAX)
-+ ret = -EINVAL;
-+ else if (!IS_ALIGNED(attr->sample_stack_user, sizeof(u64)))
-+ ret = -EINVAL;
-+ }
-+
-+out:
-+ return ret;
-+
-+err_size:
-+ put_user(sizeof(*attr), &uattr->size);
-+ ret = -E2BIG;
-+ goto out;
-+}
-+
-+static int
-+perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
-+{
-+ struct ring_buffer *rb = NULL;
-+ int ret = -EINVAL;
-+
-+ if (!output_event)
-+ goto set;
-+
-+ /* don't allow circular references */
-+ if (event == output_event)
-+ goto out;
-+
-+ /*
-+ * Don't allow cross-cpu buffers
-+ */
-+ if (output_event->cpu != event->cpu)
-+ goto out;
-+
-+ /*
-+ * If its not a per-cpu rb, it must be the same task.
-+ */
-+ if (output_event->cpu == -1 && output_event->ctx != event->ctx)
-+ goto out;
-+
-+set:
-+ mutex_lock(&event->mmap_mutex);
-+ /* Can't redirect output if we've got an active mmap() */
-+ if (atomic_read(&event->mmap_count))
-+ goto unlock;
-+
-+ if (output_event) {
-+ /* get the rb we want to redirect to */
-+ rb = ring_buffer_get(output_event);
-+ if (!rb)
-+ goto unlock;
-+ }
-+
-+ ring_buffer_attach(event, rb);
-+
-+ ret = 0;
-+unlock:
-+ mutex_unlock(&event->mmap_mutex);
-+
-+out:
-+ return ret;
-+}
-+
-+/**
-+ * sys_perf_event_open - open a performance event, associate it to a task/cpu
-+ *
-+ * @attr_uptr: event_id type attributes for monitoring/sampling
-+ * @pid: target pid
-+ * @cpu: target cpu
-+ * @group_fd: group leader event fd
-+ */
-+SYSCALL_DEFINE5(perf_event_open,
-+ struct perf_event_attr __user *, attr_uptr,
-+ pid_t, pid, int, cpu, int, group_fd, unsigned long, flags)
-+{
-+ struct perf_event *group_leader = NULL, *output_event = NULL;
-+ struct perf_event *event, *sibling;
-+ struct perf_event_attr attr;
-+ struct perf_event_context *ctx;
-+ struct file *event_file = NULL;
-+ struct fd group = {NULL, 0};
-+ struct task_struct *task = NULL;
-+ struct pmu *pmu;
-+ int event_fd;
-+ int move_group = 0;
-+ int err;
-+ int f_flags = O_RDWR;
-+
-+ /* for future expandability... */
-+ if (flags & ~PERF_FLAG_ALL)
-+ return -EINVAL;
-+
-+ err = perf_copy_attr(attr_uptr, &attr);
-+ if (err)
-+ return err;
-+
-+ if (!attr.exclude_kernel) {
-+ if (perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN))
-+ return -EACCES;
-+ }
-+
-+ if (attr.freq) {
-+ if (attr.sample_freq > sysctl_perf_event_sample_rate)
-+ return -EINVAL;
-+ } else {
-+ if (attr.sample_period & (1ULL << 63))
-+ return -EINVAL;
-+ }
-+
-+ /*
-+ * In cgroup mode, the pid argument is used to pass the fd
-+ * opened to the cgroup directory in cgroupfs. The cpu argument
-+ * designates the cpu on which to monitor threads from that
-+ * cgroup.
-+ */
-+ if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1))
-+ return -EINVAL;
-+
-+ if (flags & PERF_FLAG_FD_CLOEXEC)
-+ f_flags |= O_CLOEXEC;
-+
-+ event_fd = get_unused_fd_flags(f_flags);
-+ if (event_fd < 0)
-+ return event_fd;
-+
-+ if (group_fd != -1) {
-+ err = perf_fget_light(group_fd, &group);
-+ if (err)
-+ goto err_fd;
-+ group_leader = group.file->private_data;
-+ if (flags & PERF_FLAG_FD_OUTPUT)
-+ output_event = group_leader;
-+ if (flags & PERF_FLAG_FD_NO_GROUP)
-+ group_leader = NULL;
-+ }
-+
-+ if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) {
-+ task = find_lively_task_by_vpid(pid);
-+ if (IS_ERR(task)) {
-+ err = PTR_ERR(task);
-+ goto err_group_fd;
-+ }
-+ }
-+
-+ if (task && group_leader &&
-+ group_leader->attr.inherit != attr.inherit) {
-+ err = -EINVAL;
-+ goto err_task;
-+ }
-+
-+ get_online_cpus();
-+
-+ event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
-+ NULL, NULL);
-+ if (IS_ERR(event)) {
-+ err = PTR_ERR(event);
-+ goto err_cpus;
-+ }
-+
-+ if (flags & PERF_FLAG_PID_CGROUP) {
-+ err = perf_cgroup_connect(pid, event, &attr, group_leader);
-+ if (err) {
-+ __free_event(event);
-+ goto err_cpus;
-+ }
-+ }
-+
-+ if (is_sampling_event(event)) {
-+ if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) {
-+ err = -ENOTSUPP;
-+ goto err_alloc;
-+ }
-+ }
-+
-+ account_event(event);
-+
-+ /*
-+ * Special case software events and allow them to be part of
-+ * any hardware group.
-+ */
-+ pmu = event->pmu;
-+
-+ if (group_leader &&
-+ (is_software_event(event) != is_software_event(group_leader))) {
-+ if (is_software_event(event)) {
-+ /*
-+ * If event and group_leader are not both a software
-+ * event, and event is, then group leader is not.
-+ *
-+ * Allow the addition of software events to !software
-+ * groups, this is safe because software events never
-+ * fail to schedule.
-+ */
-+ pmu = group_leader->pmu;
-+ } else if (is_software_event(group_leader) &&
-+ (group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
-+ /*
-+ * In case the group is a pure software group, and we
-+ * try to add a hardware event, move the whole group to
-+ * the hardware context.
-+ */
-+ move_group = 1;
-+ }
-+ }
-+
-+ /*
-+ * Get the target context (task or percpu):
-+ */
-+ ctx = find_get_context(pmu, task, event->cpu);
-+ if (IS_ERR(ctx)) {
-+ err = PTR_ERR(ctx);
-+ goto err_alloc;
-+ }
-+
-+ if (task) {
-+ put_task_struct(task);
-+ task = NULL;
-+ }
-+
-+ /*
-+ * Look up the group leader (we will attach this event to it):
-+ */
-+ if (group_leader) {
-+ err = -EINVAL;
-+
-+ /*
-+ * Do not allow a recursive hierarchy (this new sibling
-+ * becoming part of another group-sibling):
-+ */
-+ if (group_leader->group_leader != group_leader)
-+ goto err_context;
-+ /*
-+ * Do not allow to attach to a group in a different
-+ * task or CPU context:
-+ */
-+ if (move_group) {
-+ if (group_leader->ctx->type != ctx->type)
-+ goto err_context;
-+ } else {
-+ if (group_leader->ctx != ctx)
-+ goto err_context;
-+ }
-+
-+ /*
-+ * Only a group leader can be exclusive or pinned
-+ */
-+ if (attr.exclusive || attr.pinned)
-+ goto err_context;
-+ }
-+
-+ if (output_event) {
-+ err = perf_event_set_output(event, output_event);
-+ if (err)
-+ goto err_context;
-+ }
-+
-+ event_file = anon_inode_getfile("[perf_event]", &perf_fops, event,
-+ f_flags);
-+ if (IS_ERR(event_file)) {
-+ err = PTR_ERR(event_file);
-+ goto err_context;
-+ }
-+
-+ if (move_group) {
-+ struct perf_event_context *gctx = group_leader->ctx;
-+
-+ mutex_lock(&gctx->mutex);
-+ perf_remove_from_context(group_leader, false);
-+
-+ /*
-+ * Removing from the context ends up with disabled
-+ * event. What we want here is event in the initial
-+ * startup state, ready to be add into new context.
-+ */
-+ perf_event__state_init(group_leader);
-+ list_for_each_entry(sibling, &group_leader->sibling_list,
-+ group_entry) {
-+ perf_remove_from_context(sibling, false);
-+ perf_event__state_init(sibling);
-+ put_ctx(gctx);
-+ }
-+ mutex_unlock(&gctx->mutex);
-+ put_ctx(gctx);
-+ }
-+
-+ WARN_ON_ONCE(ctx->parent_ctx);
-+ mutex_lock(&ctx->mutex);
-+
-+ if (move_group) {
-+ synchronize_rcu();
-+ perf_install_in_context(ctx, group_leader, group_leader->cpu);
-+ get_ctx(ctx);
-+ list_for_each_entry(sibling, &group_leader->sibling_list,
-+ group_entry) {
-+ perf_install_in_context(ctx, sibling, sibling->cpu);
-+ get_ctx(ctx);
-+ }
-+ }
-+
-+ perf_install_in_context(ctx, event, event->cpu);
-+ perf_unpin_context(ctx);
-+ mutex_unlock(&ctx->mutex);
-+
-+ put_online_cpus();
-+
-+ event->owner = current;
-+
-+ mutex_lock(&current->perf_event_mutex);
-+ list_add_tail(&event->owner_entry, &current->perf_event_list);
-+ mutex_unlock(&current->perf_event_mutex);
-+
-+ /*
-+ * Precalculate sample_data sizes
-+ */
-+ perf_event__header_size(event);
-+ perf_event__id_header_size(event);
-+
-+ /*
-+ * Drop the reference on the group_event after placing the
-+ * new event on the sibling_list. This ensures destruction
-+ * of the group leader will find the pointer to itself in
-+ * perf_group_detach().
-+ */
-+ fdput(group);
-+ fd_install(event_fd, event_file);
-+ return event_fd;
-+
-+err_context:
-+ perf_unpin_context(ctx);
-+ put_ctx(ctx);
-+err_alloc:
-+ free_event(event);
-+err_cpus:
-+ put_online_cpus();
-+err_task:
-+ if (task)
-+ put_task_struct(task);
-+err_group_fd:
-+ fdput(group);
-+err_fd:
-+ put_unused_fd(event_fd);
-+ return err;
-+}
-+
-+/**
-+ * perf_event_create_kernel_counter
-+ *
-+ * @attr: attributes of the counter to create
-+ * @cpu: cpu in which the counter is bound
-+ * @task: task to profile (NULL for percpu)
-+ */
-+struct perf_event *
-+perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
-+ struct task_struct *task,
-+ perf_overflow_handler_t overflow_handler,
-+ void *context)
-+{
-+ struct perf_event_context *ctx;
-+ struct perf_event *event;
-+ int err;
-+
-+ /*
-+ * Get the target context (task or percpu):
-+ */
-+
-+ event = perf_event_alloc(attr, cpu, task, NULL, NULL,
-+ overflow_handler, context);
-+ if (IS_ERR(event)) {
-+ err = PTR_ERR(event);
-+ goto err;
-+ }
-+
-+ /* Mark owner so we could distinguish it from user events. */
-+ event->owner = EVENT_OWNER_KERNEL;
-+
-+ account_event(event);
-+
-+ ctx = find_get_context(event->pmu, task, cpu);
-+ if (IS_ERR(ctx)) {
-+ err = PTR_ERR(ctx);
-+ goto err_free;
-+ }
-+
-+ WARN_ON_ONCE(ctx->parent_ctx);
-+ mutex_lock(&ctx->mutex);
-+ perf_install_in_context(ctx, event, cpu);
-+ perf_unpin_context(ctx);
-+ mutex_unlock(&ctx->mutex);
-+
-+ return event;
-+
-+err_free:
-+ free_event(event);
-+err:
-+ return ERR_PTR(err);
-+}
-+EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
-+
-+void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
-+{
-+ struct perf_event_context *src_ctx;
-+ struct perf_event_context *dst_ctx;
-+ struct perf_event *event, *tmp;
-+ LIST_HEAD(events);
-+
-+ src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx;
-+ dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx;
-+
-+ mutex_lock(&src_ctx->mutex);
-+ list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
-+ event_entry) {
-+ perf_remove_from_context(event, false);
-+ unaccount_event_cpu(event, src_cpu);
-+ put_ctx(src_ctx);
-+ list_add(&event->migrate_entry, &events);
-+ }
-+ mutex_unlock(&src_ctx->mutex);
-+
-+ synchronize_rcu();
-+
-+ mutex_lock(&dst_ctx->mutex);
-+ list_for_each_entry_safe(event, tmp, &events, migrate_entry) {
-+ list_del(&event->migrate_entry);
-+ if (event->state >= PERF_EVENT_STATE_OFF)
-+ event->state = PERF_EVENT_STATE_INACTIVE;
-+ account_event_cpu(event, dst_cpu);
-+ perf_install_in_context(dst_ctx, event, dst_cpu);
-+ get_ctx(dst_ctx);
-+ }
-+ mutex_unlock(&dst_ctx->mutex);
-+}
-+EXPORT_SYMBOL_GPL(perf_pmu_migrate_context);
-+
-+static void sync_child_event(struct perf_event *child_event,
-+ struct task_struct *child)
-+{
-+ struct perf_event *parent_event = child_event->parent;
-+ u64 child_val;
-+
-+ if (child_event->attr.inherit_stat)
-+ perf_event_read_event(child_event, child);
-+
-+ child_val = perf_event_count(child_event);
-+
-+ /*
-+ * Add back the child's count to the parent's count:
-+ */
-+ atomic64_add(child_val, &parent_event->child_count);
-+ atomic64_add(child_event->total_time_enabled,
-+ &parent_event->child_total_time_enabled);
-+ atomic64_add(child_event->total_time_running,
-+ &parent_event->child_total_time_running);
-+
-+ /*
-+ * Remove this event from the parent's list
-+ */
-+ WARN_ON_ONCE(parent_event->ctx->parent_ctx);
-+ mutex_lock(&parent_event->child_mutex);
-+ list_del_init(&child_event->child_list);
-+ mutex_unlock(&parent_event->child_mutex);
-+
-+ /*
-+ * Make sure user/parent get notified, that we just
-+ * lost one event.
-+ */
-+ perf_event_wakeup(parent_event);
-+
-+ /*
-+ * Release the parent event, if this was the last
-+ * reference to it.
-+ */
-+ put_event(parent_event);
-+}
-+
-+static void
-+__perf_event_exit_task(struct perf_event *child_event,
-+ struct perf_event_context *child_ctx,
-+ struct task_struct *child)
-+{
-+ /*
-+ * Do not destroy the 'original' grouping; because of the context
-+ * switch optimization the original events could've ended up in a
-+ * random child task.
-+ *
-+ * If we were to destroy the original group, all group related
-+ * operations would cease to function properly after this random
-+ * child dies.
-+ *
-+ * Do destroy all inherited groups, we don't care about those
-+ * and being thorough is better.
-+ */
-+ perf_remove_from_context(child_event, !!child_event->parent);
-+
-+ /*
-+ * It can happen that the parent exits first, and has events
-+ * that are still around due to the child reference. These
-+ * events need to be zapped.
-+ */
-+ if (child_event->parent) {
-+ sync_child_event(child_event, child);
-+ free_event(child_event);
-+ } else {
-+ child_event->state = PERF_EVENT_STATE_EXIT;
-+ perf_event_wakeup(child_event);
-+ }
-+}
-+
-+static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
-+{
-+ struct perf_event *child_event, *next;
-+ struct perf_event_context *child_ctx, *clone_ctx = NULL;
-+ unsigned long flags;
-+
-+ if (likely(!child->perf_event_ctxp[ctxn])) {
-+ perf_event_task(child, NULL, 0);
-+ return;
-+ }
-+
-+ local_irq_save(flags);
-+ /*
-+ * We can't reschedule here because interrupts are disabled,
-+ * and either child is current or it is a task that can't be
-+ * scheduled, so we are now safe from rescheduling changing
-+ * our context.
-+ */
-+ child_ctx = rcu_dereference_raw(child->perf_event_ctxp[ctxn]);
-+
-+ /*
-+ * Take the context lock here so that if find_get_context is
-+ * reading child->perf_event_ctxp, we wait until it has
-+ * incremented the context's refcount before we do put_ctx below.
-+ */
-+ raw_spin_lock(&child_ctx->lock);
-+ task_ctx_sched_out(child_ctx);
-+ child->perf_event_ctxp[ctxn] = NULL;
-+
-+ /*
-+ * If this context is a clone; unclone it so it can't get
-+ * swapped to another process while we're removing all
-+ * the events from it.
-+ */
-+ clone_ctx = unclone_ctx(child_ctx);
-+ update_context_time(child_ctx);
-+ raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
-+
-+ if (clone_ctx)
-+ put_ctx(clone_ctx);
-+
-+ /*
-+ * Report the task dead after unscheduling the events so that we
-+ * won't get any samples after PERF_RECORD_EXIT. We can however still
-+ * get a few PERF_RECORD_READ events.
-+ */
-+ perf_event_task(child, child_ctx, 0);
-+
-+ /*
-+ * We can recurse on the same lock type through:
-+ *
-+ * __perf_event_exit_task()
-+ * sync_child_event()
-+ * put_event()
-+ * mutex_lock(&ctx->mutex)
-+ *
-+ * But since its the parent context it won't be the same instance.
-+ */
-+ mutex_lock(&child_ctx->mutex);
-+
-+ list_for_each_entry_safe(child_event, next, &child_ctx->event_list, event_entry)
-+ __perf_event_exit_task(child_event, child_ctx, child);
-+
-+ mutex_unlock(&child_ctx->mutex);
-+
-+ put_ctx(child_ctx);
-+}
-+
-+/*
-+ * When a child task exits, feed back event values to parent events.
-+ */
-+void perf_event_exit_task(struct task_struct *child)
-+{
-+ struct perf_event *event, *tmp;
-+ int ctxn;
-+
-+ mutex_lock(&child->perf_event_mutex);
-+ list_for_each_entry_safe(event, tmp, &child->perf_event_list,
-+ owner_entry) {
-+ list_del_init(&event->owner_entry);
-+
-+ /*
-+ * Ensure the list deletion is visible before we clear
-+ * the owner, closes a race against perf_release() where
-+ * we need to serialize on the owner->perf_event_mutex.
-+ */
-+ smp_wmb();
-+ event->owner = NULL;
-+ }
-+ mutex_unlock(&child->perf_event_mutex);
-+
-+ for_each_task_context_nr(ctxn)
-+ perf_event_exit_task_context(child, ctxn);
-+}
-+
-+static void perf_free_event(struct perf_event *event,
-+ struct perf_event_context *ctx)
-+{
-+ struct perf_event *parent = event->parent;
-+
-+ if (WARN_ON_ONCE(!parent))
-+ return;
-+
-+ mutex_lock(&parent->child_mutex);
-+ list_del_init(&event->child_list);
-+ mutex_unlock(&parent->child_mutex);
-+
-+ put_event(parent);
-+
-+ perf_group_detach(event);
-+ list_del_event(event, ctx);
-+ free_event(event);
-+}
-+
-+/*
-+ * free an unexposed, unused context as created by inheritance by
-+ * perf_event_init_task below, used by fork() in case of fail.
-+ */
-+void perf_event_free_task(struct task_struct *task)
-+{
-+ struct perf_event_context *ctx;
-+ struct perf_event *event, *tmp;
-+ int ctxn;
-+
-+ for_each_task_context_nr(ctxn) {
-+ ctx = task->perf_event_ctxp[ctxn];
-+ if (!ctx)
-+ continue;
-+
-+ mutex_lock(&ctx->mutex);
-+again:
-+ list_for_each_entry_safe(event, tmp, &ctx->pinned_groups,
-+ group_entry)
-+ perf_free_event(event, ctx);
-+
-+ list_for_each_entry_safe(event, tmp, &ctx->flexible_groups,
-+ group_entry)
-+ perf_free_event(event, ctx);
-+
-+ if (!list_empty(&ctx->pinned_groups) ||
-+ !list_empty(&ctx->flexible_groups))
-+ goto again;
-+
-+ mutex_unlock(&ctx->mutex);
-+
-+ put_ctx(ctx);
-+ }
-+}
-+
-+void perf_event_delayed_put(struct task_struct *task)
-+{
-+ int ctxn;
-+
-+ for_each_task_context_nr(ctxn)
-+ WARN_ON_ONCE(task->perf_event_ctxp[ctxn]);
-+}
-+
-+/*
-+ * inherit a event from parent task to child task:
-+ */
-+static struct perf_event *
-+inherit_event(struct perf_event *parent_event,
-+ struct task_struct *parent,
-+ struct perf_event_context *parent_ctx,
-+ struct task_struct *child,
-+ struct perf_event *group_leader,
-+ struct perf_event_context *child_ctx)
-+{
-+ enum perf_event_active_state parent_state = parent_event->state;
-+ struct perf_event *child_event;
-+ unsigned long flags;
-+
-+ /*
-+ * Instead of creating recursive hierarchies of events,
-+ * we link inherited events back to the original parent,
-+ * which has a filp for sure, which we use as the reference
-+ * count:
-+ */
-+ if (parent_event->parent)
-+ parent_event = parent_event->parent;
-+
-+ child_event = perf_event_alloc(&parent_event->attr,
-+ parent_event->cpu,
-+ child,
-+ group_leader, parent_event,
-+ NULL, NULL);
-+ if (IS_ERR(child_event))
-+ return child_event;
-+
-+ if (is_orphaned_event(parent_event) ||
-+ !atomic_long_inc_not_zero(&parent_event->refcount)) {
-+ free_event(child_event);
-+ return NULL;
-+ }
-+
-+ get_ctx(child_ctx);
-+
-+ /*
-+ * Make the child state follow the state of the parent event,
-+ * not its attr.disabled bit. We hold the parent's mutex,
-+ * so we won't race with perf_event_{en, dis}able_family.
-+ */
-+ if (parent_state >= PERF_EVENT_STATE_INACTIVE)
-+ child_event->state = PERF_EVENT_STATE_INACTIVE;
-+ else
-+ child_event->state = PERF_EVENT_STATE_OFF;
-+
-+ if (parent_event->attr.freq) {
-+ u64 sample_period = parent_event->hw.sample_period;
-+ struct hw_perf_event *hwc = &child_event->hw;
-+
-+ hwc->sample_period = sample_period;
-+ hwc->last_period = sample_period;
-+
-+ local64_set(&hwc->period_left, sample_period);
-+ }
-+
-+ child_event->ctx = child_ctx;
-+ child_event->overflow_handler = parent_event->overflow_handler;
-+ child_event->overflow_handler_context
-+ = parent_event->overflow_handler_context;
-+
-+ /*
-+ * Precalculate sample_data sizes
-+ */
-+ perf_event__header_size(child_event);
-+ perf_event__id_header_size(child_event);
-+
-+ /*
-+ * Link it up in the child's context:
-+ */
-+ raw_spin_lock_irqsave(&child_ctx->lock, flags);
-+ add_event_to_ctx(child_event, child_ctx);
-+ raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
-+
-+ /*
-+ * Link this into the parent event's child list
-+ */
-+ WARN_ON_ONCE(parent_event->ctx->parent_ctx);
-+ mutex_lock(&parent_event->child_mutex);
-+ list_add_tail(&child_event->child_list, &parent_event->child_list);
-+ mutex_unlock(&parent_event->child_mutex);
-+
-+ return child_event;
-+}
-+
-+static int inherit_group(struct perf_event *parent_event,
-+ struct task_struct *parent,
-+ struct perf_event_context *parent_ctx,
-+ struct task_struct *child,
-+ struct perf_event_context *child_ctx)
-+{
-+ struct perf_event *leader;
-+ struct perf_event *sub;
-+ struct perf_event *child_ctr;
-+
-+ leader = inherit_event(parent_event, parent, parent_ctx,
-+ child, NULL, child_ctx);
-+ if (IS_ERR(leader))
-+ return PTR_ERR(leader);
-+ list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
-+ child_ctr = inherit_event(sub, parent, parent_ctx,
-+ child, leader, child_ctx);
-+ if (IS_ERR(child_ctr))
-+ return PTR_ERR(child_ctr);
-+ }
-+ return 0;
-+}
-+
-+static int
-+inherit_task_group(struct perf_event *event, struct task_struct *parent,
-+ struct perf_event_context *parent_ctx,
-+ struct task_struct *child, int ctxn,
-+ int *inherited_all)
-+{
-+ int ret;
-+ struct perf_event_context *child_ctx;
-+
-+ if (!event->attr.inherit) {
-+ *inherited_all = 0;
-+ return 0;
-+ }
-+
-+ child_ctx = child->perf_event_ctxp[ctxn];
-+ if (!child_ctx) {
-+ /*
-+ * This is executed from the parent task context, so
-+ * inherit events that have been marked for cloning.
-+ * First allocate and initialize a context for the
-+ * child.
-+ */
-+
-+ child_ctx = alloc_perf_context(parent_ctx->pmu, child);
-+ if (!child_ctx)
-+ return -ENOMEM;
-+
-+ child->perf_event_ctxp[ctxn] = child_ctx;
-+ }
-+
-+ ret = inherit_group(event, parent, parent_ctx,
-+ child, child_ctx);
-+
-+ if (ret)
-+ *inherited_all = 0;
-+
-+ return ret;
-+}
-+
-+/*
-+ * Initialize the perf_event context in task_struct
-+ */
-+static int perf_event_init_context(struct task_struct *child, int ctxn)
-+{
-+ struct perf_event_context *child_ctx, *parent_ctx;
-+ struct perf_event_context *cloned_ctx;
-+ struct perf_event *event;
-+ struct task_struct *parent = current;
-+ int inherited_all = 1;
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ if (likely(!parent->perf_event_ctxp[ctxn]))
-+ return 0;
-+
-+ /*
-+ * If the parent's context is a clone, pin it so it won't get
-+ * swapped under us.
-+ */
-+ parent_ctx = perf_pin_task_context(parent, ctxn);
-+ if (!parent_ctx)
-+ return 0;
-+
-+ /*
-+ * No need to check if parent_ctx != NULL here; since we saw
-+ * it non-NULL earlier, the only reason for it to become NULL
-+ * is if we exit, and since we're currently in the middle of
-+ * a fork we can't be exiting at the same time.
-+ */
-+
-+ /*
-+ * Lock the parent list. No need to lock the child - not PID
-+ * hashed yet and not running, so nobody can access it.
-+ */
-+ mutex_lock(&parent_ctx->mutex);
-+
-+ /*
-+ * We dont have to disable NMIs - we are only looking at
-+ * the list, not manipulating it:
-+ */
-+ list_for_each_entry(event, &parent_ctx->pinned_groups, group_entry) {
-+ ret = inherit_task_group(event, parent, parent_ctx,
-+ child, ctxn, &inherited_all);
-+ if (ret)
-+ break;
-+ }
-+
-+ /*
-+ * We can't hold ctx->lock when iterating the ->flexible_group list due
-+ * to allocations, but we need to prevent rotation because
-+ * rotate_ctx() will change the list from interrupt context.
-+ */
-+ raw_spin_lock_irqsave(&parent_ctx->lock, flags);
-+ parent_ctx->rotate_disable = 1;
-+ raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
-+
-+ list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) {
-+ ret = inherit_task_group(event, parent, parent_ctx,
-+ child, ctxn, &inherited_all);
-+ if (ret)
-+ break;
-+ }
-+
-+ raw_spin_lock_irqsave(&parent_ctx->lock, flags);
-+ parent_ctx->rotate_disable = 0;
-+
-+ child_ctx = child->perf_event_ctxp[ctxn];
-+
-+ if (child_ctx && inherited_all) {
-+ /*
-+ * Mark the child context as a clone of the parent
-+ * context, or of whatever the parent is a clone of.
-+ *
-+ * Note that if the parent is a clone, the holding of
-+ * parent_ctx->lock avoids it from being uncloned.
-+ */
-+ cloned_ctx = parent_ctx->parent_ctx;
-+ if (cloned_ctx) {
-+ child_ctx->parent_ctx = cloned_ctx;
-+ child_ctx->parent_gen = parent_ctx->parent_gen;
-+ } else {
-+ child_ctx->parent_ctx = parent_ctx;
-+ child_ctx->parent_gen = parent_ctx->generation;
-+ }
-+ get_ctx(child_ctx->parent_ctx);
-+ }
-+
-+ raw_spin_unlock_irqrestore(&parent_ctx->lock, flags);
-+ mutex_unlock(&parent_ctx->mutex);
-+
-+ perf_unpin_context(parent_ctx);
-+ put_ctx(parent_ctx);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Initialize the perf_event context in task_struct
-+ */
-+int perf_event_init_task(struct task_struct *child)
-+{
-+ int ctxn, ret;
-+
-+ memset(child->perf_event_ctxp, 0, sizeof(child->perf_event_ctxp));
-+ mutex_init(&child->perf_event_mutex);
-+ INIT_LIST_HEAD(&child->perf_event_list);
-+
-+ for_each_task_context_nr(ctxn) {
-+ ret = perf_event_init_context(child, ctxn);
-+ if (ret) {
-+ perf_event_free_task(child);
-+ return ret;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void __init perf_event_init_all_cpus(void)
-+{
-+ struct swevent_htable *swhash;
-+ int cpu;
-+
-+ for_each_possible_cpu(cpu) {
-+ swhash = &per_cpu(swevent_htable, cpu);
-+ mutex_init(&swhash->hlist_mutex);
-+ INIT_LIST_HEAD(&per_cpu(rotation_list, cpu));
-+ }
-+}
-+
-+static void perf_event_init_cpu(int cpu)
-+{
-+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-+
-+ mutex_lock(&swhash->hlist_mutex);
-+ swhash->online = true;
-+ if (swhash->hlist_refcount > 0) {
-+ struct swevent_hlist *hlist;
-+
-+ hlist = kzalloc_node(sizeof(*hlist), GFP_KERNEL, cpu_to_node(cpu));
-+ WARN_ON(!hlist);
-+ rcu_assign_pointer(swhash->swevent_hlist, hlist);
-+ }
-+ mutex_unlock(&swhash->hlist_mutex);
-+}
-+
-+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC
-+static void perf_pmu_rotate_stop(struct pmu *pmu)
-+{
-+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
-+
-+ WARN_ON(!irqs_disabled());
-+
-+ list_del_init(&cpuctx->rotation_list);
-+}
-+
-+static void __perf_event_exit_context(void *__info)
-+{
-+ struct remove_event re = { .detach_group = true };
-+ struct perf_event_context *ctx = __info;
-+
-+ perf_pmu_rotate_stop(ctx->pmu);
-+
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry)
-+ __perf_remove_from_context(&re);
-+ rcu_read_unlock();
-+}
-+
-+static void perf_event_exit_cpu_context(int cpu)
-+{
-+ struct perf_event_context *ctx;
-+ struct pmu *pmu;
-+ int idx;
-+
-+ idx = srcu_read_lock(&pmus_srcu);
-+ list_for_each_entry_rcu(pmu, &pmus, entry) {
-+ ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
-+
-+ mutex_lock(&ctx->mutex);
-+ smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
-+ mutex_unlock(&ctx->mutex);
-+ }
-+ srcu_read_unlock(&pmus_srcu, idx);
-+}
-+
-+static void perf_event_exit_cpu(int cpu)
-+{
-+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-+
-+ perf_event_exit_cpu_context(cpu);
-+
-+ mutex_lock(&swhash->hlist_mutex);
-+ swhash->online = false;
-+ swevent_hlist_release(swhash);
-+ mutex_unlock(&swhash->hlist_mutex);
-+}
-+#else
-+static inline void perf_event_exit_cpu(int cpu) { }
-+#endif
-+
-+static int
-+perf_reboot(struct notifier_block *notifier, unsigned long val, void *v)
-+{
-+ int cpu;
-+
-+ for_each_online_cpu(cpu)
-+ perf_event_exit_cpu(cpu);
-+
-+ return NOTIFY_OK;
-+}
-+
-+/*
-+ * Run the perf reboot notifier at the very last possible moment so that
-+ * the generic watchdog code runs as long as possible.
-+ */
-+static struct notifier_block perf_reboot_notifier = {
-+ .notifier_call = perf_reboot,
-+ .priority = INT_MIN,
-+};
-+
-+static int
-+perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
-+{
-+ unsigned int cpu = (long)hcpu;
-+
-+ switch (action & ~CPU_TASKS_FROZEN) {
-+
-+ case CPU_UP_PREPARE:
-+ case CPU_DOWN_FAILED:
-+ perf_event_init_cpu(cpu);
-+ break;
-+
-+ case CPU_UP_CANCELED:
-+ case CPU_DOWN_PREPARE:
-+ perf_event_exit_cpu(cpu);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ return NOTIFY_OK;
-+}
-+
-+void __init perf_event_init(void)
-+{
-+ int ret;
-+
-+ idr_init(&pmu_idr);
-+
-+ perf_event_init_all_cpus();
-+ init_srcu_struct(&pmus_srcu);
-+ perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);
-+ perf_pmu_register(&perf_cpu_clock, NULL, -1);
-+ perf_pmu_register(&perf_task_clock, NULL, -1);
-+ perf_tp_register();
-+ perf_cpu_notifier(perf_cpu_notify);
-+ register_reboot_notifier(&perf_reboot_notifier);
-+
-+ ret = init_hw_breakpoint();
-+ WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
-+
-+ /* do not patch jump label more than once per second */
-+ jump_label_rate_limit(&perf_sched_events, HZ);
-+
-+ /*
-+ * Build time assertion that we keep the data_head at the intended
-+ * location. IOW, validation we got the __reserved[] size right.
-+ */
-+ BUILD_BUG_ON((offsetof(struct perf_event_mmap_page, data_head))
-+ != 1024);
-+}
-+
-+static int __init perf_event_sysfs_init(void)
-+{
-+ struct pmu *pmu;
-+ int ret;
-+
-+ mutex_lock(&pmus_lock);
-+
-+ ret = bus_register(&pmu_bus);
-+ if (ret)
-+ goto unlock;
-+
-+ list_for_each_entry(pmu, &pmus, entry) {
-+ if (!pmu->name || pmu->type < 0)
-+ continue;
-+
-+ ret = pmu_dev_alloc(pmu);
-+ WARN(ret, "Failed to register pmu: %s, reason %d\n", pmu->name, ret);
-+ }
-+ pmu_bus_running = 1;
-+ ret = 0;
-+
-+unlock:
-+ mutex_unlock(&pmus_lock);
-+
-+ return ret;
-+}
-+device_initcall(perf_event_sysfs_init);
-+
-+#ifdef CONFIG_CGROUP_PERF
-+static struct cgroup_subsys_state *
-+perf_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
-+{
-+ struct perf_cgroup *jc;
-+
-+ jc = kzalloc(sizeof(*jc), GFP_KERNEL);
-+ if (!jc)
-+ return ERR_PTR(-ENOMEM);
-+
-+ jc->info = alloc_percpu(struct perf_cgroup_info);
-+ if (!jc->info) {
-+ kfree(jc);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ return &jc->css;
-+}
-+
-+static void perf_cgroup_css_free(struct cgroup_subsys_state *css)
-+{
-+ struct perf_cgroup *jc = container_of(css, struct perf_cgroup, css);
-+
-+ free_percpu(jc->info);
-+ kfree(jc);
-+}
-+
-+static int __perf_cgroup_move(void *info)
-+{
-+ struct task_struct *task = info;
-+ perf_cgroup_switch(task, PERF_CGROUP_SWOUT | PERF_CGROUP_SWIN);
-+ return 0;
-+}
-+
-+static void perf_cgroup_attach(struct cgroup_subsys_state *css,
-+ struct cgroup_taskset *tset)
-+{
-+ struct task_struct *task;
-+
-+ cgroup_taskset_for_each(task, tset)
-+ task_function_call(task, __perf_cgroup_move, task);
-+}
-+
-+static void perf_cgroup_exit(struct cgroup_subsys_state *css,
-+ struct cgroup_subsys_state *old_css,
-+ struct task_struct *task)
-+{
-+ /*
-+ * cgroup_exit() is called in the copy_process() failure path.
-+ * Ignore this case since the task hasn't ran yet, this avoids
-+ * trying to poke a half freed task state from generic code.
-+ */
-+ if (!(task->flags & PF_EXITING))
-+ return;
-+
-+ task_function_call(task, __perf_cgroup_move, task);
-+}
-+
-+struct cgroup_subsys perf_event_cgrp_subsys = {
-+ .css_alloc = perf_cgroup_css_alloc,
-+ .css_free = perf_cgroup_css_free,
-+ .exit = perf_cgroup_exit,
-+ .attach = perf_cgroup_attach,
-+};
-+#endif /* CONFIG_CGROUP_PERF */
-diff -Nur linux-3.18.12.orig/kernel/exit.c linux-3.18.12/kernel/exit.c
---- linux-3.18.12.orig/kernel/exit.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/exit.c 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/exit.c linux-3.18.14-rt/kernel/exit.c
+--- linux-3.18.14.orig/kernel/exit.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/exit.c 2015-05-31 15:32:48.649635365 -0500
@@ -147,7 +147,7 @@
* Do this under ->siglock, we can race with another thread
* doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
@@ -20169,9 +19949,9 @@ diff -Nur linux-3.18.12.orig/kernel/exit.c linux-3.18.12/kernel/exit.c
tsk->sighand = NULL;
spin_unlock(&sighand->siglock);
-diff -Nur linux-3.18.12.orig/kernel/fork.c linux-3.18.12/kernel/fork.c
---- linux-3.18.12.orig/kernel/fork.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/fork.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/fork.c linux-3.18.14-rt/kernel/fork.c
+--- linux-3.18.14.orig/kernel/fork.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/fork.c 2015-05-31 15:32:48.657635365 -0500
@@ -97,7 +97,7 @@
DEFINE_PER_CPU(unsigned long, process_counts) = 0;
@@ -20269,9 +20049,9 @@ diff -Nur linux-3.18.12.orig/kernel/fork.c linux-3.18.12/kernel/fork.c
#ifdef CONFIG_LOCKDEP
p->lockdep_depth = 0; /* no locks held yet */
p->curr_chain_key = 0;
-diff -Nur linux-3.18.12.orig/kernel/futex.c linux-3.18.12/kernel/futex.c
---- linux-3.18.12.orig/kernel/futex.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/futex.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/futex.c linux-3.18.14-rt/kernel/futex.c
+--- linux-3.18.14.orig/kernel/futex.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/futex.c 2015-05-31 15:32:48.665635365 -0500
@@ -738,7 +738,9 @@
* task still owns the PI-state:
*/
@@ -20410,9 +20190,9 @@ diff -Nur linux-3.18.12.orig/kernel/futex.c linux-3.18.12/kernel/futex.c
/*
* Fixup the pi_state owner and possibly acquire the lock if we
* haven't already.
-diff -Nur linux-3.18.12.orig/kernel/irq/handle.c linux-3.18.12/kernel/irq/handle.c
---- linux-3.18.12.orig/kernel/irq/handle.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/irq/handle.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/irq/handle.c linux-3.18.14-rt/kernel/irq/handle.c
+--- linux-3.18.14.orig/kernel/irq/handle.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/irq/handle.c 2015-05-31 15:32:48.677635365 -0500
@@ -133,6 +133,8 @@
irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
@@ -20435,9 +20215,9 @@ diff -Nur linux-3.18.12.orig/kernel/irq/handle.c linux-3.18.12/kernel/irq/handle
if (!noirqdebug)
note_interrupt(irq, desc, retval);
-diff -Nur linux-3.18.12.orig/kernel/irq/manage.c linux-3.18.12/kernel/irq/manage.c
---- linux-3.18.12.orig/kernel/irq/manage.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/irq/manage.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/irq/manage.c linux-3.18.14-rt/kernel/irq/manage.c
+--- linux-3.18.14.orig/kernel/irq/manage.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/irq/manage.c 2015-05-31 15:32:48.697635365 -0500
@@ -22,6 +22,7 @@
#include "internals.h"
@@ -20610,9 +20390,9 @@ diff -Nur linux-3.18.12.orig/kernel/irq/manage.c linux-3.18.12/kernel/irq/manage
/* Set default affinity mask once everything is setup */
setup_affinity(irq, desc, mask);
-diff -Nur linux-3.18.12.orig/kernel/irq/settings.h linux-3.18.12/kernel/irq/settings.h
---- linux-3.18.12.orig/kernel/irq/settings.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/irq/settings.h 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/irq/settings.h linux-3.18.14-rt/kernel/irq/settings.h
+--- linux-3.18.14.orig/kernel/irq/settings.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/irq/settings.h 2015-05-31 15:32:48.697635365 -0500
@@ -15,6 +15,7 @@
_IRQ_NESTED_THREAD = IRQ_NESTED_THREAD,
_IRQ_PER_CPU_DEVID = IRQ_PER_CPU_DEVID,
@@ -20646,9 +20426,9 @@ diff -Nur linux-3.18.12.orig/kernel/irq/settings.h linux-3.18.12/kernel/irq/sett
static inline bool irq_settings_is_per_cpu(struct irq_desc *desc)
{
return desc->status_use_accessors & _IRQ_PER_CPU;
-diff -Nur linux-3.18.12.orig/kernel/irq/spurious.c linux-3.18.12/kernel/irq/spurious.c
---- linux-3.18.12.orig/kernel/irq/spurious.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/irq/spurious.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/irq/spurious.c linux-3.18.14-rt/kernel/irq/spurious.c
+--- linux-3.18.14.orig/kernel/irq/spurious.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/irq/spurious.c 2015-05-31 15:32:48.709635364 -0500
@@ -444,6 +444,10 @@
static int __init irqfixup_setup(char *str)
@@ -20671,10 +20451,10 @@ diff -Nur linux-3.18.12.orig/kernel/irq/spurious.c linux-3.18.12/kernel/irq/spur
irqfixup = 2;
printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
"enabled\n");
-diff -Nur linux-3.18.12.orig/kernel/irq_work.c linux-3.18.12/kernel/irq_work.c
---- linux-3.18.12.orig/kernel/irq_work.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/irq_work.c 2015-04-26 13:32:22.435684003 -0500
-@@ -17,12 +17,15 @@
+diff -Nur linux-3.18.14.orig/kernel/irq_work.c linux-3.18.14-rt/kernel/irq_work.c
+--- linux-3.18.14.orig/kernel/irq_work.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/irq_work.c 2015-05-31 15:32:48.713635365 -0500
+@@ -17,6 +17,7 @@
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/smp.h>
@@ -20682,126 +20462,116 @@ diff -Nur linux-3.18.12.orig/kernel/irq_work.c linux-3.18.12/kernel/irq_work.c
#include <asm/processor.h>
- static DEFINE_PER_CPU(struct llist_head, raised_list);
- static DEFINE_PER_CPU(struct llist_head, lazy_list);
--
-+#ifdef CONFIG_PREEMPT_RT_FULL
-+static DEFINE_PER_CPU(struct llist_head, hirq_work_list);
-+#endif
- /*
- * Claim the entry so that no one else will poke at it.
- */
-@@ -65,6 +68,8 @@
+@@ -65,6 +66,8 @@
*/
bool irq_work_queue_on(struct irq_work *work, int cpu)
{
-+ bool raise_irqwork;
++ struct llist_head *list;
+
/* All work should have been flushed before going offline */
WARN_ON_ONCE(cpu_is_offline(cpu));
-@@ -75,7 +80,19 @@
+@@ -75,7 +78,12 @@
if (!irq_work_claim(work))
return false;
- if (llist_add(&work->llnode, &per_cpu(raised_list, cpu)))
-+#ifdef CONFIG_PREEMPT_RT_FULL
-+ if (work->flags & IRQ_WORK_HARD_IRQ)
-+ raise_irqwork = llist_add(&work->llnode,
-+ &per_cpu(hirq_work_list, cpu));
++ if (IS_ENABLED(CONFIG_PREEMPT_RT_FULL) && !(work->flags & IRQ_WORK_HARD_IRQ))
++ list = &per_cpu(lazy_list, cpu);
+ else
-+ raise_irqwork = llist_add(&work->llnode,
-+ &per_cpu(lazy_list, cpu));
-+#else
-+ raise_irqwork = llist_add(&work->llnode,
-+ &per_cpu(raised_list, cpu));
-+#endif
++ list = &per_cpu(raised_list, cpu);
+
-+ if (raise_irqwork)
++ if (llist_add(&work->llnode, list))
arch_send_call_function_single_ipi(cpu);
return true;
-@@ -93,7 +110,16 @@
+@@ -86,6 +94,9 @@
+ /* Enqueue the irq work @work on the current CPU */
+ bool irq_work_queue(struct irq_work *work)
+ {
++ struct llist_head *list;
++ bool lazy_work, realtime = IS_ENABLED(CONFIG_PREEMPT_RT_FULL);
++
+ /* Only queue if not already pending */
+ if (!irq_work_claim(work))
+ return false;
+@@ -93,13 +104,15 @@
/* Queue the entry and raise the IPI if needed. */
preempt_disable();
- /* If the work is "lazy", handle it from next tick if any */
-+#ifdef CONFIG_PREEMPT_RT_FULL
-+ if (work->flags & IRQ_WORK_HARD_IRQ) {
-+ if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list)))
-+ arch_irq_work_raise();
-+ } else {
-+ if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
-+ tick_nohz_tick_stopped())
-+ raise_softirq(TIMER_SOFTIRQ);
-+ }
-+#else
- if (work->flags & IRQ_WORK_LAZY) {
- if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
- tick_nohz_tick_stopped())
-@@ -102,6 +128,7 @@
- if (llist_add(&work->llnode, this_cpu_ptr(&raised_list)))
+- if (work->flags & IRQ_WORK_LAZY) {
+- if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
+- tick_nohz_tick_stopped())
+- arch_irq_work_raise();
+- } else {
+- if (llist_add(&work->llnode, this_cpu_ptr(&raised_list)))
++ lazy_work = work->flags & IRQ_WORK_LAZY;
++
++ if (lazy_work || (realtime && !(work->flags & IRQ_WORK_HARD_IRQ)))
++ list = this_cpu_ptr(&lazy_list);
++ else
++ list = this_cpu_ptr(&raised_list);
++
++ if (llist_add(&work->llnode, list)) {
++ if (!lazy_work || tick_nohz_tick_stopped())
arch_irq_work_raise();
}
-+#endif
- preempt_enable();
-
-@@ -116,9 +143,12 @@
+@@ -116,9 +129,8 @@
raised = this_cpu_ptr(&raised_list);
lazy = this_cpu_ptr(&lazy_list);
- if (llist_empty(raised) || arch_irq_work_has_interrupt())
-+ if (llist_empty(raised))
- if (llist_empty(lazy))
+- if (llist_empty(lazy))
- return false;
-+#ifdef CONFIG_PREEMPT_RT_FULL
-+ if (llist_empty(this_cpu_ptr(&hirq_work_list)))
-+#endif
-+ return false;
++ if (llist_empty(raised) && llist_empty(lazy))
++ return false;
/* All work should have been flushed before going offline */
WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
-@@ -132,7 +162,9 @@
+@@ -132,7 +144,7 @@
struct irq_work *work;
struct llist_node *llnode;
-+#ifndef CONFIG_PREEMPT_RT_FULL
- BUG_ON(!irqs_disabled());
-+#endif
+- BUG_ON(!irqs_disabled());
++ BUG_ON(!IS_ENABLED(CONFIG_PREEMPT_RT_FULL) && !irqs_disabled());
if (llist_empty(list))
return;
-@@ -168,18 +200,26 @@
- */
+@@ -169,17 +181,26 @@
void irq_work_run(void)
{
-+#ifdef CONFIG_PREEMPT_RT_FULL
-+ irq_work_run_list(this_cpu_ptr(&hirq_work_list));
-+#else
irq_work_run_list(this_cpu_ptr(&raised_list));
- irq_work_run_list(this_cpu_ptr(&lazy_list));
-+#endif
+- irq_work_run_list(this_cpu_ptr(&lazy_list));
++ if (IS_ENABLED(CONFIG_PREEMPT_RT_FULL)) {
++ /*
++ * NOTE: we raise softirq via IPI for safety,
++ * and execute in irq_work_tick() to move the
++ * overhead from hard to soft irq context.
++ */
++ if (!llist_empty(this_cpu_ptr(&lazy_list)))
++ raise_softirq(TIMER_SOFTIRQ);
++ } else
++ irq_work_run_list(this_cpu_ptr(&lazy_list));
}
EXPORT_SYMBOL_GPL(irq_work_run);
void irq_work_tick(void)
{
-+#ifdef CONFIG_PREEMPT_RT_FULL
-+ irq_work_run_list(this_cpu_ptr(&lazy_list));
-+#else
- struct llist_head *raised = &__get_cpu_var(raised_list);
+- struct llist_head *raised = &__get_cpu_var(raised_list);
++ struct llist_head *raised = this_cpu_ptr(&raised_list);
if (!llist_empty(raised) && !arch_irq_work_has_interrupt())
irq_work_run_list(raised);
- irq_work_run_list(&__get_cpu_var(lazy_list));
-+#endif
+- irq_work_run_list(&__get_cpu_var(lazy_list));
++ irq_work_run_list(this_cpu_ptr(&lazy_list));
}
/*
-diff -Nur linux-3.18.12.orig/kernel/Kconfig.locks linux-3.18.12/kernel/Kconfig.locks
---- linux-3.18.12.orig/kernel/Kconfig.locks 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/Kconfig.locks 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/Kconfig.locks linux-3.18.14-rt/kernel/Kconfig.locks
+--- linux-3.18.14.orig/kernel/Kconfig.locks 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/Kconfig.locks 2015-05-31 15:32:48.585635365 -0500
@@ -225,11 +225,11 @@
config MUTEX_SPIN_ON_OWNER
@@ -20816,9 +20586,9 @@ diff -Nur linux-3.18.12.orig/kernel/Kconfig.locks linux-3.18.12/kernel/Kconfig.l
config ARCH_USE_QUEUE_RWLOCK
bool
-diff -Nur linux-3.18.12.orig/kernel/Kconfig.preempt linux-3.18.12/kernel/Kconfig.preempt
---- linux-3.18.12.orig/kernel/Kconfig.preempt 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/Kconfig.preempt 2015-04-26 13:32:22.431684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/Kconfig.preempt linux-3.18.14-rt/kernel/Kconfig.preempt
+--- linux-3.18.14.orig/kernel/Kconfig.preempt 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/Kconfig.preempt 2015-05-31 15:32:48.589635366 -0500
@@ -1,3 +1,16 @@
+config PREEMPT
+ bool
@@ -20871,9 +20641,9 @@ diff -Nur linux-3.18.12.orig/kernel/Kconfig.preempt linux-3.18.12/kernel/Kconfig
endchoice
config PREEMPT_COUNT
-diff -Nur linux-3.18.12.orig/kernel/ksysfs.c linux-3.18.12/kernel/ksysfs.c
---- linux-3.18.12.orig/kernel/ksysfs.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/ksysfs.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/ksysfs.c linux-3.18.14-rt/kernel/ksysfs.c
+--- linux-3.18.14.orig/kernel/ksysfs.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/ksysfs.c 2015-05-31 15:32:48.733635364 -0500
@@ -136,6 +136,15 @@
#endif /* CONFIG_KEXEC */
@@ -20900,9 +20670,9 @@ diff -Nur linux-3.18.12.orig/kernel/ksysfs.c linux-3.18.12/kernel/ksysfs.c
NULL
};
-diff -Nur linux-3.18.12.orig/kernel/locking/lglock.c linux-3.18.12/kernel/locking/lglock.c
---- linux-3.18.12.orig/kernel/locking/lglock.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/lglock.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/lglock.c linux-3.18.14-rt/kernel/locking/lglock.c
+--- linux-3.18.14.orig/kernel/locking/lglock.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/lglock.c 2015-05-31 15:32:48.749635364 -0500
@@ -4,6 +4,15 @@
#include <linux/cpu.h>
#include <linux/string.h>
@@ -21047,9 +20817,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/lglock.c linux-3.18.12/kernel/lockin
+ }
+}
+#endif
-diff -Nur linux-3.18.12.orig/kernel/locking/lockdep.c linux-3.18.12/kernel/locking/lockdep.c
---- linux-3.18.12.orig/kernel/locking/lockdep.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/lockdep.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/lockdep.c linux-3.18.14-rt/kernel/locking/lockdep.c
+--- linux-3.18.14.orig/kernel/locking/lockdep.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/lockdep.c 2015-05-31 15:32:48.749635364 -0500
@@ -3542,6 +3542,7 @@
}
}
@@ -21066,9 +20836,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/lockdep.c linux-3.18.12/kernel/locki
if (!debug_locks)
print_irqtrace_events(current);
-diff -Nur linux-3.18.12.orig/kernel/locking/Makefile linux-3.18.12/kernel/locking/Makefile
---- linux-3.18.12.orig/kernel/locking/Makefile 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/Makefile 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/Makefile linux-3.18.14-rt/kernel/locking/Makefile
+--- linux-3.18.14.orig/kernel/locking/Makefile 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/Makefile 2015-05-31 15:32:48.737635364 -0500
@@ -1,5 +1,5 @@
-obj-y += mutex.o semaphore.o rwsem.o mcs_spinlock.o
@@ -21100,9 +20870,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/Makefile linux-3.18.12/kernel/lockin
+obj-$(CONFIG_PREEMPT_RT_FULL) += rt.o
obj-$(CONFIG_QUEUE_RWLOCK) += qrwlock.o
obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
-diff -Nur linux-3.18.12.orig/kernel/locking/percpu-rwsem.c linux-3.18.12/kernel/locking/percpu-rwsem.c
---- linux-3.18.12.orig/kernel/locking/percpu-rwsem.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/percpu-rwsem.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/percpu-rwsem.c linux-3.18.14-rt/kernel/locking/percpu-rwsem.c
+--- linux-3.18.14.orig/kernel/locking/percpu-rwsem.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/percpu-rwsem.c 2015-05-31 15:32:48.757635364 -0500
@@ -84,8 +84,12 @@
down_read(&brw->rw_sem);
@@ -21116,9 +20886,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/percpu-rwsem.c linux-3.18.12/kernel/
}
void percpu_up_read(struct percpu_rw_semaphore *brw)
-diff -Nur linux-3.18.12.orig/kernel/locking/rt.c linux-3.18.12/kernel/locking/rt.c
---- linux-3.18.12.orig/kernel/locking/rt.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/kernel/locking/rt.c 2015-04-26 13:32:22.435684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/rt.c linux-3.18.14-rt/kernel/locking/rt.c
+--- linux-3.18.14.orig/kernel/locking/rt.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/kernel/locking/rt.c 2015-05-31 15:32:48.757635364 -0500
@@ -0,0 +1,456 @@
+/*
+ * kernel/rt.c
@@ -21576,9 +21346,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/rt.c linux-3.18.12/kernel/locking/rt
+ return 1;
+}
+EXPORT_SYMBOL(atomic_dec_and_mutex_lock);
-diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex.c linux-3.18.12/kernel/locking/rtmutex.c
---- linux-3.18.12.orig/kernel/locking/rtmutex.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/rtmutex.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/rtmutex.c linux-3.18.14-rt/kernel/locking/rtmutex.c
+--- linux-3.18.14.orig/kernel/locking/rtmutex.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/rtmutex.c 2015-05-31 15:32:48.769635364 -0500
@@ -7,6 +7,11 @@
* Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
* Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt
@@ -22608,9 +22378,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex.c linux-3.18.12/kernel/locki
+}
+EXPORT_SYMBOL(ww_mutex_unlock);
+#endif
-diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex_common.h linux-3.18.12/kernel/locking/rtmutex_common.h
---- linux-3.18.12.orig/kernel/locking/rtmutex_common.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/rtmutex_common.h 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/rtmutex_common.h linux-3.18.14-rt/kernel/locking/rtmutex_common.h
+--- linux-3.18.14.orig/kernel/locking/rtmutex_common.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/rtmutex_common.h 2015-05-31 15:32:48.769635364 -0500
@@ -49,6 +49,7 @@
struct rb_node pi_tree_entry;
struct task_struct *task;
@@ -22644,9 +22414,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex_common.h linux-3.18.12/kerne
+}
+
#endif
-diff -Nur linux-3.18.12.orig/kernel/locking/spinlock.c linux-3.18.12/kernel/locking/spinlock.c
---- linux-3.18.12.orig/kernel/locking/spinlock.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/spinlock.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/spinlock.c linux-3.18.14-rt/kernel/locking/spinlock.c
+--- linux-3.18.14.orig/kernel/locking/spinlock.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/spinlock.c 2015-05-31 15:32:48.769635364 -0500
@@ -124,8 +124,11 @@
* __[spin|read|write]_lock_bh()
*/
@@ -22677,9 +22447,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/spinlock.c linux-3.18.12/kernel/lock
#ifdef CONFIG_DEBUG_LOCK_ALLOC
void __lockfunc _raw_spin_lock_nested(raw_spinlock_t *lock, int subclass)
-diff -Nur linux-3.18.12.orig/kernel/locking/spinlock_debug.c linux-3.18.12/kernel/locking/spinlock_debug.c
---- linux-3.18.12.orig/kernel/locking/spinlock_debug.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/locking/spinlock_debug.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/locking/spinlock_debug.c linux-3.18.14-rt/kernel/locking/spinlock_debug.c
+--- linux-3.18.14.orig/kernel/locking/spinlock_debug.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/locking/spinlock_debug.c 2015-05-31 15:32:48.793635364 -0500
@@ -31,6 +31,7 @@
EXPORT_SYMBOL(__raw_spin_lock_init);
@@ -22710,9 +22480,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/spinlock_debug.c linux-3.18.12/kerne
}
+
+#endif
-diff -Nur linux-3.18.12.orig/kernel/panic.c linux-3.18.12/kernel/panic.c
---- linux-3.18.12.orig/kernel/panic.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/panic.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/panic.c linux-3.18.14-rt/kernel/panic.c
+--- linux-3.18.14.orig/kernel/panic.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/panic.c 2015-05-31 15:32:48.793635364 -0500
@@ -384,9 +384,11 @@
static int init_oops_id(void)
@@ -22725,9 +22495,9 @@ diff -Nur linux-3.18.12.orig/kernel/panic.c linux-3.18.12/kernel/panic.c
oops_id++;
return 0;
-diff -Nur linux-3.18.12.orig/kernel/power/hibernate.c linux-3.18.12/kernel/power/hibernate.c
---- linux-3.18.12.orig/kernel/power/hibernate.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/power/hibernate.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/power/hibernate.c linux-3.18.14-rt/kernel/power/hibernate.c
+--- linux-3.18.14.orig/kernel/power/hibernate.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/power/hibernate.c 2015-05-31 15:32:48.797635364 -0500
@@ -287,6 +287,8 @@
local_irq_disable();
@@ -22777,9 +22547,9 @@ diff -Nur linux-3.18.12.orig/kernel/power/hibernate.c linux-3.18.12/kernel/power
local_irq_enable();
enable_nonboot_cpus();
-diff -Nur linux-3.18.12.orig/kernel/power/suspend.c linux-3.18.12/kernel/power/suspend.c
---- linux-3.18.12.orig/kernel/power/suspend.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/power/suspend.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/power/suspend.c linux-3.18.14-rt/kernel/power/suspend.c
+--- linux-3.18.14.orig/kernel/power/suspend.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/power/suspend.c 2015-05-31 15:32:48.797635364 -0500
@@ -318,6 +318,8 @@
arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());
@@ -22798,9 +22568,9 @@ diff -Nur linux-3.18.12.orig/kernel/power/suspend.c linux-3.18.12/kernel/power/s
arch_suspend_enable_irqs();
BUG_ON(irqs_disabled());
-diff -Nur linux-3.18.12.orig/kernel/printk/printk.c linux-3.18.12/kernel/printk/printk.c
---- linux-3.18.12.orig/kernel/printk/printk.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/printk/printk.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/printk/printk.c linux-3.18.14-rt/kernel/printk/printk.c
+--- linux-3.18.14.orig/kernel/printk/printk.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/printk/printk.c 2015-05-31 15:32:48.801635363 -0500
@@ -1165,6 +1165,7 @@
{
char *text;
@@ -23056,9 +22826,9 @@ diff -Nur linux-3.18.12.orig/kernel/printk/printk.c linux-3.18.12/kernel/printk/
}
console_locked = 0;
-diff -Nur linux-3.18.12.orig/kernel/ptrace.c linux-3.18.12/kernel/ptrace.c
---- linux-3.18.12.orig/kernel/ptrace.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/ptrace.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/ptrace.c linux-3.18.14-rt/kernel/ptrace.c
+--- linux-3.18.14.orig/kernel/ptrace.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/ptrace.c 2015-05-31 15:32:48.801635363 -0500
@@ -129,7 +129,12 @@
spin_lock_irq(&task->sighand->siglock);
@@ -23073,9 +22843,9 @@ diff -Nur linux-3.18.12.orig/kernel/ptrace.c linux-3.18.12/kernel/ptrace.c
ret = true;
}
spin_unlock_irq(&task->sighand->siglock);
-diff -Nur linux-3.18.12.orig/kernel/rcu/tiny.c linux-3.18.12/kernel/rcu/tiny.c
---- linux-3.18.12.orig/kernel/rcu/tiny.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/rcu/tiny.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/rcu/tiny.c linux-3.18.14-rt/kernel/rcu/tiny.c
+--- linux-3.18.14.orig/kernel/rcu/tiny.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/rcu/tiny.c 2015-05-31 15:32:48.801635363 -0500
@@ -370,6 +370,7 @@
}
EXPORT_SYMBOL_GPL(call_rcu_sched);
@@ -23092,9 +22862,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tiny.c linux-3.18.12/kernel/rcu/tiny.c
void rcu_init(void)
{
-diff -Nur linux-3.18.12.orig/kernel/rcu/tree.c linux-3.18.12/kernel/rcu/tree.c
---- linux-3.18.12.orig/kernel/rcu/tree.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/rcu/tree.c 2015-04-26 13:32:22.439684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/rcu/tree.c linux-3.18.14-rt/kernel/rcu/tree.c
+--- linux-3.18.14.orig/kernel/rcu/tree.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/rcu/tree.c 2015-05-31 15:32:48.805635363 -0500
@@ -56,6 +56,11 @@
#include <linux/random.h>
#include <linux/ftrace_event.h>
@@ -23397,9 +23167,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tree.c linux-3.18.12/kernel/rcu/tree.c
/*
* We don't need protection against CPU-hotplug here because
-diff -Nur linux-3.18.12.orig/kernel/rcu/tree.h linux-3.18.12/kernel/rcu/tree.h
---- linux-3.18.12.orig/kernel/rcu/tree.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/rcu/tree.h 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/rcu/tree.h linux-3.18.14-rt/kernel/rcu/tree.h
+--- linux-3.18.14.orig/kernel/rcu/tree.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/rcu/tree.h 2015-05-31 15:32:48.809635364 -0500
@@ -28,6 +28,7 @@
#include <linux/cpumask.h>
#include <linux/seqlock.h>
@@ -23459,9 +23229,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tree.h linux-3.18.12/kernel/rcu/tree.h
static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
struct rcu_node *rnp);
#endif /* #ifdef CONFIG_RCU_BOOST */
-diff -Nur linux-3.18.12.orig/kernel/rcu/tree_plugin.h linux-3.18.12/kernel/rcu/tree_plugin.h
---- linux-3.18.12.orig/kernel/rcu/tree_plugin.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/rcu/tree_plugin.h 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/rcu/tree_plugin.h linux-3.18.14-rt/kernel/rcu/tree_plugin.h
+--- linux-3.18.14.orig/kernel/rcu/tree_plugin.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/rcu/tree_plugin.h 2015-05-31 15:32:48.829635363 -0500
@@ -24,12 +24,6 @@
* Paul E. McKenney <paulmck@linux.vnet.ibm.com>
*/
@@ -23807,9 +23577,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tree_plugin.h linux-3.18.12/kernel/rcu/t
rdp->nocb_follower_tail = &rdp->nocb_follower_head;
}
-diff -Nur linux-3.18.12.orig/kernel/rcu/update.c linux-3.18.12/kernel/rcu/update.c
---- linux-3.18.12.orig/kernel/rcu/update.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/rcu/update.c 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/rcu/update.c linux-3.18.14-rt/kernel/rcu/update.c
+--- linux-3.18.14.orig/kernel/rcu/update.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/rcu/update.c 2015-05-31 15:32:48.829635363 -0500
@@ -170,6 +170,7 @@
}
EXPORT_SYMBOL_GPL(rcu_read_lock_held);
@@ -23826,9 +23596,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/update.c linux-3.18.12/kernel/rcu/update
#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
-diff -Nur linux-3.18.12.orig/kernel/relay.c linux-3.18.12/kernel/relay.c
---- linux-3.18.12.orig/kernel/relay.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/relay.c 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/relay.c linux-3.18.14-rt/kernel/relay.c
+--- linux-3.18.14.orig/kernel/relay.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/relay.c 2015-05-31 15:32:48.829635363 -0500
@@ -339,6 +339,10 @@
{
struct rchan_buf *buf = (struct rchan_buf *)data;
@@ -23864,9 +23634,9 @@ diff -Nur linux-3.18.12.orig/kernel/relay.c linux-3.18.12/kernel/relay.c
}
old = buf->data;
-diff -Nur linux-3.18.12.orig/kernel/res_counter.c linux-3.18.12/kernel/res_counter.c
---- linux-3.18.12.orig/kernel/res_counter.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/res_counter.c 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/res_counter.c linux-3.18.14-rt/kernel/res_counter.c
+--- linux-3.18.14.orig/kernel/res_counter.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/res_counter.c 2015-05-31 15:32:48.845635363 -0500
@@ -59,7 +59,7 @@
r = ret = 0;
@@ -23903,9 +23673,9 @@ diff -Nur linux-3.18.12.orig/kernel/res_counter.c linux-3.18.12/kernel/res_count
return ret;
}
-diff -Nur linux-3.18.12.orig/kernel/sched/completion.c linux-3.18.12/kernel/sched/completion.c
---- linux-3.18.12.orig/kernel/sched/completion.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/completion.c 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/completion.c linux-3.18.14-rt/kernel/sched/completion.c
+--- linux-3.18.14.orig/kernel/sched/completion.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/completion.c 2015-05-31 15:32:48.889635363 -0500
@@ -30,10 +30,10 @@
{
unsigned long flags;
@@ -24000,9 +23770,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/completion.c linux-3.18.12/kernel/sche
return ret;
}
EXPORT_SYMBOL(completion_done);
-diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core.c
---- linux-3.18.12.orig/kernel/sched/core.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/core.c 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/core.c linux-3.18.14-rt/kernel/sched/core.c
+--- linux-3.18.14.orig/kernel/sched/core.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/core.c 2015-05-31 15:32:48.893635363 -0500
@@ -280,7 +280,11 @@
* Number of tasks to iterate in a single balance run.
* Limited because this is done with IRQs disabled.
@@ -24529,16 +24299,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
__preempt_count_sub(PREEMPT_ACTIVE);
/*
-@@ -3097,6 +3316,8 @@
- } else {
- if (dl_prio(oldprio))
- p->dl.dl_boosted = 0;
-+ if (rt_prio(oldprio))
-+ p->rt.timeout = 0;
- p->sched_class = &fair_sched_class;
- }
-
-@@ -4234,9 +4455,16 @@
+@@ -4236,9 +4455,16 @@
static void __cond_resched(void)
{
@@ -24558,7 +24319,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
}
int __sched _cond_resched(void)
-@@ -4277,6 +4505,7 @@
+@@ -4279,6 +4505,7 @@
}
EXPORT_SYMBOL(__cond_resched_lock);
@@ -24566,7 +24327,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
int __sched __cond_resched_softirq(void)
{
BUG_ON(!in_softirq());
-@@ -4290,6 +4519,7 @@
+@@ -4292,6 +4519,7 @@
return 0;
}
EXPORT_SYMBOL(__cond_resched_softirq);
@@ -24574,7 +24335,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
/**
* yield - yield the current processor to other threads.
-@@ -4651,7 +4881,9 @@
+@@ -4653,7 +4881,9 @@
/* Set the preempt count _outside_ the spinlocks! */
init_idle_preempt_count(idle, cpu);
@@ -24585,7 +24346,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
/*
* The idle tasks have their own, simple scheduling class:
*/
-@@ -4693,11 +4925,91 @@
+@@ -4695,11 +4925,91 @@
void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
{
@@ -24680,7 +24441,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
}
/*
-@@ -4743,7 +5055,7 @@
+@@ -4745,7 +5055,7 @@
do_set_cpus_allowed(p, new_mask);
/* Can the task run on the task's current CPU? If so, we're done */
@@ -24689,7 +24450,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
goto out;
dest_cpu = cpumask_any_and(cpu_active_mask, new_mask);
-@@ -4883,6 +5195,8 @@
+@@ -4885,6 +5195,8 @@
#ifdef CONFIG_HOTPLUG_CPU
@@ -24698,7 +24459,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
/*
* Ensures that the idle task is using init_mm right before its cpu goes
* offline.
-@@ -4897,7 +5211,11 @@
+@@ -4899,7 +5211,11 @@
switch_mm(mm, &init_mm, current);
finish_arch_post_lock_switch();
}
@@ -24711,7 +24472,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
}
/*
-@@ -5240,6 +5558,10 @@
+@@ -5242,6 +5558,10 @@
case CPU_DEAD:
calc_load_migrate(rq);
@@ -24722,7 +24483,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
break;
#endif
}
-@@ -7181,7 +7503,8 @@
+@@ -7183,7 +7503,8 @@
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
static inline int preempt_count_equals(int preempt_offset)
{
@@ -24732,9 +24493,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core
return (nested == preempt_offset);
}
-diff -Nur linux-3.18.12.orig/kernel/sched/cputime.c linux-3.18.12/kernel/sched/cputime.c
---- linux-3.18.12.orig/kernel/sched/cputime.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/cputime.c 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/cputime.c linux-3.18.14-rt/kernel/sched/cputime.c
+--- linux-3.18.14.orig/kernel/sched/cputime.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/cputime.c 2015-05-31 15:32:48.893635363 -0500
@@ -675,37 +675,45 @@
void vtime_account_system(struct task_struct *tsk)
@@ -24888,9 +24649,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/cputime.c linux-3.18.12/kernel/sched/c
}
-diff -Nur linux-3.18.12.orig/kernel/sched/deadline.c linux-3.18.12/kernel/sched/deadline.c
---- linux-3.18.12.orig/kernel/sched/deadline.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/deadline.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/deadline.c linux-3.18.14-rt/kernel/sched/deadline.c
+--- linux-3.18.14.orig/kernel/sched/deadline.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/deadline.c 2015-05-31 15:32:48.893635363 -0500
@@ -570,6 +570,7 @@
hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -24899,9 +24660,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/deadline.c linux-3.18.12/kernel/sched/
}
static
-diff -Nur linux-3.18.12.orig/kernel/sched/debug.c linux-3.18.12/kernel/sched/debug.c
---- linux-3.18.12.orig/kernel/sched/debug.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/debug.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/debug.c linux-3.18.14-rt/kernel/sched/debug.c
+--- linux-3.18.14.orig/kernel/sched/debug.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/debug.c 2015-05-31 15:32:48.897635363 -0500
@@ -256,6 +256,9 @@
P(rt_throttled);
PN(rt_time);
@@ -24923,9 +24684,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/debug.c linux-3.18.12/kernel/sched/deb
#undef PN
#undef __PN
#undef P
-diff -Nur linux-3.18.12.orig/kernel/sched/fair.c linux-3.18.12/kernel/sched/fair.c
---- linux-3.18.12.orig/kernel/sched/fair.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/fair.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/fair.c linux-3.18.14-rt/kernel/sched/fair.c
+--- linux-3.18.14.orig/kernel/sched/fair.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/fair.c 2015-05-31 15:32:48.897635363 -0500
@@ -2951,7 +2951,7 @@
ideal_runtime = sched_slice(cfs_rq, curr);
delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
@@ -24998,9 +24759,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/fair.c linux-3.18.12/kernel/sched/fair
} else
check_preempt_curr(rq, p, 0);
}
-diff -Nur linux-3.18.12.orig/kernel/sched/features.h linux-3.18.12/kernel/sched/features.h
---- linux-3.18.12.orig/kernel/sched/features.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/features.h 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/features.h linux-3.18.14-rt/kernel/sched/features.h
+--- linux-3.18.14.orig/kernel/sched/features.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/features.h 2015-05-31 15:32:48.897635363 -0500
@@ -50,12 +50,18 @@
*/
SCHED_FEAT(NONTASK_CAPACITY, true)
@@ -25021,9 +24782,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/features.h linux-3.18.12/kernel/sched/
SCHED_FEAT(FORCE_SD_OVERLAP, false)
SCHED_FEAT(RT_RUNTIME_SHARE, true)
SCHED_FEAT(LB_MIN, false)
-diff -Nur linux-3.18.12.orig/kernel/sched/Makefile linux-3.18.12/kernel/sched/Makefile
---- linux-3.18.12.orig/kernel/sched/Makefile 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/Makefile 2015-04-26 13:32:22.443684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/Makefile linux-3.18.14-rt/kernel/sched/Makefile
+--- linux-3.18.14.orig/kernel/sched/Makefile 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/Makefile 2015-05-31 15:32:48.861635363 -0500
@@ -13,7 +13,7 @@
obj-y += core.o proc.o clock.o cputime.o
@@ -25033,9 +24794,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/Makefile linux-3.18.12/kernel/sched/Ma
obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
-diff -Nur linux-3.18.12.orig/kernel/sched/rt.c linux-3.18.12/kernel/sched/rt.c
---- linux-3.18.12.orig/kernel/sched/rt.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/rt.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/rt.c linux-3.18.14-rt/kernel/sched/rt.c
+--- linux-3.18.14.orig/kernel/sched/rt.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/rt.c 2015-05-31 15:32:48.897635363 -0500
@@ -43,6 +43,7 @@
hrtimer_init(&rt_b->rt_period_timer,
@@ -25044,9 +24805,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/rt.c linux-3.18.12/kernel/sched/rt.c
rt_b->rt_period_timer.function = sched_rt_period_timer;
}
-diff -Nur linux-3.18.12.orig/kernel/sched/sched.h linux-3.18.12/kernel/sched/sched.h
---- linux-3.18.12.orig/kernel/sched/sched.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/sched/sched.h 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/sched.h linux-3.18.14-rt/kernel/sched/sched.h
+--- linux-3.18.14.orig/kernel/sched/sched.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/sched/sched.h 2015-05-31 15:32:48.897635363 -0500
@@ -1018,6 +1018,7 @@
#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */
#define WF_FORK 0x02 /* child wakeup after fork */
@@ -25071,9 +24832,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/sched.h linux-3.18.12/kernel/sched/sch
extern struct rt_bandwidth def_rt_bandwidth;
extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
-diff -Nur linux-3.18.12.orig/kernel/sched/wait-simple.c linux-3.18.12/kernel/sched/wait-simple.c
---- linux-3.18.12.orig/kernel/sched/wait-simple.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/kernel/sched/wait-simple.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/wait-simple.c linux-3.18.14-rt/kernel/sched/wait-simple.c
+--- linux-3.18.14.orig/kernel/sched/wait-simple.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/kernel/sched/wait-simple.c 2015-05-31 15:32:48.897635363 -0500
@@ -0,0 +1,115 @@
+/*
+ * Simple waitqueues without fancy flags and callbacks
@@ -25190,9 +24951,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/wait-simple.c linux-3.18.12/kernel/sch
+ return woken;
+}
+EXPORT_SYMBOL(__swait_wake);
-diff -Nur linux-3.18.12.orig/kernel/sched/work-simple.c linux-3.18.12/kernel/sched/work-simple.c
---- linux-3.18.12.orig/kernel/sched/work-simple.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/kernel/sched/work-simple.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/sched/work-simple.c linux-3.18.14-rt/kernel/sched/work-simple.c
+--- linux-3.18.14.orig/kernel/sched/work-simple.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/kernel/sched/work-simple.c 2015-05-31 15:32:48.901635363 -0500
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 BMW Car IT GmbH, Daniel Wagner daniel.wagner@bmw-carit.de
@@ -25366,9 +25127,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/work-simple.c linux-3.18.12/kernel/sch
+ mutex_unlock(&worker_mutex);
+}
+EXPORT_SYMBOL_GPL(swork_put);
-diff -Nur linux-3.18.12.orig/kernel/signal.c linux-3.18.12/kernel/signal.c
---- linux-3.18.12.orig/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/signal.c 2015-04-26 13:32:22.447684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/signal.c linux-3.18.14-rt/kernel/signal.c
+--- linux-3.18.14.orig/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/signal.c 2015-05-31 15:32:48.921635363 -0500
@@ -14,6 +14,7 @@
#include <linux/export.h>
#include <linux/init.h>
@@ -25613,9 +25374,9 @@ diff -Nur linux-3.18.12.orig/kernel/signal.c linux-3.18.12/kernel/signal.c
freezable_schedule();
} else {
/*
-diff -Nur linux-3.18.12.orig/kernel/softirq.c linux-3.18.12/kernel/softirq.c
---- linux-3.18.12.orig/kernel/softirq.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/softirq.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/softirq.c linux-3.18.14-rt/kernel/softirq.c
+--- linux-3.18.14.orig/kernel/softirq.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/softirq.c 2015-05-31 15:32:48.921635363 -0500
@@ -21,10 +21,12 @@
#include <linux/freezer.h>
#include <linux/kthread.h>
@@ -26507,9 +26268,9 @@ diff -Nur linux-3.18.12.orig/kernel/softirq.c linux-3.18.12/kernel/softirq.c
.thread_should_run = ksoftirqd_should_run,
.thread_fn = run_ksoftirqd,
.thread_comm = "ksoftirqd/%u",
-diff -Nur linux-3.18.12.orig/kernel/stop_machine.c linux-3.18.12/kernel/stop_machine.c
---- linux-3.18.12.orig/kernel/stop_machine.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/stop_machine.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/stop_machine.c linux-3.18.14-rt/kernel/stop_machine.c
+--- linux-3.18.14.orig/kernel/stop_machine.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/stop_machine.c 2015-05-31 15:32:48.925635362 -0500
@@ -30,12 +30,12 @@
atomic_t nr_todo; /* nr left to execute */
bool executed; /* actually executed? */
@@ -26770,9 +26531,9 @@ diff -Nur linux-3.18.12.orig/kernel/stop_machine.c linux-3.18.12/kernel/stop_mac
cpu_relax();
mutex_unlock(&stop_cpus_mutex);
-diff -Nur linux-3.18.12.orig/kernel/time/hrtimer.c linux-3.18.12/kernel/time/hrtimer.c
---- linux-3.18.12.orig/kernel/time/hrtimer.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/hrtimer.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/hrtimer.c linux-3.18.14-rt/kernel/time/hrtimer.c
+--- linux-3.18.14.orig/kernel/time/hrtimer.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/hrtimer.c 2015-05-31 15:32:48.925635362 -0500
@@ -48,11 +48,13 @@
#include <linux/sched/rt.h>
#include <linux/sched/deadline.h>
@@ -27377,9 +27138,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/hrtimer.c linux-3.18.12/kernel/time/hrt
}
/**
-diff -Nur linux-3.18.12.orig/kernel/time/itimer.c linux-3.18.12/kernel/time/itimer.c
---- linux-3.18.12.orig/kernel/time/itimer.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/itimer.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/itimer.c linux-3.18.14-rt/kernel/time/itimer.c
+--- linux-3.18.14.orig/kernel/time/itimer.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/itimer.c 2015-05-31 15:32:48.957635362 -0500
@@ -213,6 +213,7 @@
/* We are sharing ->siglock with it_real_fn() */
if (hrtimer_try_to_cancel(timer) < 0) {
@@ -27388,9 +27149,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/itimer.c linux-3.18.12/kernel/time/itim
goto again;
}
expires = timeval_to_ktime(value->it_value);
-diff -Nur linux-3.18.12.orig/kernel/time/jiffies.c linux-3.18.12/kernel/time/jiffies.c
---- linux-3.18.12.orig/kernel/time/jiffies.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/jiffies.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/jiffies.c linux-3.18.14-rt/kernel/time/jiffies.c
+--- linux-3.18.14.orig/kernel/time/jiffies.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/jiffies.c 2015-05-31 15:32:48.957635362 -0500
@@ -73,7 +73,8 @@
.shift = JIFFIES_SHIFT,
};
@@ -27413,9 +27174,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/jiffies.c linux-3.18.12/kernel/time/jif
return ret;
}
EXPORT_SYMBOL(get_jiffies_64);
-diff -Nur linux-3.18.12.orig/kernel/time/ntp.c linux-3.18.12/kernel/time/ntp.c
---- linux-3.18.12.orig/kernel/time/ntp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/ntp.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/ntp.c linux-3.18.14-rt/kernel/time/ntp.c
+--- linux-3.18.14.orig/kernel/time/ntp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/ntp.c 2015-05-31 15:32:48.957635362 -0500
@@ -10,6 +10,7 @@
#include <linux/workqueue.h>
#include <linux/hrtimer.h>
@@ -27477,9 +27238,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/ntp.c linux-3.18.12/kernel/time/ntp.c
#else
void ntp_notify_cmos_timer(void) { }
-diff -Nur linux-3.18.12.orig/kernel/time/posix-cpu-timers.c linux-3.18.12/kernel/time/posix-cpu-timers.c
---- linux-3.18.12.orig/kernel/time/posix-cpu-timers.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/posix-cpu-timers.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/posix-cpu-timers.c linux-3.18.14-rt/kernel/time/posix-cpu-timers.c
+--- linux-3.18.14.orig/kernel/time/posix-cpu-timers.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/posix-cpu-timers.c 2015-05-31 15:32:48.961635362 -0500
@@ -3,6 +3,7 @@
*/
@@ -27727,9 +27488,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/posix-cpu-timers.c linux-3.18.12/kernel
/*
* Set one of the process-wide special case CPU timers or RLIMIT_CPU.
* The tsk->sighand->siglock must be held by the caller.
-diff -Nur linux-3.18.12.orig/kernel/time/posix-timers.c linux-3.18.12/kernel/time/posix-timers.c
---- linux-3.18.12.orig/kernel/time/posix-timers.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/posix-timers.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/posix-timers.c linux-3.18.14-rt/kernel/time/posix-timers.c
+--- linux-3.18.14.orig/kernel/time/posix-timers.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/posix-timers.c 2015-05-31 15:32:48.961635362 -0500
@@ -499,6 +499,7 @@
static struct pid *good_sigevent(sigevent_t * event)
{
@@ -27825,9 +27586,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/posix-timers.c linux-3.18.12/kernel/tim
goto retry_delete;
}
list_del(&timer->list);
-diff -Nur linux-3.18.12.orig/kernel/time/tick-common.c linux-3.18.12/kernel/time/tick-common.c
---- linux-3.18.12.orig/kernel/time/tick-common.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/tick-common.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/tick-common.c linux-3.18.14-rt/kernel/time/tick-common.c
+--- linux-3.18.14.orig/kernel/time/tick-common.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/tick-common.c 2015-05-31 15:32:48.961635362 -0500
@@ -78,13 +78,15 @@
static void tick_periodic(int cpu)
{
@@ -27858,9 +27619,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/tick-common.c linux-3.18.12/kernel/time
clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
-diff -Nur linux-3.18.12.orig/kernel/time/tick-internal.h linux-3.18.12/kernel/time/tick-internal.h
---- linux-3.18.12.orig/kernel/time/tick-internal.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/tick-internal.h 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/tick-internal.h linux-3.18.14-rt/kernel/time/tick-internal.h
+--- linux-3.18.14.orig/kernel/time/tick-internal.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/tick-internal.h 2015-05-31 15:32:48.961635362 -0500
@@ -6,7 +6,8 @@
#include "timekeeping.h"
@@ -27871,9 +27632,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/tick-internal.h linux-3.18.12/kernel/ti
#define CS_NAME_LEN 32
-diff -Nur linux-3.18.12.orig/kernel/time/tick-sched.c linux-3.18.12/kernel/time/tick-sched.c
---- linux-3.18.12.orig/kernel/time/tick-sched.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/tick-sched.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/tick-sched.c linux-3.18.14-rt/kernel/time/tick-sched.c
+--- linux-3.18.14.orig/kernel/time/tick-sched.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/tick-sched.c 2015-05-31 15:32:48.961635362 -0500
@@ -62,7 +62,8 @@
return;
@@ -27983,9 +27744,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/tick-sched.c linux-3.18.12/kernel/time/
ts->sched_timer.function = tick_sched_timer;
/* Get the next period (per cpu) */
-diff -Nur linux-3.18.12.orig/kernel/time/timekeeping.c linux-3.18.12/kernel/time/timekeeping.c
---- linux-3.18.12.orig/kernel/time/timekeeping.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/timekeeping.c 2015-04-26 13:32:22.451684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/timekeeping.c linux-3.18.14-rt/kernel/time/timekeeping.c
+--- linux-3.18.14.orig/kernel/time/timekeeping.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/timekeeping.c 2015-05-31 15:32:48.969635362 -0500
@@ -1814,8 +1814,10 @@
*/
void xtime_update(unsigned long ticks)
@@ -27999,9 +27760,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/timekeeping.c linux-3.18.12/kernel/time
+ raw_spin_unlock(&jiffies_lock);
update_wall_time();
}
-diff -Nur linux-3.18.12.orig/kernel/time/timer.c linux-3.18.12/kernel/time/timer.c
---- linux-3.18.12.orig/kernel/time/timer.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/time/timer.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/time/timer.c linux-3.18.14-rt/kernel/time/timer.c
+--- linux-3.18.14.orig/kernel/time/timer.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/time/timer.c 2015-05-31 15:32:48.973635362 -0500
@@ -78,6 +78,9 @@
struct tvec_base {
spinlock_t lock;
@@ -28223,9 +27984,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/timer.c linux-3.18.12/kernel/time/timer
}
#endif /* CONFIG_HOTPLUG_CPU */
-diff -Nur linux-3.18.12.orig/kernel/trace/Kconfig linux-3.18.12/kernel/trace/Kconfig
---- linux-3.18.12.orig/kernel/trace/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/Kconfig 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/Kconfig linux-3.18.14-rt/kernel/trace/Kconfig
+--- linux-3.18.14.orig/kernel/trace/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/Kconfig 2015-05-31 15:32:48.973635362 -0500
@@ -187,6 +187,24 @@
enabled. This option and the preempt-off timing option can be
used together or separately.)
@@ -28351,9 +28112,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/Kconfig linux-3.18.12/kernel/trace/Kco
config ENABLE_DEFAULT_TRACERS
bool "Trace process context switches and events"
depends on !GENERIC_TRACER
-diff -Nur linux-3.18.12.orig/kernel/trace/latency_hist.c linux-3.18.12/kernel/trace/latency_hist.c
---- linux-3.18.12.orig/kernel/trace/latency_hist.c 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/kernel/trace/latency_hist.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/latency_hist.c linux-3.18.14-rt/kernel/trace/latency_hist.c
+--- linux-3.18.14.orig/kernel/trace/latency_hist.c 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/kernel/trace/latency_hist.c 2015-05-31 15:32:48.989635362 -0500
@@ -0,0 +1,1178 @@
+/*
+ * kernel/trace/latency_hist.c
@@ -29533,9 +29294,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/latency_hist.c linux-3.18.12/kernel/tr
+}
+
+device_initcall(latency_hist_init);
-diff -Nur linux-3.18.12.orig/kernel/trace/Makefile linux-3.18.12/kernel/trace/Makefile
---- linux-3.18.12.orig/kernel/trace/Makefile 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/Makefile 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/Makefile linux-3.18.14-rt/kernel/trace/Makefile
+--- linux-3.18.14.orig/kernel/trace/Makefile 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/Makefile 2015-05-31 15:32:48.989635362 -0500
@@ -36,6 +36,10 @@
obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
@@ -29547,9 +29308,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/Makefile linux-3.18.12/kernel/trace/Ma
obj-$(CONFIG_NOP_TRACER) += trace_nop.o
obj-$(CONFIG_STACK_TRACER) += trace_stack.o
obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o
-diff -Nur linux-3.18.12.orig/kernel/trace/trace.c linux-3.18.12/kernel/trace/trace.c
---- linux-3.18.12.orig/kernel/trace/trace.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/trace.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/trace.c linux-3.18.14-rt/kernel/trace/trace.c
+--- linux-3.18.14.orig/kernel/trace/trace.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/trace.c 2015-05-31 15:32:49.021635361 -0500
@@ -1579,6 +1579,7 @@
struct task_struct *tsk = current;
@@ -29621,9 +29382,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace.c linux-3.18.12/kernel/trace/tra
}
void
-diff -Nur linux-3.18.12.orig/kernel/trace/trace_events.c linux-3.18.12/kernel/trace/trace_events.c
---- linux-3.18.12.orig/kernel/trace/trace_events.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/trace_events.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/trace_events.c linux-3.18.14-rt/kernel/trace/trace_events.c
+--- linux-3.18.14.orig/kernel/trace/trace_events.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/trace_events.c 2015-05-31 15:32:49.025635362 -0500
@@ -162,6 +162,8 @@
__common_field(unsigned char, flags);
__common_field(unsigned char, preempt_count);
@@ -29633,9 +29394,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace_events.c linux-3.18.12/kernel/tr
return ret;
}
-diff -Nur linux-3.18.12.orig/kernel/trace/trace.h linux-3.18.12/kernel/trace/trace.h
---- linux-3.18.12.orig/kernel/trace/trace.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/trace.h 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/trace.h linux-3.18.14-rt/kernel/trace/trace.h
+--- linux-3.18.14.orig/kernel/trace/trace.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/trace.h 2015-05-31 15:32:49.021635361 -0500
@@ -119,6 +119,7 @@
* NEED_RESCHED - reschedule is requested
* HARDIRQ - inside an interrupt handler
@@ -29652,9 +29413,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace.h linux-3.18.12/kernel/trace/tra
};
#define TRACE_BUF_SIZE 1024
-diff -Nur linux-3.18.12.orig/kernel/trace/trace_irqsoff.c linux-3.18.12/kernel/trace/trace_irqsoff.c
---- linux-3.18.12.orig/kernel/trace/trace_irqsoff.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/trace_irqsoff.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/trace_irqsoff.c linux-3.18.14-rt/kernel/trace/trace_irqsoff.c
+--- linux-3.18.14.orig/kernel/trace/trace_irqsoff.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/trace_irqsoff.c 2015-05-31 15:32:49.025635362 -0500
@@ -17,6 +17,7 @@
#include <linux/fs.h>
@@ -29738,9 +29499,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace_irqsoff.c linux-3.18.12/kernel/t
if (preempt_trace() && !irq_trace())
start_critical_timing(a0, a1);
}
-diff -Nur linux-3.18.12.orig/kernel/trace/trace_output.c linux-3.18.12/kernel/trace/trace_output.c
---- linux-3.18.12.orig/kernel/trace/trace_output.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/trace/trace_output.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/trace/trace_output.c linux-3.18.14-rt/kernel/trace/trace_output.c
+--- linux-3.18.14.orig/kernel/trace/trace_output.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/trace/trace_output.c 2015-05-31 15:32:49.025635362 -0500
@@ -410,6 +410,7 @@
{
char hardsoft_irq;
@@ -29787,9 +29548,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace_output.c linux-3.18.12/kernel/tr
return ret;
}
-diff -Nur linux-3.18.12.orig/kernel/user.c linux-3.18.12/kernel/user.c
---- linux-3.18.12.orig/kernel/user.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/user.c 2015-04-26 13:32:22.455684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/user.c linux-3.18.14-rt/kernel/user.c
+--- linux-3.18.14.orig/kernel/user.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/user.c 2015-05-31 15:32:49.045635362 -0500
@@ -158,11 +158,11 @@
if (!up)
return;
@@ -29804,9 +29565,9 @@ diff -Nur linux-3.18.12.orig/kernel/user.c linux-3.18.12/kernel/user.c
}
struct user_struct *alloc_uid(kuid_t uid)
-diff -Nur linux-3.18.12.orig/kernel/watchdog.c linux-3.18.12/kernel/watchdog.c
---- linux-3.18.12.orig/kernel/watchdog.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/watchdog.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/watchdog.c linux-3.18.14-rt/kernel/watchdog.c
+--- linux-3.18.14.orig/kernel/watchdog.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/watchdog.c 2015-05-31 15:32:49.065635361 -0500
@@ -248,6 +248,8 @@
#ifdef CONFIG_HARDLOCKUP_DETECTOR
@@ -29848,9 +29609,9 @@ diff -Nur linux-3.18.12.orig/kernel/watchdog.c linux-3.18.12/kernel/watchdog.c
/* Enable the perf event */
watchdog_nmi_enable(cpu);
-diff -Nur linux-3.18.12.orig/kernel/workqueue.c linux-3.18.12/kernel/workqueue.c
---- linux-3.18.12.orig/kernel/workqueue.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/workqueue.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/workqueue.c linux-3.18.14-rt/kernel/workqueue.c
+--- linux-3.18.14.orig/kernel/workqueue.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/workqueue.c 2015-05-31 15:32:49.069635361 -0500
@@ -48,6 +48,8 @@
#include <linux/nodemask.h>
#include <linux/moduleparam.h>
@@ -30448,9 +30209,9 @@ diff -Nur linux-3.18.12.orig/kernel/workqueue.c linux-3.18.12/kernel/workqueue.c
}
out_unlock:
mutex_unlock(&wq_pool_mutex);
-diff -Nur linux-3.18.12.orig/kernel/workqueue_internal.h linux-3.18.12/kernel/workqueue_internal.h
---- linux-3.18.12.orig/kernel/workqueue_internal.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/kernel/workqueue_internal.h 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/kernel/workqueue_internal.h linux-3.18.14-rt/kernel/workqueue_internal.h
+--- linux-3.18.14.orig/kernel/workqueue_internal.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/kernel/workqueue_internal.h 2015-05-31 15:32:49.069635361 -0500
@@ -43,6 +43,7 @@
unsigned long last_active; /* L: last active timestamp */
unsigned int flags; /* X: flags */
@@ -30469,9 +30230,9 @@ diff -Nur linux-3.18.12.orig/kernel/workqueue_internal.h linux-3.18.12/kernel/wo
+void wq_worker_sleeping(struct task_struct *task);
#endif /* _KERNEL_WORKQUEUE_INTERNAL_H */
-diff -Nur linux-3.18.12.orig/lib/debugobjects.c linux-3.18.12/lib/debugobjects.c
---- linux-3.18.12.orig/lib/debugobjects.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/debugobjects.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/debugobjects.c linux-3.18.14-rt/lib/debugobjects.c
+--- linux-3.18.14.orig/lib/debugobjects.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/debugobjects.c 2015-05-31 15:32:49.113635361 -0500
@@ -309,7 +309,10 @@
struct debug_obj *obj;
unsigned long flags;
@@ -30484,9 +30245,9 @@ diff -Nur linux-3.18.12.orig/lib/debugobjects.c linux-3.18.12/lib/debugobjects.c
db = get_bucket((unsigned long) addr);
-diff -Nur linux-3.18.12.orig/lib/idr.c linux-3.18.12/lib/idr.c
---- linux-3.18.12.orig/lib/idr.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/idr.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/idr.c linux-3.18.14-rt/lib/idr.c
+--- linux-3.18.14.orig/lib/idr.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/idr.c 2015-05-31 15:32:49.141635361 -0500
@@ -31,6 +31,7 @@
#include <linux/spinlock.h>
#include <linux/percpu.h>
@@ -30552,9 +30313,9 @@ diff -Nur linux-3.18.12.orig/lib/idr.c linux-3.18.12/lib/idr.c
if (!new)
break;
-diff -Nur linux-3.18.12.orig/lib/Kconfig linux-3.18.12/lib/Kconfig
---- linux-3.18.12.orig/lib/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/Kconfig 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/Kconfig linux-3.18.14-rt/lib/Kconfig
+--- linux-3.18.14.orig/lib/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/Kconfig 2015-05-31 15:32:49.085635361 -0500
@@ -383,6 +383,7 @@
config CPUMASK_OFFSTACK
@@ -30563,9 +30324,9 @@ diff -Nur linux-3.18.12.orig/lib/Kconfig linux-3.18.12/lib/Kconfig
help
Use dynamic allocation for cpumask_var_t, instead of putting
them on the stack. This is a bit more expensive, but avoids
-diff -Nur linux-3.18.12.orig/lib/Kconfig.debug linux-3.18.12/lib/Kconfig.debug
---- linux-3.18.12.orig/lib/Kconfig.debug 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/Kconfig.debug 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/Kconfig.debug linux-3.18.14-rt/lib/Kconfig.debug
+--- linux-3.18.14.orig/lib/Kconfig.debug 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/Kconfig.debug 2015-05-31 15:32:49.097635361 -0500
@@ -639,7 +639,7 @@
config DEBUG_SHIRQ
@@ -30575,9 +30336,9 @@ diff -Nur linux-3.18.12.orig/lib/Kconfig.debug linux-3.18.12/lib/Kconfig.debug
help
Enable this to generate a spurious interrupt as soon as a shared
interrupt handler is registered, and just before one is deregistered.
-diff -Nur linux-3.18.12.orig/lib/locking-selftest.c linux-3.18.12/lib/locking-selftest.c
---- linux-3.18.12.orig/lib/locking-selftest.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/locking-selftest.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/locking-selftest.c linux-3.18.14-rt/lib/locking-selftest.c
+--- linux-3.18.14.orig/lib/locking-selftest.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/locking-selftest.c 2015-05-31 15:32:49.141635361 -0500
@@ -590,6 +590,8 @@
#include "locking-selftest-spin-hardirq.h"
GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin)
@@ -30726,9 +30487,9 @@ diff -Nur linux-3.18.12.orig/lib/locking-selftest.c linux-3.18.12/lib/locking-se
ww_tests();
-diff -Nur linux-3.18.12.orig/lib/percpu_ida.c linux-3.18.12/lib/percpu_ida.c
---- linux-3.18.12.orig/lib/percpu_ida.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/percpu_ida.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/percpu_ida.c linux-3.18.14-rt/lib/percpu_ida.c
+--- linux-3.18.14.orig/lib/percpu_ida.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/percpu_ida.c 2015-05-31 15:32:49.161635360 -0500
@@ -29,6 +29,9 @@
#include <linux/string.h>
#include <linux/spinlock.h>
@@ -30817,9 +30578,9 @@ diff -Nur linux-3.18.12.orig/lib/percpu_ida.c linux-3.18.12/lib/percpu_ida.c
return err;
}
EXPORT_SYMBOL_GPL(percpu_ida_for_each_free);
-diff -Nur linux-3.18.12.orig/lib/radix-tree.c linux-3.18.12/lib/radix-tree.c
---- linux-3.18.12.orig/lib/radix-tree.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/radix-tree.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/radix-tree.c linux-3.18.14-rt/lib/radix-tree.c
+--- linux-3.18.14.orig/lib/radix-tree.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/radix-tree.c 2015-05-31 15:32:49.161635360 -0500
@@ -195,12 +195,13 @@
* succeed in getting a node here (and never reach
* kmem_cache_alloc)
@@ -30851,9 +30612,9 @@ diff -Nur linux-3.18.12.orig/lib/radix-tree.c linux-3.18.12/lib/radix-tree.c
/*
* Return the maximum key which can be store into a
-diff -Nur linux-3.18.12.orig/lib/scatterlist.c linux-3.18.12/lib/scatterlist.c
---- linux-3.18.12.orig/lib/scatterlist.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/scatterlist.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/scatterlist.c linux-3.18.14-rt/lib/scatterlist.c
+--- linux-3.18.14.orig/lib/scatterlist.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/scatterlist.c 2015-05-31 15:32:49.161635360 -0500
@@ -592,7 +592,7 @@
flush_kernel_dcache_page(miter->page);
@@ -30881,9 +30642,9 @@ diff -Nur linux-3.18.12.orig/lib/scatterlist.c linux-3.18.12/lib/scatterlist.c
return offset;
}
-diff -Nur linux-3.18.12.orig/lib/smp_processor_id.c linux-3.18.12/lib/smp_processor_id.c
---- linux-3.18.12.orig/lib/smp_processor_id.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/lib/smp_processor_id.c 2015-04-26 13:32:22.459684003 -0500
+diff -Nur linux-3.18.14.orig/lib/smp_processor_id.c linux-3.18.14-rt/lib/smp_processor_id.c
+--- linux-3.18.14.orig/lib/smp_processor_id.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/lib/smp_processor_id.c 2015-05-31 15:32:49.161635360 -0500
@@ -39,8 +39,9 @@
if (!printk_ratelimit())
goto out_enable;
@@ -30896,9 +30657,9 @@ diff -Nur linux-3.18.12.orig/lib/smp_processor_id.c linux-3.18.12/lib/smp_proces
print_symbol("caller is %s\n", (long)__builtin_return_address(0));
dump_stack();
-diff -Nur linux-3.18.12.orig/mm/filemap.c linux-3.18.12/mm/filemap.c
---- linux-3.18.12.orig/mm/filemap.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/filemap.c 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/filemap.c linux-3.18.14-rt/mm/filemap.c
+--- linux-3.18.14.orig/mm/filemap.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/filemap.c 2015-05-31 15:32:49.181635360 -0500
@@ -168,7 +168,9 @@
if (!workingset_node_pages(node) &&
list_empty(&node->private_list)) {
@@ -30925,9 +30686,9 @@ diff -Nur linux-3.18.12.orig/mm/filemap.c linux-3.18.12/mm/filemap.c
}
return 0;
}
-diff -Nur linux-3.18.12.orig/mm/highmem.c linux-3.18.12/mm/highmem.c
---- linux-3.18.12.orig/mm/highmem.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/highmem.c 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/highmem.c linux-3.18.14-rt/mm/highmem.c
+--- linux-3.18.14.orig/mm/highmem.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/highmem.c 2015-05-31 15:32:49.201635360 -0500
@@ -29,10 +29,11 @@
#include <linux/kgdb.h>
#include <asm/tlbflush.h>
@@ -30952,9 +30713,9 @@ diff -Nur linux-3.18.12.orig/mm/highmem.c linux-3.18.12/mm/highmem.c
unsigned int nr_free_highpages (void)
{
-diff -Nur linux-3.18.12.orig/mm/Kconfig linux-3.18.12/mm/Kconfig
---- linux-3.18.12.orig/mm/Kconfig 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/Kconfig 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/Kconfig linux-3.18.14-rt/mm/Kconfig
+--- linux-3.18.14.orig/mm/Kconfig 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/Kconfig 2015-05-31 15:32:49.177635360 -0500
@@ -408,7 +408,7 @@
config TRANSPARENT_HUGEPAGE
@@ -30964,9 +30725,9 @@ diff -Nur linux-3.18.12.orig/mm/Kconfig linux-3.18.12/mm/Kconfig
select COMPACTION
help
Transparent Hugepages allows the kernel to use huge pages and
-diff -Nur linux-3.18.12.orig/mm/memcontrol.c linux-3.18.12/mm/memcontrol.c
---- linux-3.18.12.orig/mm/memcontrol.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/memcontrol.c 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/memcontrol.c linux-3.18.14-rt/mm/memcontrol.c
+--- linux-3.18.14.orig/mm/memcontrol.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/memcontrol.c 2015-05-31 15:32:49.213635360 -0500
@@ -60,6 +60,8 @@
#include <net/sock.h>
#include <net/ip.h>
@@ -31067,9 +30828,9 @@ diff -Nur linux-3.18.12.orig/mm/memcontrol.c linux-3.18.12/mm/memcontrol.c
}
static void uncharge_list(struct list_head *page_list)
-diff -Nur linux-3.18.12.orig/mm/memory.c linux-3.18.12/mm/memory.c
---- linux-3.18.12.orig/mm/memory.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/memory.c 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/memory.c linux-3.18.14-rt/mm/memory.c
+--- linux-3.18.14.orig/mm/memory.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/memory.c 2015-05-31 15:32:49.229635360 -0500
@@ -3244,6 +3244,32 @@
return 0;
}
@@ -31103,9 +30864,9 @@ diff -Nur linux-3.18.12.orig/mm/memory.c linux-3.18.12/mm/memory.c
/*
* By the time we get here, we already hold the mm semaphore
*
-diff -Nur linux-3.18.12.orig/mm/mmu_context.c linux-3.18.12/mm/mmu_context.c
---- linux-3.18.12.orig/mm/mmu_context.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/mmu_context.c 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/mmu_context.c linux-3.18.14-rt/mm/mmu_context.c
+--- linux-3.18.14.orig/mm/mmu_context.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/mmu_context.c 2015-05-31 15:32:49.249635360 -0500
@@ -23,6 +23,7 @@
struct task_struct *tsk = current;
@@ -31122,9 +30883,9 @@ diff -Nur linux-3.18.12.orig/mm/mmu_context.c linux-3.18.12/mm/mmu_context.c
task_unlock(tsk);
#ifdef finish_arch_post_lock_switch
finish_arch_post_lock_switch();
-diff -Nur linux-3.18.12.orig/mm/page_alloc.c linux-3.18.12/mm/page_alloc.c
---- linux-3.18.12.orig/mm/page_alloc.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/page_alloc.c 2015-04-26 13:32:22.463684003 -0500
+diff -Nur linux-3.18.14.orig/mm/page_alloc.c linux-3.18.14-rt/mm/page_alloc.c
+--- linux-3.18.14.orig/mm/page_alloc.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/page_alloc.c 2015-05-31 15:32:49.253635359 -0500
@@ -59,6 +59,7 @@
#include <linux/page-debug-flags.h>
#include <linux/hugetlb.h>
@@ -31457,9 +31218,9 @@ diff -Nur linux-3.18.12.orig/mm/page_alloc.c linux-3.18.12/mm/page_alloc.c
}
#ifdef CONFIG_MEMORY_HOTREMOVE
-diff -Nur linux-3.18.12.orig/mm/slab.h linux-3.18.12/mm/slab.h
---- linux-3.18.12.orig/mm/slab.h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/slab.h 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/slab.h linux-3.18.14-rt/mm/slab.h
+--- linux-3.18.14.orig/mm/slab.h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/slab.h 2015-05-31 15:32:49.257635359 -0500
@@ -315,7 +315,11 @@
* The slab lists for all objects.
*/
@@ -31472,9 +31233,9 @@ diff -Nur linux-3.18.12.orig/mm/slab.h linux-3.18.12/mm/slab.h
#ifdef CONFIG_SLAB
struct list_head slabs_partial; /* partial list first, better asm code */
-diff -Nur linux-3.18.12.orig/mm/slub.c linux-3.18.12/mm/slub.c
---- linux-3.18.12.orig/mm/slub.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/slub.c 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/slub.c linux-3.18.14-rt/mm/slub.c
+--- linux-3.18.14.orig/mm/slub.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/slub.c 2015-05-31 15:32:49.257635359 -0500
@@ -1044,7 +1044,7 @@
{
struct kmem_cache_node *n = get_node(s, page_to_nid(page));
@@ -31864,9 +31625,9 @@ diff -Nur linux-3.18.12.orig/mm/slub.c linux-3.18.12/mm/slub.c
}
for (i = 0; i < t.count; i++) {
-diff -Nur linux-3.18.12.orig/mm/swap.c linux-3.18.12/mm/swap.c
---- linux-3.18.12.orig/mm/swap.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/swap.c 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/swap.c linux-3.18.14-rt/mm/swap.c
+--- linux-3.18.14.orig/mm/swap.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/swap.c 2015-05-31 15:32:49.285635359 -0500
@@ -31,6 +31,7 @@
#include <linux/memcontrol.h>
#include <linux/gfp.h>
@@ -31985,9 +31746,9 @@ diff -Nur linux-3.18.12.orig/mm/swap.c linux-3.18.12/mm/swap.c
}
static void lru_add_drain_per_cpu(struct work_struct *dummy)
-diff -Nur linux-3.18.12.orig/mm/truncate.c linux-3.18.12/mm/truncate.c
---- linux-3.18.12.orig/mm/truncate.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/truncate.c 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/truncate.c linux-3.18.14-rt/mm/truncate.c
+--- linux-3.18.14.orig/mm/truncate.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/truncate.c 2015-05-31 15:32:49.293635359 -0500
@@ -56,8 +56,11 @@
* protected by mapping->tree_lock.
*/
@@ -32002,9 +31763,9 @@ diff -Nur linux-3.18.12.orig/mm/truncate.c linux-3.18.12/mm/truncate.c
__radix_tree_delete_node(&mapping->page_tree, node);
unlock:
spin_unlock_irq(&mapping->tree_lock);
-diff -Nur linux-3.18.12.orig/mm/vmalloc.c linux-3.18.12/mm/vmalloc.c
---- linux-3.18.12.orig/mm/vmalloc.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/vmalloc.c 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/vmalloc.c linux-3.18.14-rt/mm/vmalloc.c
+--- linux-3.18.14.orig/mm/vmalloc.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/vmalloc.c 2015-05-31 15:32:49.297635359 -0500
@@ -798,7 +798,7 @@
struct vmap_block *vb;
struct vmap_area *va;
@@ -32056,9 +31817,9 @@ diff -Nur linux-3.18.12.orig/mm/vmalloc.c linux-3.18.12/mm/vmalloc.c
rcu_read_unlock();
if (!addr) {
-diff -Nur linux-3.18.12.orig/mm/vmstat.c linux-3.18.12/mm/vmstat.c
---- linux-3.18.12.orig/mm/vmstat.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/vmstat.c 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/vmstat.c linux-3.18.14-rt/mm/vmstat.c
+--- linux-3.18.14.orig/mm/vmstat.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/vmstat.c 2015-05-31 15:32:49.297635359 -0500
@@ -221,6 +221,7 @@
long x;
long t;
@@ -32107,9 +31868,9 @@ diff -Nur linux-3.18.12.orig/mm/vmstat.c linux-3.18.12/mm/vmstat.c
}
void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
-diff -Nur linux-3.18.12.orig/mm/workingset.c linux-3.18.12/mm/workingset.c
---- linux-3.18.12.orig/mm/workingset.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/mm/workingset.c 2015-04-26 13:32:22.467684003 -0500
+diff -Nur linux-3.18.14.orig/mm/workingset.c linux-3.18.14-rt/mm/workingset.c
+--- linux-3.18.14.orig/mm/workingset.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/mm/workingset.c 2015-05-31 15:32:49.321635359 -0500
@@ -264,7 +264,8 @@
* point where they would still be useful.
*/
@@ -32177,9 +31938,9 @@ diff -Nur linux-3.18.12.orig/mm/workingset.c linux-3.18.12/mm/workingset.c
err:
return ret;
}
-diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
---- linux-3.18.12.orig/net/core/dev.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/core/dev.c 2015-04-26 13:32:22.471684003 -0500
+diff -Nur linux-3.18.14.orig/net/core/dev.c linux-3.18.14-rt/net/core/dev.c
+--- linux-3.18.14.orig/net/core/dev.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/core/dev.c 2015-05-31 15:32:49.369635359 -0500
@@ -182,6 +182,7 @@
static DEFINE_HASHTABLE(napi_hash, 8);
@@ -32296,7 +32057,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
}
EXPORT_SYMBOL(__dev_kfree_skb_irq);
-@@ -3336,6 +3344,7 @@
+@@ -3334,6 +3342,7 @@
rps_unlock(sd);
local_irq_restore(flags);
@@ -32304,7 +32065,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
atomic_long_inc(&skb->dev->rx_dropped);
kfree_skb(skb);
-@@ -3354,7 +3363,7 @@
+@@ -3352,7 +3361,7 @@
struct rps_dev_flow voidflow, *rflow = &voidflow;
int cpu;
@@ -32313,7 +32074,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
rcu_read_lock();
cpu = get_rps_cpu(skb->dev, skb, &rflow);
-@@ -3364,13 +3373,13 @@
+@@ -3362,13 +3371,13 @@
ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
rcu_read_unlock();
@@ -32330,7 +32091,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
}
return ret;
}
-@@ -3404,16 +3413,44 @@
+@@ -3402,16 +3411,44 @@
trace_netif_rx_ni_entry(skb);
@@ -32379,7 +32140,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
static void net_tx_action(struct softirq_action *h)
{
struct softnet_data *sd = this_cpu_ptr(&softnet_data);
-@@ -3455,7 +3492,7 @@
+@@ -3453,7 +3490,7 @@
head = head->next_sched;
root_lock = qdisc_lock(q);
@@ -32388,7 +32149,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
smp_mb__before_atomic();
clear_bit(__QDISC_STATE_SCHED,
&q->state);
-@@ -3848,7 +3885,7 @@
+@@ -3846,7 +3883,7 @@
skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
if (skb->dev == dev) {
__skb_unlink(skb, &sd->input_pkt_queue);
@@ -32397,7 +32158,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
input_queue_head_incr(sd);
}
}
-@@ -3857,10 +3894,13 @@
+@@ -3855,10 +3892,13 @@
skb_queue_walk_safe(&sd->process_queue, skb, tmp) {
if (skb->dev == dev) {
__skb_unlink(skb, &sd->process_queue);
@@ -32412,7 +32173,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
}
static int napi_gro_complete(struct sk_buff *skb)
-@@ -4323,6 +4363,7 @@
+@@ -4321,6 +4361,7 @@
} else
#endif
local_irq_enable();
@@ -32420,7 +32181,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
}
static int process_backlog(struct napi_struct *napi, int quota)
-@@ -4394,6 +4435,7 @@
+@@ -4392,6 +4433,7 @@
local_irq_save(flags);
____napi_schedule(this_cpu_ptr(&softnet_data), n);
local_irq_restore(flags);
@@ -32428,7 +32189,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
}
EXPORT_SYMBOL(__napi_schedule);
-@@ -4516,10 +4558,17 @@
+@@ -4514,10 +4556,17 @@
struct softnet_data *sd = this_cpu_ptr(&softnet_data);
unsigned long time_limit = jiffies + 2;
int budget = netdev_budget;
@@ -32446,7 +32207,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
while (!list_empty(&sd->poll_list)) {
struct napi_struct *n;
int work, weight;
-@@ -7008,6 +7057,7 @@
+@@ -7006,6 +7055,7 @@
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_enable();
@@ -32454,7 +32215,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
/* Process offline CPU's input_pkt_queue */
while ((skb = __skb_dequeue(&oldsd->process_queue))) {
-@@ -7018,6 +7068,9 @@
+@@ -7016,6 +7066,9 @@
netif_rx_internal(skb);
input_queue_head_incr(oldsd);
}
@@ -32464,7 +32225,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
return NOTIFY_OK;
}
-@@ -7319,8 +7372,9 @@
+@@ -7317,8 +7370,9 @@
for_each_possible_cpu(i) {
struct softnet_data *sd = &per_cpu(softnet_data, i);
@@ -32476,9 +32237,9 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c
INIT_LIST_HEAD(&sd->poll_list);
sd->output_queue_tailp = &sd->output_queue;
#ifdef CONFIG_RPS
-diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c
---- linux-3.18.12.orig/net/core/skbuff.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/core/skbuff.c 2015-04-26 13:32:22.471684003 -0500
+diff -Nur linux-3.18.14.orig/net/core/skbuff.c linux-3.18.14-rt/net/core/skbuff.c
+--- linux-3.18.14.orig/net/core/skbuff.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/core/skbuff.c 2015-05-31 15:32:49.393635358 -0500
@@ -63,6 +63,7 @@
#include <linux/errqueue.h>
#include <linux/prefetch.h>
@@ -32487,7 +32248,7 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c
#include <net/protocol.h>
#include <net/dst.h>
-@@ -336,6 +337,7 @@
+@@ -353,6 +354,7 @@
unsigned int pagecnt_bias;
};
static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
@@ -32495,7 +32256,7 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c
static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
{
-@@ -344,7 +346,7 @@
+@@ -361,7 +363,7 @@
int order;
unsigned long flags;
@@ -32504,7 +32265,7 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c
nc = this_cpu_ptr(&netdev_alloc_cache);
if (unlikely(!nc->frag.page)) {
refill:
-@@ -389,7 +391,7 @@
+@@ -407,7 +409,7 @@
nc->frag.offset += fragsz;
nc->pagecnt_bias--;
end:
@@ -32513,3589 +32274,4344 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c
return data;
}
-diff -Nur linux-3.18.12.orig/net/core/sock.c linux-3.18.12/net/core/sock.c
---- linux-3.18.12.orig/net/core/sock.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/core/sock.c 2015-04-26 13:32:22.471684003 -0500
-@@ -2326,12 +2326,11 @@
- if (sk->sk_lock.owned)
- __lock_sock(sk);
- sk->sk_lock.owned = 1;
-- spin_unlock(&sk->sk_lock.slock);
-+ spin_unlock_bh(&sk->sk_lock.slock);
- /*
- * The sk_lock has mutex_lock() semantics here:
- */
- mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
-- local_bh_enable();
- }
- EXPORT_SYMBOL(lock_sock_nested);
-
-diff -Nur linux-3.18.12.orig/net/ipv4/icmp.c linux-3.18.12/net/ipv4/icmp.c
---- linux-3.18.12.orig/net/ipv4/icmp.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/ipv4/icmp.c 2015-04-26 13:32:22.471684003 -0500
-@@ -69,6 +69,7 @@
- #include <linux/jiffies.h>
- #include <linux/kernel.h>
- #include <linux/fcntl.h>
-+#include <linux/sysrq.h>
- #include <linux/socket.h>
- #include <linux/in.h>
- #include <linux/inet.h>
-@@ -864,6 +865,30 @@
- }
-
- /*
-+ * 32bit and 64bit have different timestamp length, so we check for
-+ * the cookie at offset 20 and verify it is repeated at offset 50
+diff -Nur linux-3.18.14.orig/net/core/skbuff.c.orig linux-3.18.14-rt/net/core/skbuff.c.orig
+--- linux-3.18.14.orig/net/core/skbuff.c.orig 1969-12-31 18:00:00.000000000 -0600
++++ linux-3.18.14-rt/net/core/skbuff.c.orig 2015-05-20 10:04:50.000000000 -0500
+@@ -0,0 +1,4231 @@
++/*
++ * Routines having to do with the 'struct sk_buff' memory handlers.
++ *
++ * Authors: Alan Cox <alan@lxorguk.ukuu.org.uk>
++ * Florian La Roche <rzsfl@rz.uni-sb.de>
++ *
++ * Fixes:
++ * Alan Cox : Fixed the worst of the load
++ * balancer bugs.
++ * Dave Platt : Interrupt stacking fix.
++ * Richard Kooijman : Timestamp fixes.
++ * Alan Cox : Changed buffer format.
++ * Alan Cox : destructor hook for AF_UNIX etc.
++ * Linus Torvalds : Better skb_clone.
++ * Alan Cox : Added skb_copy.
++ * Alan Cox : Added all the changed routines Linus
++ * only put in the headers
++ * Ray VanTassle : Fixed --skb->lock in free
++ * Alan Cox : skb_copy copy arp field
++ * Andi Kleen : slabified it.
++ * Robert Olsson : Removed skb_head_pool
++ *
++ * NOTE:
++ * The __skb_ routines should be called with interrupts
++ * disabled, or you better be *real* sure that the operation is atomic
++ * with respect to whatever list is being frobbed (e.g. via lock_sock()
++ * or via disabling bottom half handlers, etc).
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
+ */
-+#define CO_POS0 20
-+#define CO_POS1 50
-+#define CO_SIZE sizeof(int)
-+#define ICMP_SYSRQ_SIZE 57
+
+/*
-+ * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie
-+ * pattern and if it matches send the next byte as a trigger to sysrq.
++ * The functions in this file will not compile correctly with gcc 2.4.x
+ */
-+static void icmp_check_sysrq(struct net *net, struct sk_buff *skb)
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/kmemcheck.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/in.h>
++#include <linux/inet.h>
++#include <linux/slab.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/netdevice.h>
++#ifdef CONFIG_NET_CLS_ACT
++#include <net/pkt_sched.h>
++#endif
++#include <linux/string.h>
++#include <linux/skbuff.h>
++#include <linux/splice.h>
++#include <linux/cache.h>
++#include <linux/rtnetlink.h>
++#include <linux/init.h>
++#include <linux/scatterlist.h>
++#include <linux/errqueue.h>
++#include <linux/prefetch.h>
++#include <linux/if_vlan.h>
++
++#include <net/protocol.h>
++#include <net/dst.h>
++#include <net/sock.h>
++#include <net/checksum.h>
++#include <net/ip6_checksum.h>
++#include <net/xfrm.h>
++
++#include <asm/uaccess.h>
++#include <trace/events/skb.h>
++#include <linux/highmem.h>
++
++struct kmem_cache *skbuff_head_cache __read_mostly;
++static struct kmem_cache *skbuff_fclone_cache __read_mostly;
++
++/**
++ * skb_panic - private function for out-of-line support
++ * @skb: buffer
++ * @sz: size
++ * @addr: address
++ * @msg: skb_over_panic or skb_under_panic
++ *
++ * Out-of-line support for skb_put() and skb_push().
++ * Called via the wrapper skb_over_panic() or skb_under_panic().
++ * Keep out of line to prevent kernel bloat.
++ * __builtin_return_address is not used because it is not always reliable.
++ */
++static void skb_panic(struct sk_buff *skb, unsigned int sz, void *addr,
++ const char msg[])
+{
-+ int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq);
-+ char *p = skb->data;
++ pr_emerg("%s: text:%p len:%d put:%d head:%p data:%p tail:%#lx end:%#lx dev:%s\n",
++ msg, addr, skb->len, sz, skb->head, skb->data,
++ (unsigned long)skb->tail, (unsigned long)skb->end,
++ skb->dev ? skb->dev->name : "<NULL>");
++ BUG();
++}
+
-+ if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) &&
-+ !memcmp(&cookie, p + CO_POS1, CO_SIZE) &&
-+ p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE])
-+ handle_sysrq(p[CO_POS0 + CO_SIZE]);
++static void skb_over_panic(struct sk_buff *skb, unsigned int sz, void *addr)
++{
++ skb_panic(skb, sz, addr, __func__);
+}
+
-+/*
- * Handle ICMP_ECHO ("ping") requests.
- *
- * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo
-@@ -890,6 +915,11 @@
- icmp_param.data_len = skb->len;
- icmp_param.head_len = sizeof(struct icmphdr);
- icmp_reply(&icmp_param, skb);
++static void skb_under_panic(struct sk_buff *skb, unsigned int sz, void *addr)
++{
++ skb_panic(skb, sz, addr, __func__);
++}
+
-+ if (skb->len == ICMP_SYSRQ_SIZE &&
-+ net->ipv4.sysctl_icmp_echo_sysrq) {
-+ icmp_check_sysrq(net, skb);
-+ }
- }
- }
-
-diff -Nur linux-3.18.12.orig/net/ipv4/sysctl_net_ipv4.c linux-3.18.12/net/ipv4/sysctl_net_ipv4.c
---- linux-3.18.12.orig/net/ipv4/sysctl_net_ipv4.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/ipv4/sysctl_net_ipv4.c 2015-04-26 13:32:22.471684003 -0500
-@@ -779,6 +779,13 @@
- .proc_handler = proc_dointvec
- },
- {
-+ .procname = "icmp_echo_sysrq",
-+ .data = &init_net.ipv4.sysctl_icmp_echo_sysrq,
-+ .maxlen = sizeof(int),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec
-+ },
-+ {
- .procname = "icmp_ignore_bogus_error_responses",
- .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
- .maxlen = sizeof(int),
-diff -Nur linux-3.18.12.orig/net/mac80211/rx.c linux-3.18.12/net/mac80211/rx.c
---- linux-3.18.12.orig/net/mac80211/rx.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/mac80211/rx.c 2015-04-26 13:32:22.471684003 -0500
-@@ -3359,7 +3359,7 @@
- struct ieee80211_supported_band *sband;
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-
-- WARN_ON_ONCE(softirq_count() == 0);
-+ WARN_ON_ONCE_NONRT(softirq_count() == 0);
-
- if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
- goto drop;
-diff -Nur linux-3.18.12.orig/net/mac80211/rx.c.orig linux-3.18.12/net/mac80211/rx.c.orig
---- linux-3.18.12.orig/net/mac80211/rx.c.orig 1969-12-31 18:00:00.000000000 -0600
-+++ linux-3.18.12/net/mac80211/rx.c.orig 2015-04-20 14:48:02.000000000 -0500
-@@ -0,0 +1,3476 @@
+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
-+ * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
-+ * Copyright 2013-2014 Intel Mobile Communications GmbH
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
++ * kmalloc_reserve is a wrapper around kmalloc_node_track_caller that tells
++ * the caller if emergency pfmemalloc reserves are being used. If it is and
++ * the socket is later found to be SOCK_MEMALLOC then PFMEMALLOC reserves
++ * may be used. Otherwise, the packet data may be discarded until enough
++ * memory is free
+ */
++#define kmalloc_reserve(size, gfp, node, pfmemalloc) \
++ __kmalloc_reserve(size, gfp, node, _RET_IP_, pfmemalloc)
+
-+#include <linux/jiffies.h>
-+#include <linux/slab.h>
-+#include <linux/kernel.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rcupdate.h>
-+#include <linux/export.h>
-+#include <net/mac80211.h>
-+#include <net/ieee80211_radiotap.h>
-+#include <asm/unaligned.h>
-+
-+#include "ieee80211_i.h"
-+#include "driver-ops.h"
-+#include "led.h"
-+#include "mesh.h"
-+#include "wep.h"
-+#include "wpa.h"
-+#include "tkip.h"
-+#include "wme.h"
-+#include "rate.h"
++static void *__kmalloc_reserve(size_t size, gfp_t flags, int node,
++ unsigned long ip, bool *pfmemalloc)
++{
++ void *obj;
++ bool ret_pfmemalloc = false;
+
-+/*
-+ * monitor mode reception
++ /*
++ * Try a regular allocation, when that fails and we're not entitled
++ * to the reserves, fail.
++ */
++ obj = kmalloc_node_track_caller(size,
++ flags | __GFP_NOMEMALLOC | __GFP_NOWARN,
++ node);
++ if (obj || !(gfp_pfmemalloc_allowed(flags)))
++ goto out;
++
++ /* Try again but now we are using pfmemalloc reserves */
++ ret_pfmemalloc = true;
++ obj = kmalloc_node_track_caller(size, flags, node);
++
++out:
++ if (pfmemalloc)
++ *pfmemalloc = ret_pfmemalloc;
++
++ return obj;
++}
++
++/* Allocate a new skbuff. We do this ourselves so we can fill in a few
++ * 'private' fields and also do memory statistics to find all the
++ * [BEEP] leaks.
+ *
-+ * This function cleans up the SKB, i.e. it removes all the stuff
-+ * only useful for monitoring.
+ */
-+static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
-+ struct sk_buff *skb)
++
++struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
+{
-+ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
-+ if (likely(skb->len > FCS_LEN))
-+ __pskb_trim(skb, skb->len - FCS_LEN);
-+ else {
-+ /* driver bug */
-+ WARN_ON(1);
-+ dev_kfree_skb(skb);
-+ return NULL;
-+ }
-+ }
++ struct sk_buff *skb;
++
++ /* Get the HEAD */
++ skb = kmem_cache_alloc_node(skbuff_head_cache,
++ gfp_mask & ~__GFP_DMA, node);
++ if (!skb)
++ goto out;
++
++ /*
++ * Only clear those fields we need to clear, not those that we will
++ * actually initialise below. Hence, don't put any more fields after
++ * the tail pointer in struct sk_buff!
++ */
++ memset(skb, 0, offsetof(struct sk_buff, tail));
++ skb->head = NULL;
++ skb->truesize = sizeof(struct sk_buff);
++ atomic_set(&skb->users, 1);
+
++ skb->mac_header = (typeof(skb->mac_header))~0U;
++out:
+ return skb;
+}
+
-+static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len)
++/**
++ * __alloc_skb - allocate a network buffer
++ * @size: size to allocate
++ * @gfp_mask: allocation mask
++ * @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache
++ * instead of head cache and allocate a cloned (child) skb.
++ * If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for
++ * allocations in case the data is required for writeback
++ * @node: numa node to allocate memory on
++ *
++ * Allocate a new &sk_buff. The returned buffer has no headroom and a
++ * tail room of at least size bytes. The object has a reference count
++ * of one. The return is the buffer. On a failure the return is %NULL.
++ *
++ * Buffers may only be allocated from interrupts using a @gfp_mask of
++ * %GFP_ATOMIC.
++ */
++struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
++ int flags, int node)
+{
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *hdr = (void *)skb->data;
++ struct kmem_cache *cache;
++ struct skb_shared_info *shinfo;
++ struct sk_buff *skb;
++ u8 *data;
++ bool pfmemalloc;
+
-+ if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
-+ RX_FLAG_FAILED_PLCP_CRC |
-+ RX_FLAG_AMPDU_IS_ZEROLEN))
-+ return true;
++ cache = (flags & SKB_ALLOC_FCLONE)
++ ? skbuff_fclone_cache : skbuff_head_cache;
+
-+ if (unlikely(skb->len < 16 + present_fcs_len))
-+ return true;
++ if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX))
++ gfp_mask |= __GFP_MEMALLOC;
+
-+ if (ieee80211_is_ctl(hdr->frame_control) &&
-+ !ieee80211_is_pspoll(hdr->frame_control) &&
-+ !ieee80211_is_back_req(hdr->frame_control))
-+ return true;
++ /* Get the HEAD */
++ skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
++ if (!skb)
++ goto out;
++ prefetchw(skb);
+
-+ return false;
++ /* We do our best to align skb_shared_info on a separate cache
++ * line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives
++ * aligned memory blocks, unless SLUB/SLAB debug is enabled.
++ * Both skb->head and skb_shared_info are cache line aligned.
++ */
++ size = SKB_DATA_ALIGN(size);
++ size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
++ data = kmalloc_reserve(size, gfp_mask, node, &pfmemalloc);
++ if (!data)
++ goto nodata;
++ /* kmalloc(size) might give us more room than requested.
++ * Put skb_shared_info exactly at the end of allocated zone,
++ * to allow max possible filling before reallocation.
++ */
++ size = SKB_WITH_OVERHEAD(ksize(data));
++ prefetchw(data + size);
++
++ /*
++ * Only clear those fields we need to clear, not those that we will
++ * actually initialise below. Hence, don't put any more fields after
++ * the tail pointer in struct sk_buff!
++ */
++ memset(skb, 0, offsetof(struct sk_buff, tail));
++ /* Account for allocated memory : skb + skb->head */
++ skb->truesize = SKB_TRUESIZE(size);
++ skb->pfmemalloc = pfmemalloc;
++ atomic_set(&skb->users, 1);
++ skb->head = data;
++ skb->data = data;
++ skb_reset_tail_pointer(skb);
++ skb->end = skb->tail + size;
++ skb->mac_header = (typeof(skb->mac_header))~0U;
++ skb->transport_header = (typeof(skb->transport_header))~0U;
++
++ /* make sure we initialize shinfo sequentially */
++ shinfo = skb_shinfo(skb);
++ memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
++ atomic_set(&shinfo->dataref, 1);
++ kmemcheck_annotate_variable(shinfo->destructor_arg);
++
++ if (flags & SKB_ALLOC_FCLONE) {
++ struct sk_buff_fclones *fclones;
++
++ fclones = container_of(skb, struct sk_buff_fclones, skb1);
++
++ kmemcheck_annotate_bitfield(&fclones->skb2, flags1);
++ skb->fclone = SKB_FCLONE_ORIG;
++ atomic_set(&fclones->fclone_ref, 1);
++
++ fclones->skb2.fclone = SKB_FCLONE_FREE;
++ fclones->skb2.pfmemalloc = pfmemalloc;
++ }
++out:
++ return skb;
++nodata:
++ kmem_cache_free(cache, skb);
++ skb = NULL;
++ goto out;
+}
++EXPORT_SYMBOL(__alloc_skb);
+
-+static int
-+ieee80211_rx_radiotap_space(struct ieee80211_local *local,
-+ struct ieee80211_rx_status *status)
++/**
++ * __build_skb - build a network buffer
++ * @data: data buffer provided by caller
++ * @frag_size: size of data, or 0 if head was kmalloced
++ *
++ * Allocate a new &sk_buff. Caller provides space holding head and
++ * skb_shared_info. @data must have been allocated by kmalloc() only if
++ * @frag_size is 0, otherwise data should come from the page allocator
++ * or vmalloc()
++ * The return is the new skb buffer.
++ * On a failure the return is %NULL, and @data is not freed.
++ * Notes :
++ * Before IO, driver allocates only data buffer where NIC put incoming frame
++ * Driver should add room at head (NET_SKB_PAD) and
++ * MUST add room at tail (SKB_DATA_ALIGN(skb_shared_info))
++ * After IO, driver calls build_skb(), to allocate sk_buff and populate it
++ * before giving packet to stack.
++ * RX rings only contains data buffers, not full skbs.
++ */
++struct sk_buff *__build_skb(void *data, unsigned int frag_size)
+{
-+ int len;
++ struct skb_shared_info *shinfo;
++ struct sk_buff *skb;
++ unsigned int size = frag_size ? : ksize(data);
+
-+ /* always present fields */
-+ len = sizeof(struct ieee80211_radiotap_header) + 8;
++ skb = kmem_cache_alloc(skbuff_head_cache, GFP_ATOMIC);
++ if (!skb)
++ return NULL;
+
-+ /* allocate extra bitmaps */
-+ if (status->chains)
-+ len += 4 * hweight8(status->chains);
++ size -= SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
-+ if (ieee80211_have_rx_timestamp(status)) {
-+ len = ALIGN(len, 8);
-+ len += 8;
-+ }
-+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
-+ len += 1;
++ memset(skb, 0, offsetof(struct sk_buff, tail));
++ skb->truesize = SKB_TRUESIZE(size);
++ atomic_set(&skb->users, 1);
++ skb->head = data;
++ skb->data = data;
++ skb_reset_tail_pointer(skb);
++ skb->end = skb->tail + size;
++ skb->mac_header = (typeof(skb->mac_header))~0U;
++ skb->transport_header = (typeof(skb->transport_header))~0U;
+
-+ /* antenna field, if we don't have per-chain info */
-+ if (!status->chains)
-+ len += 1;
++ /* make sure we initialize shinfo sequentially */
++ shinfo = skb_shinfo(skb);
++ memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
++ atomic_set(&shinfo->dataref, 1);
++ kmemcheck_annotate_variable(shinfo->destructor_arg);
+
-+ /* padding for RX_FLAGS if necessary */
-+ len = ALIGN(len, 2);
++ return skb;
++}
+
-+ if (status->flag & RX_FLAG_HT) /* HT info */
-+ len += 3;
++/* build_skb() is wrapper over __build_skb(), that specifically
++ * takes care of skb->head and skb->pfmemalloc
++ * This means that if @frag_size is not zero, then @data must be backed
++ * by a page fragment, not kmalloc() or vmalloc()
++ */
++struct sk_buff *build_skb(void *data, unsigned int frag_size)
++{
++ struct sk_buff *skb = __build_skb(data, frag_size);
+
-+ if (status->flag & RX_FLAG_AMPDU_DETAILS) {
-+ len = ALIGN(len, 4);
-+ len += 8;
++ if (skb && frag_size) {
++ skb->head_frag = 1;
++ if (virt_to_head_page(data)->pfmemalloc)
++ skb->pfmemalloc = 1;
+ }
++ return skb;
++}
++EXPORT_SYMBOL(build_skb);
+
-+ if (status->flag & RX_FLAG_VHT) {
-+ len = ALIGN(len, 2);
-+ len += 12;
-+ }
++struct netdev_alloc_cache {
++ struct page_frag frag;
++ /* we maintain a pagecount bias, so that we dont dirty cache line
++ * containing page->_count every time we allocate a fragment.
++ */
++ unsigned int pagecnt_bias;
++};
++static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache);
++
++static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
++{
++ struct netdev_alloc_cache *nc;
++ void *data = NULL;
++ int order;
++ unsigned long flags;
+
-+ if (status->chains) {
-+ /* antenna and antenna signal fields */
-+ len += 2 * hweight8(status->chains);
++ local_irq_save(flags);
++ nc = this_cpu_ptr(&netdev_alloc_cache);
++ if (unlikely(!nc->frag.page)) {
++refill:
++ for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) {
++ gfp_t gfp = gfp_mask;
++
++ if (order)
++ gfp |= __GFP_COMP | __GFP_NOWARN |
++ __GFP_NOMEMALLOC;
++ nc->frag.page = alloc_pages(gfp, order);
++ if (likely(nc->frag.page))
++ break;
++ if (--order < 0)
++ goto end;
++ }
++ nc->frag.size = PAGE_SIZE << order;
++ /* Even if we own the page, we do not use atomic_set().
++ * This would break get_page_unless_zero() users.
++ */
++ atomic_add(NETDEV_PAGECNT_MAX_BIAS - 1,
++ &nc->frag.page->_count);
++ nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS;
++ nc->frag.offset = 0;
++ }
++
++ if (nc->frag.offset + fragsz > nc->frag.size) {
++ if (atomic_read(&nc->frag.page->_count) != nc->pagecnt_bias) {
++ if (!atomic_sub_and_test(nc->pagecnt_bias,
++ &nc->frag.page->_count))
++ goto refill;
++ /* OK, page count is 0, we can safely set it */
++ atomic_set(&nc->frag.page->_count,
++ NETDEV_PAGECNT_MAX_BIAS);
++ } else {
++ atomic_add(NETDEV_PAGECNT_MAX_BIAS - nc->pagecnt_bias,
++ &nc->frag.page->_count);
++ }
++ nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS;
++ nc->frag.offset = 0;
+ }
+
-+ return len;
++ data = page_address(nc->frag.page) + nc->frag.offset;
++ nc->frag.offset += fragsz;
++ nc->pagecnt_bias--;
++end:
++ local_irq_restore(flags);
++ return data;
+}
+
-+/*
-+ * ieee80211_add_rx_radiotap_header - add radiotap header
-+ *
-+ * add a radiotap header containing all the fields which the hardware provided.
-+ */
-+static void
-+ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
-+ struct sk_buff *skb,
-+ struct ieee80211_rate *rate,
-+ int rtap_len, bool has_fcs)
-+{
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_radiotap_header *rthdr;
-+ unsigned char *pos;
-+ __le32 *it_present;
-+ u32 it_present_val;
-+ u16 rx_flags = 0;
-+ u16 channel_flags = 0;
-+ int mpdulen, chain;
-+ unsigned long chains = status->chains;
-+
-+ mpdulen = skb->len;
-+ if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
-+ mpdulen += FCS_LEN;
-+
-+ rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
-+ memset(rthdr, 0, rtap_len);
-+ it_present = &rthdr->it_present;
-+
-+ /* radiotap header, set always present flags */
-+ rthdr->it_len = cpu_to_le16(rtap_len);
-+ it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) |
-+ BIT(IEEE80211_RADIOTAP_CHANNEL) |
-+ BIT(IEEE80211_RADIOTAP_RX_FLAGS);
-+
-+ if (!status->chains)
-+ it_present_val |= BIT(IEEE80211_RADIOTAP_ANTENNA);
-+
-+ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
-+ it_present_val |=
-+ BIT(IEEE80211_RADIOTAP_EXT) |
-+ BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE);
-+ put_unaligned_le32(it_present_val, it_present);
-+ it_present++;
-+ it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) |
-+ BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
-+ }
-+
-+ put_unaligned_le32(it_present_val, it_present);
-+
-+ pos = (void *)(it_present + 1);
-+
-+ /* the order of the following fields is important */
-+
-+ /* IEEE80211_RADIOTAP_TSFT */
-+ if (ieee80211_have_rx_timestamp(status)) {
-+ /* padding */
-+ while ((pos - (u8 *)rthdr) & 7)
-+ *pos++ = 0;
-+ put_unaligned_le64(
-+ ieee80211_calculate_rx_timestamp(local, status,
-+ mpdulen, 0),
-+ pos);
-+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
-+ pos += 8;
-+ }
-+
-+ /* IEEE80211_RADIOTAP_FLAGS */
-+ if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))
-+ *pos |= IEEE80211_RADIOTAP_F_FCS;
-+ if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
-+ *pos |= IEEE80211_RADIOTAP_F_BADFCS;
-+ if (status->flag & RX_FLAG_SHORTPRE)
-+ *pos |= IEEE80211_RADIOTAP_F_SHORTPRE;
-+ pos++;
-+
-+ /* IEEE80211_RADIOTAP_RATE */
-+ if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) {
-+ /*
-+ * Without rate information don't add it. If we have,
-+ * MCS information is a separate field in radiotap,
-+ * added below. The byte here is needed as padding
-+ * for the channel though, so initialise it to 0.
-+ */
-+ *pos = 0;
-+ } else {
-+ int shift = 0;
-+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
-+ if (status->flag & RX_FLAG_10MHZ)
-+ shift = 1;
-+ else if (status->flag & RX_FLAG_5MHZ)
-+ shift = 2;
-+ *pos = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift));
-+ }
-+ pos++;
-+
-+ /* IEEE80211_RADIOTAP_CHANNEL */
-+ put_unaligned_le16(status->freq, pos);
-+ pos += 2;
-+ if (status->flag & RX_FLAG_10MHZ)
-+ channel_flags |= IEEE80211_CHAN_HALF;
-+ else if (status->flag & RX_FLAG_5MHZ)
-+ channel_flags |= IEEE80211_CHAN_QUARTER;
-+
-+ if (status->band == IEEE80211_BAND_5GHZ)
-+ channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ;
-+ else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
-+ channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
-+ else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
-+ channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ;
-+ else if (rate)
-+ channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ;
-+ else
-+ channel_flags |= IEEE80211_CHAN_2GHZ;
-+ put_unaligned_le16(channel_flags, pos);
-+ pos += 2;
-+
-+ /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
-+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM &&
-+ !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
-+ *pos = status->signal;
-+ rthdr->it_present |=
-+ cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
-+ pos++;
-+ }
-+
-+ /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
-+
-+ if (!status->chains) {
-+ /* IEEE80211_RADIOTAP_ANTENNA */
-+ *pos = status->antenna;
-+ pos++;
-+ }
-+
-+ /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
-+
-+ /* IEEE80211_RADIOTAP_RX_FLAGS */
-+ /* ensure 2 byte alignment for the 2 byte field as required */
-+ if ((pos - (u8 *)rthdr) & 1)
-+ *pos++ = 0;
-+ if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
-+ rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
-+ put_unaligned_le16(rx_flags, pos);
-+ pos += 2;
-+
-+ if (status->flag & RX_FLAG_HT) {
-+ unsigned int stbc;
-+
-+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
-+ *pos++ = local->hw.radiotap_mcs_details;
-+ *pos = 0;
-+ if (status->flag & RX_FLAG_SHORT_GI)
-+ *pos |= IEEE80211_RADIOTAP_MCS_SGI;
-+ if (status->flag & RX_FLAG_40MHZ)
-+ *pos |= IEEE80211_RADIOTAP_MCS_BW_40;
-+ if (status->flag & RX_FLAG_HT_GF)
-+ *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;
-+ if (status->flag & RX_FLAG_LDPC)
-+ *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC;
-+ stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT;
-+ *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT;
-+ pos++;
-+ *pos++ = status->rate_idx;
-+ }
-+
-+ if (status->flag & RX_FLAG_AMPDU_DETAILS) {
-+ u16 flags = 0;
-+
-+ /* ensure 4 byte alignment */
-+ while ((pos - (u8 *)rthdr) & 3)
-+ pos++;
-+ rthdr->it_present |=
-+ cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
-+ put_unaligned_le32(status->ampdu_reference, pos);
-+ pos += 4;
-+ if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN)
-+ flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN;
-+ if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN)
-+ flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN;
-+ if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN)
-+ flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN;
-+ if (status->flag & RX_FLAG_AMPDU_IS_LAST)
-+ flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST;
-+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR)
-+ flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR;
-+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
-+ flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN;
-+ put_unaligned_le16(flags, pos);
-+ pos += 2;
-+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
-+ *pos++ = status->ampdu_delimiter_crc;
-+ else
-+ *pos++ = 0;
-+ *pos++ = 0;
-+ }
-+
-+ if (status->flag & RX_FLAG_VHT) {
-+ u16 known = local->hw.radiotap_vht_details;
-+
-+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
-+ /* known field - how to handle 80+80? */
-+ if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
-+ known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
-+ put_unaligned_le16(known, pos);
-+ pos += 2;
-+ /* flags */
-+ if (status->flag & RX_FLAG_SHORT_GI)
-+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
-+ /* in VHT, STBC is binary */
-+ if (status->flag & RX_FLAG_STBC_MASK)
-+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
-+ if (status->vht_flag & RX_VHT_FLAG_BF)
-+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
-+ pos++;
-+ /* bandwidth */
-+ if (status->vht_flag & RX_VHT_FLAG_80MHZ)
-+ *pos++ = 4;
-+ else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ)
-+ *pos++ = 0; /* marked not known above */
-+ else if (status->vht_flag & RX_VHT_FLAG_160MHZ)
-+ *pos++ = 11;
-+ else if (status->flag & RX_FLAG_40MHZ)
-+ *pos++ = 1;
-+ else /* 20 MHz */
-+ *pos++ = 0;
-+ /* MCS/NSS */
-+ *pos = (status->rate_idx << 4) | status->vht_nss;
-+ pos += 4;
-+ /* coding field */
-+ if (status->flag & RX_FLAG_LDPC)
-+ *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0;
-+ pos++;
-+ /* group ID */
-+ pos++;
-+ /* partial_aid */
-+ pos += 2;
-+ }
-+
-+ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
-+ *pos++ = status->chain_signal[chain];
-+ *pos++ = chain;
-+ }
++/**
++ * netdev_alloc_frag - allocate a page fragment
++ * @fragsz: fragment size
++ *
++ * Allocates a frag from a page for receive buffer.
++ * Uses GFP_ATOMIC allocations.
++ */
++void *netdev_alloc_frag(unsigned int fragsz)
++{
++ return __netdev_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD);
+}
++EXPORT_SYMBOL(netdev_alloc_frag);
+
-+/*
-+ * This function copies a received frame to all monitor interfaces and
-+ * returns a cleaned-up SKB that no longer includes the FCS nor the
-+ * radiotap header the driver might have added.
++/**
++ * __netdev_alloc_skb - allocate an skbuff for rx on a specific device
++ * @dev: network device to receive on
++ * @length: length to allocate
++ * @gfp_mask: get_free_pages mask, passed to alloc_skb
++ *
++ * Allocate a new &sk_buff and assign it a usage count of one. The
++ * buffer has unspecified headroom built in. Users should allocate
++ * the headroom they think they need without accounting for the
++ * built in space. The built in space is used for optimisations.
++ *
++ * %NULL is returned if there is no free memory.
+ */
-+static struct sk_buff *
-+ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
-+ struct ieee80211_rate *rate)
++struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
++ unsigned int length, gfp_t gfp_mask)
+{
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
-+ struct ieee80211_sub_if_data *sdata;
-+ int needed_headroom;
-+ struct sk_buff *skb, *skb2;
-+ struct net_device *prev_dev = NULL;
-+ int present_fcs_len = 0;
++ struct sk_buff *skb = NULL;
++ unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +
++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
-+ /*
-+ * First, we may need to make a copy of the skb because
-+ * (1) we need to modify it for radiotap (if not present), and
-+ * (2) the other RX handlers will modify the skb we got.
-+ *
-+ * We don't need to, of course, if we aren't going to return
-+ * the SKB because it has a bad FCS/PLCP checksum.
-+ */
++ if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) {
++ void *data;
+
-+ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
-+ present_fcs_len = FCS_LEN;
++ if (sk_memalloc_socks())
++ gfp_mask |= __GFP_MEMALLOC;
+
-+ /* ensure hdr->frame_control is in skb head */
-+ if (!pskb_may_pull(origskb, 2)) {
-+ dev_kfree_skb(origskb);
-+ return NULL;
-+ }
++ data = __netdev_alloc_frag(fragsz, gfp_mask);
+
-+ if (!local->monitors) {
-+ if (should_drop_frame(origskb, present_fcs_len)) {
-+ dev_kfree_skb(origskb);
-+ return NULL;
++ if (likely(data)) {
++ skb = build_skb(data, fragsz);
++ if (unlikely(!skb))
++ put_page(virt_to_head_page(data));
+ }
-+
-+ return remove_monitor_info(local, origskb);
++ } else {
++ skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask,
++ SKB_ALLOC_RX, NUMA_NO_NODE);
++ }
++ if (likely(skb)) {
++ skb_reserve(skb, NET_SKB_PAD);
++ skb->dev = dev;
+ }
++ return skb;
++}
++EXPORT_SYMBOL(__netdev_alloc_skb);
+
-+ /* room for the radiotap header based on driver features */
-+ needed_headroom = ieee80211_rx_radiotap_space(local, status);
++void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
++ int size, unsigned int truesize)
++{
++ skb_fill_page_desc(skb, i, page, off, size);
++ skb->len += size;
++ skb->data_len += size;
++ skb->truesize += truesize;
++}
++EXPORT_SYMBOL(skb_add_rx_frag);
+
-+ if (should_drop_frame(origskb, present_fcs_len)) {
-+ /* only need to expand headroom if necessary */
-+ skb = origskb;
-+ origskb = NULL;
++void skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size,
++ unsigned int truesize)
++{
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
-+ /*
-+ * This shouldn't trigger often because most devices have an
-+ * RX header they pull before we get here, and that should
-+ * be big enough for our radiotap information. We should
-+ * probably export the length to drivers so that we can have
-+ * them allocate enough headroom to start with.
-+ */
-+ if (skb_headroom(skb) < needed_headroom &&
-+ pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) {
-+ dev_kfree_skb(skb);
-+ return NULL;
-+ }
-+ } else {
-+ /*
-+ * Need to make a copy and possibly remove radiotap header
-+ * and FCS from the original.
-+ */
-+ skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC);
++ skb_frag_size_add(frag, size);
++ skb->len += size;
++ skb->data_len += size;
++ skb->truesize += truesize;
++}
++EXPORT_SYMBOL(skb_coalesce_rx_frag);
+
-+ origskb = remove_monitor_info(local, origskb);
++static void skb_drop_list(struct sk_buff **listp)
++{
++ kfree_skb_list(*listp);
++ *listp = NULL;
++}
+
-+ if (!skb)
-+ return origskb;
-+ }
++static inline void skb_drop_fraglist(struct sk_buff *skb)
++{
++ skb_drop_list(&skb_shinfo(skb)->frag_list);
++}
+
-+ /* prepend radiotap information */
-+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
-+ true);
++static void skb_clone_fraglist(struct sk_buff *skb)
++{
++ struct sk_buff *list;
+
-+ skb_reset_mac_header(skb);
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ skb->protocol = htons(ETH_P_802_2);
++ skb_walk_frags(skb, list)
++ skb_get(list);
++}
+
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+ if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
-+ continue;
++static void skb_free_head(struct sk_buff *skb)
++{
++ if (skb->head_frag)
++ put_page(virt_to_head_page(skb->head));
++ else
++ kfree(skb->head);
++}
+
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
-+ continue;
++static void skb_release_data(struct sk_buff *skb)
++{
++ struct skb_shared_info *shinfo = skb_shinfo(skb);
++ int i;
+
-+ if (!ieee80211_sdata_running(sdata))
-+ continue;
++ if (skb->cloned &&
++ atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
++ &shinfo->dataref))
++ return;
+
-+ if (prev_dev) {
-+ skb2 = skb_clone(skb, GFP_ATOMIC);
-+ if (skb2) {
-+ skb2->dev = prev_dev;
-+ netif_receive_skb(skb2);
-+ }
-+ }
++ for (i = 0; i < shinfo->nr_frags; i++)
++ __skb_frag_unref(&shinfo->frags[i]);
++
++ /*
++ * If skb buf is from userspace, we need to notify the caller
++ * the lower device DMA has done;
++ */
++ if (shinfo->tx_flags & SKBTX_DEV_ZEROCOPY) {
++ struct ubuf_info *uarg;
+
-+ prev_dev = sdata->dev;
-+ sdata->dev->stats.rx_packets++;
-+ sdata->dev->stats.rx_bytes += skb->len;
++ uarg = shinfo->destructor_arg;
++ if (uarg->callback)
++ uarg->callback(uarg, true);
+ }
+
-+ if (prev_dev) {
-+ skb->dev = prev_dev;
-+ netif_receive_skb(skb);
-+ } else
-+ dev_kfree_skb(skb);
++ if (shinfo->frag_list)
++ kfree_skb_list(shinfo->frag_list);
+
-+ return origskb;
++ skb_free_head(skb);
+}
+
-+static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
++/*
++ * Free an skbuff by memory without cleaning the state.
++ */
++static void kfree_skbmem(struct sk_buff *skb)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-+ int tid, seqno_idx, security_idx;
++ struct sk_buff_fclones *fclones;
+
-+ /* does the frame have a qos control field? */
-+ if (ieee80211_is_data_qos(hdr->frame_control)) {
-+ u8 *qc = ieee80211_get_qos_ctl(hdr);
-+ /* frame has qos control */
-+ tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
-+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
-+ status->rx_flags |= IEEE80211_RX_AMSDU;
++ switch (skb->fclone) {
++ case SKB_FCLONE_UNAVAILABLE:
++ kmem_cache_free(skbuff_head_cache, skb);
++ break;
+
-+ seqno_idx = tid;
-+ security_idx = tid;
-+ } else {
-+ /*
-+ * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"):
-+ *
-+ * Sequence numbers for management frames, QoS data
-+ * frames with a broadcast/multicast address in the
-+ * Address 1 field, and all non-QoS data frames sent
-+ * by QoS STAs are assigned using an additional single
-+ * modulo-4096 counter, [...]
-+ *
-+ * We also use that counter for non-QoS STAs.
++ case SKB_FCLONE_ORIG:
++ fclones = container_of(skb, struct sk_buff_fclones, skb1);
++ if (atomic_dec_and_test(&fclones->fclone_ref))
++ kmem_cache_free(skbuff_fclone_cache, fclones);
++ break;
++
++ case SKB_FCLONE_CLONE:
++ fclones = container_of(skb, struct sk_buff_fclones, skb2);
++
++ /* The clone portion is available for
++ * fast-cloning again.
+ */
-+ seqno_idx = IEEE80211_NUM_TIDS;
-+ security_idx = 0;
-+ if (ieee80211_is_mgmt(hdr->frame_control))
-+ security_idx = IEEE80211_NUM_TIDS;
-+ tid = 0;
++ skb->fclone = SKB_FCLONE_FREE;
++
++ if (atomic_dec_and_test(&fclones->fclone_ref))
++ kmem_cache_free(skbuff_fclone_cache, fclones);
++ break;
++ }
++}
++
++static void skb_release_head_state(struct sk_buff *skb)
++{
++ skb_dst_drop(skb);
++#ifdef CONFIG_XFRM
++ secpath_put(skb->sp);
++#endif
++ if (skb->destructor) {
++ WARN_ON(in_irq());
++ skb->destructor(skb);
+ }
++#if IS_ENABLED(CONFIG_NF_CONNTRACK)
++ nf_conntrack_put(skb->nfct);
++#endif
++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
++ nf_bridge_put(skb->nf_bridge);
++#endif
++/* XXX: IS this still necessary? - JHS */
++#ifdef CONFIG_NET_SCHED
++ skb->tc_index = 0;
++#ifdef CONFIG_NET_CLS_ACT
++ skb->tc_verd = 0;
++#endif
++#endif
++}
+
-+ rx->seqno_idx = seqno_idx;
-+ rx->security_idx = security_idx;
-+ /* Set skb->priority to 1d tag if highest order bit of TID is not set.
-+ * For now, set skb->priority to 0 for other cases. */
-+ rx->skb->priority = (tid > 7) ? 0 : tid;
++/* Free everything but the sk_buff shell. */
++static void skb_release_all(struct sk_buff *skb)
++{
++ skb_release_head_state(skb);
++ if (likely(skb->head))
++ skb_release_data(skb);
+}
+
+/**
-+ * DOC: Packet alignment
-+ *
-+ * Drivers always need to pass packets that are aligned to two-byte boundaries
-+ * to the stack.
-+ *
-+ * Additionally, should, if possible, align the payload data in a way that
-+ * guarantees that the contained IP header is aligned to a four-byte
-+ * boundary. In the case of regular frames, this simply means aligning the
-+ * payload to a four-byte boundary (because either the IP header is directly
-+ * contained, or IV/RFC1042 headers that have a length divisible by four are
-+ * in front of it). If the payload data is not properly aligned and the
-+ * architecture doesn't support efficient unaligned operations, mac80211
-+ * will align the data.
-+ *
-+ * With A-MSDU frames, however, the payload data address must yield two modulo
-+ * four because there are 14-byte 802.3 headers within the A-MSDU frames that
-+ * push the IP header further back to a multiple of four again. Thankfully, the
-+ * specs were sane enough this time around to require padding each A-MSDU
-+ * subframe to a length that is a multiple of four.
++ * __kfree_skb - private function
++ * @skb: buffer
+ *
-+ * Padding like Atheros hardware adds which is between the 802.11 header and
-+ * the payload is not supported, the driver is required to move the 802.11
-+ * header to be directly in front of the payload in that case.
++ * Free an sk_buff. Release anything attached to the buffer.
++ * Clean the state. This is an internal helper function. Users should
++ * always call kfree_skb
+ */
-+static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
++
++void __kfree_skb(struct sk_buff *skb)
+{
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ WARN_ONCE((unsigned long)rx->skb->data & 1,
-+ "unaligned packet at 0x%p\n", rx->skb->data);
-+#endif
++ skb_release_all(skb);
++ kfree_skbmem(skb);
+}
++EXPORT_SYMBOL(__kfree_skb);
+
-+
-+/* rx handlers */
-+
-+static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)
++/**
++ * kfree_skb - free an sk_buff
++ * @skb: buffer to free
++ *
++ * Drop a reference to the buffer and free it if the usage count has
++ * hit zero.
++ */
++void kfree_skb(struct sk_buff *skb)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ if (unlikely(!skb))
++ return;
++ if (likely(atomic_read(&skb->users) == 1))
++ smp_rmb();
++ else if (likely(!atomic_dec_and_test(&skb->users)))
++ return;
++ trace_kfree_skb(skb, __builtin_return_address(0));
++ __kfree_skb(skb);
++}
++EXPORT_SYMBOL(kfree_skb);
+
-+ if (is_multicast_ether_addr(hdr->addr1))
-+ return 0;
++void kfree_skb_list(struct sk_buff *segs)
++{
++ while (segs) {
++ struct sk_buff *next = segs->next;
+
-+ return ieee80211_is_robust_mgmt_frame(skb);
++ kfree_skb(segs);
++ segs = next;
++ }
+}
++EXPORT_SYMBOL(kfree_skb_list);
+
-+
-+static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb)
++/**
++ * skb_tx_error - report an sk_buff xmit error
++ * @skb: buffer that triggered an error
++ *
++ * Report xmit error if a device callback is tracking this skb.
++ * skb must be freed afterwards.
++ */
++void skb_tx_error(struct sk_buff *skb)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
++ if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
++ struct ubuf_info *uarg;
+
-+ if (!is_multicast_ether_addr(hdr->addr1))
-+ return 0;
++ uarg = skb_shinfo(skb)->destructor_arg;
++ if (uarg->callback)
++ uarg->callback(uarg, false);
++ skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
++ }
++}
++EXPORT_SYMBOL(skb_tx_error);
+
-+ return ieee80211_is_robust_mgmt_frame(skb);
++/**
++ * consume_skb - free an skbuff
++ * @skb: buffer to free
++ *
++ * Drop a ref to the buffer and free it if the usage count has hit zero
++ * Functions identically to kfree_skb, but kfree_skb assumes that the frame
++ * is being dropped after a failure and notes that
++ */
++void consume_skb(struct sk_buff *skb)
++{
++ if (unlikely(!skb))
++ return;
++ if (likely(atomic_read(&skb->users) == 1))
++ smp_rmb();
++ else if (likely(!atomic_dec_and_test(&skb->users)))
++ return;
++ trace_consume_skb(skb);
++ __kfree_skb(skb);
+}
++EXPORT_SYMBOL(consume_skb);
+
++/* Make sure a field is enclosed inside headers_start/headers_end section */
++#define CHECK_SKB_FIELD(field) \
++ BUILD_BUG_ON(offsetof(struct sk_buff, field) < \
++ offsetof(struct sk_buff, headers_start)); \
++ BUILD_BUG_ON(offsetof(struct sk_buff, field) > \
++ offsetof(struct sk_buff, headers_end)); \
+
-+/* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */
-+static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
++static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+{
-+ struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data;
-+ struct ieee80211_mmie *mmie;
-+
-+ if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
-+ return -1;
++ new->tstamp = old->tstamp;
++ /* We do not copy old->sk */
++ new->dev = old->dev;
++ memcpy(new->cb, old->cb, sizeof(old->cb));
++ skb_dst_copy(new, old);
++#ifdef CONFIG_XFRM
++ new->sp = secpath_get(old->sp);
++#endif
++ __nf_copy(new, old, false);
+
-+ if (!ieee80211_is_robust_mgmt_frame(skb))
-+ return -1; /* not a robust management frame */
++ /* Note : this field could be in headers_start/headers_end section
++ * It is not yet because we do not want to have a 16 bit hole
++ */
++ new->queue_mapping = old->queue_mapping;
+
-+ mmie = (struct ieee80211_mmie *)
-+ (skb->data + skb->len - sizeof(*mmie));
-+ if (mmie->element_id != WLAN_EID_MMIE ||
-+ mmie->length != sizeof(*mmie) - 2)
-+ return -1;
++ memcpy(&new->headers_start, &old->headers_start,
++ offsetof(struct sk_buff, headers_end) -
++ offsetof(struct sk_buff, headers_start));
++ CHECK_SKB_FIELD(protocol);
++ CHECK_SKB_FIELD(csum);
++ CHECK_SKB_FIELD(hash);
++ CHECK_SKB_FIELD(priority);
++ CHECK_SKB_FIELD(skb_iif);
++ CHECK_SKB_FIELD(vlan_proto);
++ CHECK_SKB_FIELD(vlan_tci);
++ CHECK_SKB_FIELD(transport_header);
++ CHECK_SKB_FIELD(network_header);
++ CHECK_SKB_FIELD(mac_header);
++ CHECK_SKB_FIELD(inner_protocol);
++ CHECK_SKB_FIELD(inner_transport_header);
++ CHECK_SKB_FIELD(inner_network_header);
++ CHECK_SKB_FIELD(inner_mac_header);
++ CHECK_SKB_FIELD(mark);
++#ifdef CONFIG_NETWORK_SECMARK
++ CHECK_SKB_FIELD(secmark);
++#endif
++#ifdef CONFIG_NET_RX_BUSY_POLL
++ CHECK_SKB_FIELD(napi_id);
++#endif
++#ifdef CONFIG_NET_SCHED
++ CHECK_SKB_FIELD(tc_index);
++#ifdef CONFIG_NET_CLS_ACT
++ CHECK_SKB_FIELD(tc_verd);
++#endif
++#endif
+
-+ return le16_to_cpu(mmie->key_id);
+}
+
-+static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
-+ struct sk_buff *skb)
++/*
++ * You should not add any new code to this function. Add it to
++ * __copy_skb_header above instead.
++ */
++static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ __le16 fc;
-+ int hdrlen;
-+ u8 keyid;
++#define C(x) n->x = skb->x
+
-+ fc = hdr->frame_control;
-+ hdrlen = ieee80211_hdrlen(fc);
++ n->next = n->prev = NULL;
++ n->sk = NULL;
++ __copy_skb_header(n, skb);
+
-+ if (skb->len < hdrlen + cs->hdr_len)
-+ return -EINVAL;
++ C(len);
++ C(data_len);
++ C(mac_len);
++ n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
++ n->cloned = 1;
++ n->nohdr = 0;
++ n->destructor = NULL;
++ C(tail);
++ C(end);
++ C(head);
++ C(head_frag);
++ C(data);
++ C(truesize);
++ atomic_set(&n->users, 1);
+
-+ skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
-+ keyid &= cs->key_idx_mask;
-+ keyid >>= cs->key_idx_shift;
++ atomic_inc(&(skb_shinfo(skb)->dataref));
++ skb->cloned = 1;
++
++ return n;
++#undef C
++}
+
-+ return keyid;
++/**
++ * skb_morph - morph one skb into another
++ * @dst: the skb to receive the contents
++ * @src: the skb to supply the contents
++ *
++ * This is identical to skb_clone except that the target skb is
++ * supplied by the user.
++ *
++ * The target skb is returned upon exit.
++ */
++struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
++{
++ skb_release_all(dst);
++ return __skb_clone(dst, src);
+}
++EXPORT_SYMBOL_GPL(skb_morph);
+
-+static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
++/**
++ * skb_copy_ubufs - copy userspace skb frags buffers to kernel
++ * @skb: the skb to modify
++ * @gfp_mask: allocation priority
++ *
++ * This must be called on SKBTX_DEV_ZEROCOPY skb.
++ * It will copy all frags into kernel and drop the reference
++ * to userspace pages.
++ *
++ * If this function is called from an interrupt gfp_mask() must be
++ * %GFP_ATOMIC.
++ *
++ * Returns 0 on success or a negative error code on failure
++ * to allocate kernel memory to copy to.
++ */
++int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ char *dev_addr = rx->sdata->vif.addr;
++ int i;
++ int num_frags = skb_shinfo(skb)->nr_frags;
++ struct page *page, *head = NULL;
++ struct ubuf_info *uarg = skb_shinfo(skb)->destructor_arg;
+
-+ if (ieee80211_is_data(hdr->frame_control)) {
-+ if (is_multicast_ether_addr(hdr->addr1)) {
-+ if (ieee80211_has_tods(hdr->frame_control) ||
-+ !ieee80211_has_fromds(hdr->frame_control))
-+ return RX_DROP_MONITOR;
-+ if (ether_addr_equal(hdr->addr3, dev_addr))
-+ return RX_DROP_MONITOR;
-+ } else {
-+ if (!ieee80211_has_a4(hdr->frame_control))
-+ return RX_DROP_MONITOR;
-+ if (ether_addr_equal(hdr->addr4, dev_addr))
-+ return RX_DROP_MONITOR;
++ for (i = 0; i < num_frags; i++) {
++ u8 *vaddr;
++ skb_frag_t *f = &skb_shinfo(skb)->frags[i];
++
++ page = alloc_page(gfp_mask);
++ if (!page) {
++ while (head) {
++ struct page *next = (struct page *)page_private(head);
++ put_page(head);
++ head = next;
++ }
++ return -ENOMEM;
+ }
++ vaddr = kmap_atomic(skb_frag_page(f));
++ memcpy(page_address(page),
++ vaddr + f->page_offset, skb_frag_size(f));
++ kunmap_atomic(vaddr);
++ set_page_private(page, (unsigned long)head);
++ head = page;
+ }
+
-+ /* If there is not an established peer link and this is not a peer link
-+ * establisment frame, beacon or probe, drop the frame.
-+ */
++ /* skb frags release userspace buffers */
++ for (i = 0; i < num_frags; i++)
++ skb_frag_unref(skb, i);
++
++ uarg->callback(uarg, false);
++
++ /* skb frags point to kernel buffers */
++ for (i = num_frags - 1; i >= 0; i--) {
++ __skb_fill_page_desc(skb, i, head, 0,
++ skb_shinfo(skb)->frags[i].size);
++ head = (struct page *)page_private(head);
++ }
+
-+ if (!rx->sta || sta_plink_state(rx->sta) != NL80211_PLINK_ESTAB) {
-+ struct ieee80211_mgmt *mgmt;
++ skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
++ return 0;
++}
++EXPORT_SYMBOL_GPL(skb_copy_ubufs);
+
-+ if (!ieee80211_is_mgmt(hdr->frame_control))
-+ return RX_DROP_MONITOR;
++/**
++ * skb_clone - duplicate an sk_buff
++ * @skb: buffer to clone
++ * @gfp_mask: allocation priority
++ *
++ * Duplicate an &sk_buff. The new one is not owned by a socket. Both
++ * copies share the same packet data but not structure. The new
++ * buffer has a reference count of 1. If the allocation fails the
++ * function returns %NULL otherwise the new buffer is returned.
++ *
++ * If this function is called from an interrupt gfp_mask() must be
++ * %GFP_ATOMIC.
++ */
+
-+ if (ieee80211_is_action(hdr->frame_control)) {
-+ u8 category;
++struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
++{
++ struct sk_buff_fclones *fclones = container_of(skb,
++ struct sk_buff_fclones,
++ skb1);
++ struct sk_buff *n = &fclones->skb2;
+
-+ /* make sure category field is present */
-+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
-+ return RX_DROP_MONITOR;
++ if (skb_orphan_frags(skb, gfp_mask))
++ return NULL;
+
-+ mgmt = (struct ieee80211_mgmt *)hdr;
-+ category = mgmt->u.action.category;
-+ if (category != WLAN_CATEGORY_MESH_ACTION &&
-+ category != WLAN_CATEGORY_SELF_PROTECTED)
-+ return RX_DROP_MONITOR;
-+ return RX_CONTINUE;
-+ }
++ if (skb->fclone == SKB_FCLONE_ORIG &&
++ n->fclone == SKB_FCLONE_FREE) {
++ n->fclone = SKB_FCLONE_CLONE;
++ atomic_inc(&fclones->fclone_ref);
++ } else {
++ if (skb_pfmemalloc(skb))
++ gfp_mask |= __GFP_MEMALLOC;
+
-+ if (ieee80211_is_probe_req(hdr->frame_control) ||
-+ ieee80211_is_probe_resp(hdr->frame_control) ||
-+ ieee80211_is_beacon(hdr->frame_control) ||
-+ ieee80211_is_auth(hdr->frame_control))
-+ return RX_CONTINUE;
++ n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
++ if (!n)
++ return NULL;
+
-+ return RX_DROP_MONITOR;
++ kmemcheck_annotate_bitfield(n, flags1);
++ n->fclone = SKB_FCLONE_UNAVAILABLE;
+ }
+
-+ return RX_CONTINUE;
++ return __skb_clone(n, skb);
+}
++EXPORT_SYMBOL(skb_clone);
+
-+static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,
-+ struct tid_ampdu_rx *tid_agg_rx,
-+ int index,
-+ struct sk_buff_head *frames)
++static void skb_headers_offset_update(struct sk_buff *skb, int off)
+{
-+ struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index];
-+ struct sk_buff *skb;
-+ struct ieee80211_rx_status *status;
-+
-+ lockdep_assert_held(&tid_agg_rx->reorder_lock);
-+
-+ if (skb_queue_empty(skb_list))
-+ goto no_frame;
++ /* Only adjust this if it actually is csum_start rather than csum */
++ if (skb->ip_summed == CHECKSUM_PARTIAL)
++ skb->csum_start += off;
++ /* {transport,network,mac}_header and tail are relative to skb->head */
++ skb->transport_header += off;
++ skb->network_header += off;
++ if (skb_mac_header_was_set(skb))
++ skb->mac_header += off;
++ skb->inner_transport_header += off;
++ skb->inner_network_header += off;
++ skb->inner_mac_header += off;
++}
+
-+ if (!ieee80211_rx_reorder_ready(skb_list)) {
-+ __skb_queue_purge(skb_list);
-+ goto no_frame;
-+ }
++static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
++{
++ __copy_skb_header(new, old);
+
-+ /* release frames from the reorder ring buffer */
-+ tid_agg_rx->stored_mpdu_num--;
-+ while ((skb = __skb_dequeue(skb_list))) {
-+ status = IEEE80211_SKB_RXCB(skb);
-+ status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
-+ __skb_queue_tail(frames, skb);
-+ }
++ skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
++ skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
++ skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
++}
+
-+no_frame:
-+ tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);
++static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
++{
++ if (skb_pfmemalloc(skb))
++ return SKB_ALLOC_RX;
++ return 0;
+}
+
-+static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata,
-+ struct tid_ampdu_rx *tid_agg_rx,
-+ u16 head_seq_num,
-+ struct sk_buff_head *frames)
++/**
++ * skb_copy - create private copy of an sk_buff
++ * @skb: buffer to copy
++ * @gfp_mask: allocation priority
++ *
++ * Make a copy of both an &sk_buff and its data. This is used when the
++ * caller wishes to modify the data and needs a private copy of the
++ * data to alter. Returns %NULL on failure or the pointer to the buffer
++ * on success. The returned buffer has a reference count of 1.
++ *
++ * As by-product this function converts non-linear &sk_buff to linear
++ * one, so that &sk_buff becomes completely private and caller is allowed
++ * to modify all the data of returned buffer. This means that this
++ * function is not recommended for use in circumstances when only
++ * header is going to be modified. Use pskb_copy() instead.
++ */
++
++struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
+{
-+ int index;
++ int headerlen = skb_headroom(skb);
++ unsigned int size = skb_end_offset(skb) + skb->data_len;
++ struct sk_buff *n = __alloc_skb(size, gfp_mask,
++ skb_alloc_rx_flag(skb), NUMA_NO_NODE);
+
-+ lockdep_assert_held(&tid_agg_rx->reorder_lock);
++ if (!n)
++ return NULL;
+
-+ while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {
-+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
-+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
-+ frames);
-+ }
++ /* Set the data pointer */
++ skb_reserve(n, headerlen);
++ /* Set the tail pointer and length */
++ skb_put(n, skb->len);
++
++ if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len))
++ BUG();
++
++ copy_skb_header(n, skb);
++ return n;
+}
++EXPORT_SYMBOL(skb_copy);
+
-+/*
-+ * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
-+ * the skb was added to the buffer longer than this time ago, the earlier
-+ * frames that have not yet been received are assumed to be lost and the skb
-+ * can be released for processing. This may also release other skb's from the
-+ * reorder buffer if there are no additional gaps between the frames.
++/**
++ * __pskb_copy_fclone - create copy of an sk_buff with private head.
++ * @skb: buffer to copy
++ * @headroom: headroom of new skb
++ * @gfp_mask: allocation priority
++ * @fclone: if true allocate the copy of the skb from the fclone
++ * cache instead of the head cache; it is recommended to set this
++ * to true for the cases where the copy will likely be cloned
+ *
-+ * Callers must hold tid_agg_rx->reorder_lock.
++ * Make a copy of both an &sk_buff and part of its data, located
++ * in header. Fragmented data remain shared. This is used when
++ * the caller wishes to modify only header of &sk_buff and needs
++ * private copy of the header to alter. Returns %NULL on failure
++ * or the pointer to the buffer on success.
++ * The returned buffer has a reference count of 1.
+ */
-+#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
+
-+static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
-+ struct tid_ampdu_rx *tid_agg_rx,
-+ struct sk_buff_head *frames)
++struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
++ gfp_t gfp_mask, bool fclone)
+{
-+ int index, i, j;
++ unsigned int size = skb_headlen(skb) + headroom;
++ int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0);
++ struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE);
+
-+ lockdep_assert_held(&tid_agg_rx->reorder_lock);
++ if (!n)
++ goto out;
+
-+ /* release the buffer until next missing frame */
-+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
-+ if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) &&
-+ tid_agg_rx->stored_mpdu_num) {
-+ /*
-+ * No buffers ready to be released, but check whether any
-+ * frames in the reorder buffer have timed out.
-+ */
-+ int skipped = 1;
-+ for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
-+ j = (j + 1) % tid_agg_rx->buf_size) {
-+ if (!ieee80211_rx_reorder_ready(
-+ &tid_agg_rx->reorder_buf[j])) {
-+ skipped++;
-+ continue;
-+ }
-+ if (skipped &&
-+ !time_after(jiffies, tid_agg_rx->reorder_time[j] +
-+ HT_RX_REORDER_BUF_TIMEOUT))
-+ goto set_release_timer;
++ /* Set the data pointer */
++ skb_reserve(n, headroom);
++ /* Set the tail pointer and length */
++ skb_put(n, skb_headlen(skb));
++ /* Copy the bytes */
++ skb_copy_from_linear_data(skb, n->data, n->len);
+
-+ /* don't leave incomplete A-MSDUs around */
-+ for (i = (index + 1) % tid_agg_rx->buf_size; i != j;
-+ i = (i + 1) % tid_agg_rx->buf_size)
-+ __skb_queue_purge(&tid_agg_rx->reorder_buf[i]);
++ n->truesize += skb->data_len;
++ n->data_len = skb->data_len;
++ n->len = skb->len;
+
-+ ht_dbg_ratelimited(sdata,
-+ "release an RX reorder frame due to timeout on earlier frames\n");
-+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, j,
-+ frames);
++ if (skb_shinfo(skb)->nr_frags) {
++ int i;
+
-+ /*
-+ * Increment the head seq# also for the skipped slots.
-+ */
-+ tid_agg_rx->head_seq_num =
-+ (tid_agg_rx->head_seq_num +
-+ skipped) & IEEE80211_SN_MASK;
-+ skipped = 0;
++ if (skb_orphan_frags(skb, gfp_mask)) {
++ kfree_skb(n);
++ n = NULL;
++ goto out;
+ }
-+ } else while (ieee80211_rx_reorder_ready(
-+ &tid_agg_rx->reorder_buf[index])) {
-+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
-+ frames);
-+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
-+ }
-+
-+ if (tid_agg_rx->stored_mpdu_num) {
-+ j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
-+
-+ for (; j != (index - 1) % tid_agg_rx->buf_size;
-+ j = (j + 1) % tid_agg_rx->buf_size) {
-+ if (ieee80211_rx_reorder_ready(
-+ &tid_agg_rx->reorder_buf[j]))
-+ break;
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
++ skb_frag_ref(skb, i);
+ }
++ skb_shinfo(n)->nr_frags = i;
++ }
+
-+ set_release_timer:
-+
-+ mod_timer(&tid_agg_rx->reorder_timer,
-+ tid_agg_rx->reorder_time[j] + 1 +
-+ HT_RX_REORDER_BUF_TIMEOUT);
-+ } else {
-+ del_timer(&tid_agg_rx->reorder_timer);
++ if (skb_has_frag_list(skb)) {
++ skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
++ skb_clone_fraglist(n);
+ }
++
++ copy_skb_header(n, skb);
++out:
++ return n;
+}
++EXPORT_SYMBOL(__pskb_copy_fclone);
+
-+/*
-+ * As this function belongs to the RX path it must be under
-+ * rcu_read_lock protection. It returns false if the frame
-+ * can be processed immediately, true if it was consumed.
++/**
++ * pskb_expand_head - reallocate header of &sk_buff
++ * @skb: buffer to reallocate
++ * @nhead: room to add at head
++ * @ntail: room to add at tail
++ * @gfp_mask: allocation priority
++ *
++ * Expands (or creates identical copy, if @nhead and @ntail are zero)
++ * header of @skb. &sk_buff itself is not changed. &sk_buff MUST have
++ * reference count of 1. Returns zero in the case of success or error,
++ * if expansion failed. In the last case, &sk_buff is not changed.
++ *
++ * All the pointers pointing into skb header may change and must be
++ * reloaded after call to this function.
+ */
-+static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata,
-+ struct tid_ampdu_rx *tid_agg_rx,
-+ struct sk_buff *skb,
-+ struct sk_buff_head *frames)
++
++int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
++ gfp_t gfp_mask)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ u16 sc = le16_to_cpu(hdr->seq_ctrl);
-+ u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
-+ u16 head_seq_num, buf_size;
-+ int index;
-+ bool ret = true;
++ int i;
++ u8 *data;
++ int size = nhead + skb_end_offset(skb) + ntail;
++ long off;
+
-+ spin_lock(&tid_agg_rx->reorder_lock);
++ BUG_ON(nhead < 0);
+
-+ /*
-+ * Offloaded BA sessions have no known starting sequence number so pick
-+ * one from first Rxed frame for this tid after BA was started.
-+ */
-+ if (unlikely(tid_agg_rx->auto_seq)) {
-+ tid_agg_rx->auto_seq = false;
-+ tid_agg_rx->ssn = mpdu_seq_num;
-+ tid_agg_rx->head_seq_num = mpdu_seq_num;
-+ }
++ if (skb_shared(skb))
++ BUG();
+
-+ buf_size = tid_agg_rx->buf_size;
-+ head_seq_num = tid_agg_rx->head_seq_num;
++ size = SKB_DATA_ALIGN(size);
+
-+ /* frame with out of date sequence number */
-+ if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {
-+ dev_kfree_skb(skb);
-+ goto out;
-+ }
++ if (skb_pfmemalloc(skb))
++ gfp_mask |= __GFP_MEMALLOC;
++ data = kmalloc_reserve(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
++ gfp_mask, NUMA_NO_NODE, NULL);
++ if (!data)
++ goto nodata;
++ size = SKB_WITH_OVERHEAD(ksize(data));
+
-+ /*
-+ * If frame the sequence number exceeds our buffering window
-+ * size release some previous frames to make room for this one.
++ /* Copy only real data... and, alas, header. This should be
++ * optimized for the cases when header is void.
+ */
-+ if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) {
-+ head_seq_num = ieee80211_sn_inc(
-+ ieee80211_sn_sub(mpdu_seq_num, buf_size));
-+ /* release stored frames up to new head to stack */
-+ ieee80211_release_reorder_frames(sdata, tid_agg_rx,
-+ head_seq_num, frames);
-+ }
-+
-+ /* Now the new frame is always in the range of the reordering buffer */
++ memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head);
+
-+ index = mpdu_seq_num % tid_agg_rx->buf_size;
-+
-+ /* check if we already stored this frame */
-+ if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) {
-+ dev_kfree_skb(skb);
-+ goto out;
-+ }
++ memcpy((struct skb_shared_info *)(data + size),
++ skb_shinfo(skb),
++ offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
+
+ /*
-+ * If the current MPDU is in the right order and nothing else
-+ * is stored we can process it directly, no need to buffer it.
-+ * If it is first but there's something stored, we may be able
-+ * to release frames after this one.
++ * if shinfo is shared we must drop the old head gracefully, but if it
++ * is not we can just drop the old head and let the existing refcount
++ * be since all we did is relocate the values
+ */
-+ if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
-+ tid_agg_rx->stored_mpdu_num == 0) {
-+ if (!(status->flag & RX_FLAG_AMSDU_MORE))
-+ tid_agg_rx->head_seq_num =
-+ ieee80211_sn_inc(tid_agg_rx->head_seq_num);
-+ ret = false;
-+ goto out;
-+ }
++ if (skb_cloned(skb)) {
++ /* copy this zero copy skb frags */
++ if (skb_orphan_frags(skb, gfp_mask))
++ goto nofrags;
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
++ skb_frag_ref(skb, i);
++
++ if (skb_has_frag_list(skb))
++ skb_clone_fraglist(skb);
+
-+ /* put the frame in the reordering buffer */
-+ __skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb);
-+ if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
-+ tid_agg_rx->reorder_time[index] = jiffies;
-+ tid_agg_rx->stored_mpdu_num++;
-+ ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames);
++ skb_release_data(skb);
++ } else {
++ skb_free_head(skb);
+ }
++ off = (data + nhead) - skb->head;
+
-+ out:
-+ spin_unlock(&tid_agg_rx->reorder_lock);
-+ return ret;
++ skb->head = data;
++ skb->head_frag = 0;
++ skb->data += off;
++#ifdef NET_SKBUFF_DATA_USES_OFFSET
++ skb->end = size;
++ off = nhead;
++#else
++ skb->end = skb->head + size;
++#endif
++ skb->tail += off;
++ skb_headers_offset_update(skb, nhead);
++ skb->cloned = 0;
++ skb->hdr_len = 0;
++ skb->nohdr = 0;
++ atomic_set(&skb_shinfo(skb)->dataref, 1);
++ return 0;
++
++nofrags:
++ kfree(data);
++nodata:
++ return -ENOMEM;
+}
++EXPORT_SYMBOL(pskb_expand_head);
+
-+/*
-+ * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
-+ * true if the MPDU was buffered, false if it should be processed.
-+ */
-+static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
-+ struct sk_buff_head *frames)
++/* Make private copy of skb with writable head and some headroom */
++
++struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
+{
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_local *local = rx->local;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct sta_info *sta = rx->sta;
-+ struct tid_ampdu_rx *tid_agg_rx;
-+ u16 sc;
-+ u8 tid, ack_policy;
++ struct sk_buff *skb2;
++ int delta = headroom - skb_headroom(skb);
+
-+ if (!ieee80211_is_data_qos(hdr->frame_control) ||
-+ is_multicast_ether_addr(hdr->addr1))
-+ goto dont_reorder;
++ if (delta <= 0)
++ skb2 = pskb_copy(skb, GFP_ATOMIC);
++ else {
++ skb2 = skb_clone(skb, GFP_ATOMIC);
++ if (skb2 && pskb_expand_head(skb2, SKB_DATA_ALIGN(delta), 0,
++ GFP_ATOMIC)) {
++ kfree_skb(skb2);
++ skb2 = NULL;
++ }
++ }
++ return skb2;
++}
++EXPORT_SYMBOL(skb_realloc_headroom);
+
++/**
++ * skb_copy_expand - copy and expand sk_buff
++ * @skb: buffer to copy
++ * @newheadroom: new free bytes at head
++ * @newtailroom: new free bytes at tail
++ * @gfp_mask: allocation priority
++ *
++ * Make a copy of both an &sk_buff and its data and while doing so
++ * allocate additional space.
++ *
++ * This is used when the caller wishes to modify the data and needs a
++ * private copy of the data to alter as well as more space for new fields.
++ * Returns %NULL on failure or the pointer to the buffer
++ * on success. The returned buffer has a reference count of 1.
++ *
++ * You must pass %GFP_ATOMIC as the allocation priority if this function
++ * is called from an interrupt.
++ */
++struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
++ int newheadroom, int newtailroom,
++ gfp_t gfp_mask)
++{
+ /*
-+ * filter the QoS data rx stream according to
-+ * STA/TID and check if this STA/TID is on aggregation
++ * Allocate the copy buffer
+ */
++ struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom,
++ gfp_mask, skb_alloc_rx_flag(skb),
++ NUMA_NO_NODE);
++ int oldheadroom = skb_headroom(skb);
++ int head_copy_len, head_copy_off;
+
-+ if (!sta)
-+ goto dont_reorder;
++ if (!n)
++ return NULL;
+
-+ ack_policy = *ieee80211_get_qos_ctl(hdr) &
-+ IEEE80211_QOS_CTL_ACK_POLICY_MASK;
-+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
++ skb_reserve(n, newheadroom);
+
-+ tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
-+ if (!tid_agg_rx)
-+ goto dont_reorder;
++ /* Set the tail pointer and length */
++ skb_put(n, skb->len);
+
-+ /* qos null data frames are excluded */
-+ if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
-+ goto dont_reorder;
++ head_copy_len = oldheadroom;
++ head_copy_off = 0;
++ if (newheadroom <= head_copy_len)
++ head_copy_len = newheadroom;
++ else
++ head_copy_off = newheadroom - head_copy_len;
+
-+ /* not part of a BA session */
-+ if (ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
-+ ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
-+ goto dont_reorder;
++ /* Copy the linear header and data. */
++ if (skb_copy_bits(skb, -head_copy_len, n->head + head_copy_off,
++ skb->len + head_copy_len))
++ BUG();
+
-+ /* not actually part of this BA session */
-+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ goto dont_reorder;
++ copy_skb_header(n, skb);
+
-+ /* new, potentially un-ordered, ampdu frame - process it */
++ skb_headers_offset_update(n, newheadroom - oldheadroom);
+
-+ /* reset session timer */
-+ if (tid_agg_rx->timeout)
-+ tid_agg_rx->last_rx = jiffies;
++ return n;
++}
++EXPORT_SYMBOL(skb_copy_expand);
+
-+ /* if this mpdu is fragmented - terminate rx aggregation session */
-+ sc = le16_to_cpu(hdr->seq_ctrl);
-+ if (sc & IEEE80211_SCTL_FRAG) {
-+ skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
-+ skb_queue_tail(&rx->sdata->skb_queue, skb);
-+ ieee80211_queue_work(&local->hw, &rx->sdata->work);
-+ return;
++/**
++ * skb_pad - zero pad the tail of an skb
++ * @skb: buffer to pad
++ * @pad: space to pad
++ *
++ * Ensure that a buffer is followed by a padding area that is zero
++ * filled. Used by network drivers which may DMA or transfer data
++ * beyond the buffer end onto the wire.
++ *
++ * May return error in out of memory cases. The skb is freed on error.
++ */
++
++int skb_pad(struct sk_buff *skb, int pad)
++{
++ int err;
++ int ntail;
++
++ /* If the skbuff is non linear tailroom is always zero.. */
++ if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) {
++ memset(skb->data+skb->len, 0, pad);
++ return 0;
+ }
+
-+ /*
-+ * No locking needed -- we will only ever process one
-+ * RX packet at a time, and thus own tid_agg_rx. All
-+ * other code manipulating it needs to (and does) make
-+ * sure that we cannot get to it any more before doing
-+ * anything with it.
++ ntail = skb->data_len + pad - (skb->end - skb->tail);
++ if (likely(skb_cloned(skb) || ntail > 0)) {
++ err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC);
++ if (unlikely(err))
++ goto free_skb;
++ }
++
++ /* FIXME: The use of this function with non-linear skb's really needs
++ * to be audited.
+ */
-+ if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb,
-+ frames))
-+ return;
++ err = skb_linearize(skb);
++ if (unlikely(err))
++ goto free_skb;
++
++ memset(skb->data + skb->len, 0, pad);
++ return 0;
+
-+ dont_reorder:
-+ __skb_queue_tail(frames, skb);
++free_skb:
++ kfree_skb(skb);
++ return err;
+}
++EXPORT_SYMBOL(skb_pad);
++
++/**
++ * pskb_put - add data to the tail of a potentially fragmented buffer
++ * @skb: start of the buffer to use
++ * @tail: tail fragment of the buffer to use
++ * @len: amount of data to add
++ *
++ * This function extends the used data area of the potentially
++ * fragmented buffer. @tail must be the last fragment of @skb -- or
++ * @skb itself. If this would exceed the total buffer size the kernel
++ * will panic. A pointer to the first byte of the extra data is
++ * returned.
++ */
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
++unsigned char *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
++ if (tail != skb) {
++ skb->data_len += len;
++ skb->len += len;
++ }
++ return skb_put(tail, len);
++}
++EXPORT_SYMBOL_GPL(pskb_put);
+
-+ /*
-+ * Drop duplicate 802.11 retransmissions
-+ * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
-+ */
-+ if (rx->skb->len >= 24 && rx->sta &&
-+ !ieee80211_is_ctl(hdr->frame_control) &&
-+ !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
-+ !is_multicast_ether_addr(hdr->addr1)) {
-+ if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
-+ rx->sta->last_seq_ctrl[rx->seqno_idx] ==
-+ hdr->seq_ctrl)) {
-+ if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
-+ rx->local->dot11FrameDuplicateCount++;
-+ rx->sta->num_duplicates++;
-+ }
-+ return RX_DROP_UNUSABLE;
-+ } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
-+ rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
++/**
++ * skb_put - add data to a buffer
++ * @skb: buffer to use
++ * @len: amount of data to add
++ *
++ * This function extends the used data area of the buffer. If this would
++ * exceed the total buffer size the kernel will panic. A pointer to the
++ * first byte of the extra data is returned.
++ */
++unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
++{
++ unsigned char *tmp = skb_tail_pointer(skb);
++ SKB_LINEAR_ASSERT(skb);
++ skb->tail += len;
++ skb->len += len;
++ if (unlikely(skb->tail > skb->end))
++ skb_over_panic(skb, len, __builtin_return_address(0));
++ return tmp;
++}
++EXPORT_SYMBOL(skb_put);
++
++/**
++ * skb_push - add data to the start of a buffer
++ * @skb: buffer to use
++ * @len: amount of data to add
++ *
++ * This function extends the used data area of the buffer at the buffer
++ * start. If this would exceed the total buffer headroom the kernel will
++ * panic. A pointer to the first byte of the extra data is returned.
++ */
++unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
++{
++ skb->data -= len;
++ skb->len += len;
++ if (unlikely(skb->data<skb->head))
++ skb_under_panic(skb, len, __builtin_return_address(0));
++ return skb->data;
++}
++EXPORT_SYMBOL(skb_push);
++
++/**
++ * skb_pull - remove data from the start of a buffer
++ * @skb: buffer to use
++ * @len: amount of data to remove
++ *
++ * This function removes data from the start of a buffer, returning
++ * the memory to the headroom. A pointer to the next data in the buffer
++ * is returned. Once the data has been pulled future pushes will overwrite
++ * the old data.
++ */
++unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
++{
++ return skb_pull_inline(skb, len);
++}
++EXPORT_SYMBOL(skb_pull);
++
++/**
++ * skb_trim - remove end from a buffer
++ * @skb: buffer to alter
++ * @len: new length
++ *
++ * Cut the length of a buffer down by removing data from the tail. If
++ * the buffer is already under the length specified it is not modified.
++ * The skb must be linear.
++ */
++void skb_trim(struct sk_buff *skb, unsigned int len)
++{
++ if (skb->len > len)
++ __skb_trim(skb, len);
++}
++EXPORT_SYMBOL(skb_trim);
++
++/* Trims skb to length len. It can change skb pointers.
++ */
++
++int ___pskb_trim(struct sk_buff *skb, unsigned int len)
++{
++ struct sk_buff **fragp;
++ struct sk_buff *frag;
++ int offset = skb_headlen(skb);
++ int nfrags = skb_shinfo(skb)->nr_frags;
++ int i;
++ int err;
++
++ if (skb_cloned(skb) &&
++ unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
++ return err;
++
++ i = 0;
++ if (offset >= len)
++ goto drop_pages;
++
++ for (; i < nfrags; i++) {
++ int end = offset + skb_frag_size(&skb_shinfo(skb)->frags[i]);
++
++ if (end < len) {
++ offset = end;
++ continue;
+ }
-+ }
+
-+ if (unlikely(rx->skb->len < 16)) {
-+ I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
-+ return RX_DROP_MONITOR;
-+ }
++ skb_frag_size_set(&skb_shinfo(skb)->frags[i++], len - offset);
+
-+ /* Drop disallowed frame classes based on STA auth/assoc state;
-+ * IEEE 802.11, Chap 5.5.
-+ *
-+ * mac80211 filters only based on association state, i.e. it drops
-+ * Class 3 frames from not associated stations. hostapd sends
-+ * deauth/disassoc frames when needed. In addition, hostapd is
-+ * responsible for filtering on both auth and assoc states.
-+ */
++drop_pages:
++ skb_shinfo(skb)->nr_frags = i;
+
-+ if (ieee80211_vif_is_mesh(&rx->sdata->vif))
-+ return ieee80211_rx_mesh_check(rx);
++ for (; i < nfrags; i++)
++ skb_frag_unref(skb, i);
+
-+ if (unlikely((ieee80211_is_data(hdr->frame_control) ||
-+ ieee80211_is_pspoll(hdr->frame_control)) &&
-+ rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-+ rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
-+ (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
-+ /*
-+ * accept port control frames from the AP even when it's not
-+ * yet marked ASSOC to prevent a race where we don't set the
-+ * assoc bit quickly enough before it sends the first frame
-+ */
-+ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
-+ ieee80211_is_data_present(hdr->frame_control)) {
-+ unsigned int hdrlen;
-+ __be16 ethertype;
++ if (skb_has_frag_list(skb))
++ skb_drop_fraglist(skb);
++ goto done;
++ }
++
++ for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
++ fragp = &frag->next) {
++ int end = offset + frag->len;
+
-+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ if (skb_shared(frag)) {
++ struct sk_buff *nfrag;
+
-+ if (rx->skb->len < hdrlen + 8)
-+ return RX_DROP_MONITOR;
++ nfrag = skb_clone(frag, GFP_ATOMIC);
++ if (unlikely(!nfrag))
++ return -ENOMEM;
++
++ nfrag->next = frag->next;
++ consume_skb(frag);
++ frag = nfrag;
++ *fragp = frag;
++ }
+
-+ skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
-+ if (ethertype == rx->sdata->control_port_protocol)
-+ return RX_CONTINUE;
++ if (end < len) {
++ offset = end;
++ continue;
+ }
+
-+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
-+ cfg80211_rx_spurious_frame(rx->sdata->dev,
-+ hdr->addr2,
-+ GFP_ATOMIC))
-+ return RX_DROP_UNUSABLE;
++ if (end > len &&
++ unlikely((err = pskb_trim(frag, len - offset))))
++ return err;
++
++ if (frag->next)
++ skb_drop_list(&frag->next);
++ break;
++ }
+
-+ return RX_DROP_MONITOR;
++done:
++ if (len > skb_headlen(skb)) {
++ skb->data_len -= skb->len - len;
++ skb->len = len;
++ } else {
++ skb->len = len;
++ skb->data_len = 0;
++ skb_set_tail_pointer(skb, len);
+ }
+
-+ return RX_CONTINUE;
++ return 0;
+}
++EXPORT_SYMBOL(___pskb_trim);
+
++/**
++ * __pskb_pull_tail - advance tail of skb header
++ * @skb: buffer to reallocate
++ * @delta: number of bytes to advance tail
++ *
++ * The function makes a sense only on a fragmented &sk_buff,
++ * it expands header moving its tail forward and copying necessary
++ * data from fragmented part.
++ *
++ * &sk_buff MUST have reference count of 1.
++ *
++ * Returns %NULL (and &sk_buff does not change) if pull failed
++ * or value of new tail of skb in the case of success.
++ *
++ * All the pointers pointing into skb header may change and must be
++ * reloaded after call to this function.
++ */
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx)
++/* Moves tail of skb head forward, copying data from fragmented part,
++ * when it is necessary.
++ * 1. It may fail due to malloc failure.
++ * 2. It may change skb pointers.
++ *
++ * It is pretty complicated. Luckily, it is called only in exceptional cases.
++ */
++unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta)
+{
-+ struct ieee80211_local *local;
-+ struct ieee80211_hdr *hdr;
-+ struct sk_buff *skb;
++ /* If skb has not enough free space at tail, get new one
++ * plus 128 bytes for future expansions. If we have enough
++ * room at tail, reallocate without expansion only if skb is cloned.
++ */
++ int i, k, eat = (skb->tail + delta) - skb->end;
+
-+ local = rx->local;
-+ skb = rx->skb;
-+ hdr = (struct ieee80211_hdr *) skb->data;
++ if (eat > 0 || skb_cloned(skb)) {
++ if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0,
++ GFP_ATOMIC))
++ return NULL;
++ }
+
-+ if (!local->pspolling)
-+ return RX_CONTINUE;
++ if (skb_copy_bits(skb, skb_headlen(skb), skb_tail_pointer(skb), delta))
++ BUG();
+
-+ if (!ieee80211_has_fromds(hdr->frame_control))
-+ /* this is not from AP */
-+ return RX_CONTINUE;
++ /* Optimization: no fragments, no reasons to preestimate
++ * size of pulled pages. Superb.
++ */
++ if (!skb_has_frag_list(skb))
++ goto pull_pages;
+
-+ if (!ieee80211_is_data(hdr->frame_control))
-+ return RX_CONTINUE;
++ /* Estimate size of pulled pages. */
++ eat = delta;
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
-+ if (!ieee80211_has_moredata(hdr->frame_control)) {
-+ /* AP has no more frames buffered for us */
-+ local->pspolling = false;
-+ return RX_CONTINUE;
++ if (size >= eat)
++ goto pull_pages;
++ eat -= size;
+ }
+
-+ /* more data bit is set, let's request a new frame from the AP */
-+ ieee80211_send_pspoll(local, rx->sdata);
-+
-+ return RX_CONTINUE;
-+}
++ /* If we need update frag list, we are in troubles.
++ * Certainly, it possible to add an offset to skb data,
++ * but taking into account that pulling is expected to
++ * be very rare operation, it is worth to fight against
++ * further bloating skb head and crucify ourselves here instead.
++ * Pure masohism, indeed. 8)8)
++ */
++ if (eat) {
++ struct sk_buff *list = skb_shinfo(skb)->frag_list;
++ struct sk_buff *clone = NULL;
++ struct sk_buff *insp = NULL;
+
-+static void sta_ps_start(struct sta_info *sta)
-+{
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+ struct ieee80211_local *local = sdata->local;
-+ struct ps_data *ps;
++ do {
++ BUG_ON(!list);
+
-+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
-+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+ ps = &sdata->bss->ps;
-+ else
-+ return;
++ if (list->len <= eat) {
++ /* Eaten as whole. */
++ eat -= list->len;
++ list = list->next;
++ insp = list;
++ } else {
++ /* Eaten partially. */
++
++ if (skb_shared(list)) {
++ /* Sucks! We need to fork list. :-( */
++ clone = skb_clone(list, GFP_ATOMIC);
++ if (!clone)
++ return NULL;
++ insp = list->next;
++ list = clone;
++ } else {
++ /* This may be pulled without
++ * problems. */
++ insp = list;
++ }
++ if (!pskb_pull(list, eat)) {
++ kfree_skb(clone);
++ return NULL;
++ }
++ break;
++ }
++ } while (eat);
+
-+ atomic_inc(&ps->num_sta_ps);
-+ set_sta_flag(sta, WLAN_STA_PS_STA);
-+ if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
-+ drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
-+ ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
-+ sta->sta.addr, sta->sta.aid);
-+}
++ /* Free pulled out fragments. */
++ while ((list = skb_shinfo(skb)->frag_list) != insp) {
++ skb_shinfo(skb)->frag_list = list->next;
++ kfree_skb(list);
++ }
++ /* And insert new clone at head. */
++ if (clone) {
++ clone->next = list;
++ skb_shinfo(skb)->frag_list = clone;
++ }
++ }
++ /* Success! Now we may commit changes to skb data. */
+
-+static void sta_ps_end(struct sta_info *sta)
-+{
-+ ps_dbg(sta->sdata, "STA %pM aid %d exits power save mode\n",
-+ sta->sta.addr, sta->sta.aid);
++pull_pages:
++ eat = delta;
++ k = 0;
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
-+ if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-+ /*
-+ * Clear the flag only if the other one is still set
-+ * so that the TX path won't start TX'ing new frames
-+ * directly ... In the case that the driver flag isn't
-+ * set ieee80211_sta_ps_deliver_wakeup() will clear it.
-+ */
-+ clear_sta_flag(sta, WLAN_STA_PS_STA);
-+ ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
-+ sta->sta.addr, sta->sta.aid);
-+ return;
++ if (size <= eat) {
++ skb_frag_unref(skb, i);
++ eat -= size;
++ } else {
++ skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
++ if (eat) {
++ skb_shinfo(skb)->frags[k].page_offset += eat;
++ skb_frag_size_sub(&skb_shinfo(skb)->frags[k], eat);
++ eat = 0;
++ }
++ k++;
++ }
+ }
++ skb_shinfo(skb)->nr_frags = k;
++
++ skb->tail += delta;
++ skb->data_len -= delta;
+
-+ set_sta_flag(sta, WLAN_STA_PS_DELIVER);
-+ clear_sta_flag(sta, WLAN_STA_PS_STA);
-+ ieee80211_sta_ps_deliver_wakeup(sta);
++ return skb_tail_pointer(skb);
+}
++EXPORT_SYMBOL(__pskb_pull_tail);
+
-+int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
++/**
++ * skb_copy_bits - copy bits from skb to kernel buffer
++ * @skb: source skb
++ * @offset: offset in source
++ * @to: destination buffer
++ * @len: number of bytes to copy
++ *
++ * Copy the specified number of bytes from the source skb to the
++ * destination buffer.
++ *
++ * CAUTION ! :
++ * If its prototype is ever changed,
++ * check arch/{*}/net/{*}.S files,
++ * since it is called from BPF assembly code.
++ */
++int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
+{
-+ struct sta_info *sta_inf = container_of(sta, struct sta_info, sta);
-+ bool in_ps;
++ int start = skb_headlen(skb);
++ struct sk_buff *frag_iter;
++ int i, copy;
+
-+ WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
++ if (offset > (int)skb->len - len)
++ goto fault;
+
-+ /* Don't let the same PS state be set twice */
-+ in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA);
-+ if ((start && in_ps) || (!start && !in_ps))
-+ return -EINVAL;
++ /* Copy header. */
++ if ((copy = start - offset) > 0) {
++ if (copy > len)
++ copy = len;
++ skb_copy_from_linear_data_offset(skb, offset, to, copy);
++ if ((len -= copy) == 0)
++ return 0;
++ offset += copy;
++ to += copy;
++ }
+
-+ if (start)
-+ sta_ps_start(sta_inf);
-+ else
-+ sta_ps_end(sta_inf);
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ int end;
++ skb_frag_t *f = &skb_shinfo(skb)->frags[i];
+
-+ return 0;
-+}
-+EXPORT_SYMBOL(ieee80211_sta_ps_transition);
++ WARN_ON(start > offset + len);
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
-+{
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_hdr *hdr = (void *)rx->skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-+ int tid, ac;
++ end = start + skb_frag_size(f);
++ if ((copy = end - offset) > 0) {
++ u8 *vaddr;
+
-+ if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ return RX_CONTINUE;
++ if (copy > len)
++ copy = len;
+
-+ if (sdata->vif.type != NL80211_IFTYPE_AP &&
-+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
-+ return RX_CONTINUE;
++ vaddr = kmap_atomic(skb_frag_page(f));
++ memcpy(to,
++ vaddr + f->page_offset + offset - start,
++ copy);
++ kunmap_atomic(vaddr);
+
-+ /*
-+ * The device handles station powersave, so don't do anything about
-+ * uAPSD and PS-Poll frames (the latter shouldn't even come up from
-+ * it to mac80211 since they're handled.)
-+ */
-+ if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS)
-+ return RX_CONTINUE;
++ if ((len -= copy) == 0)
++ return 0;
++ offset += copy;
++ to += copy;
++ }
++ start = end;
++ }
+
-+ /*
-+ * Don't do anything if the station isn't already asleep. In
-+ * the uAPSD case, the station will probably be marked asleep,
-+ * in the PS-Poll case the station must be confused ...
-+ */
-+ if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA))
-+ return RX_CONTINUE;
++ skb_walk_frags(skb, frag_iter) {
++ int end;
+
-+ if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
-+ if (!test_sta_flag(rx->sta, WLAN_STA_SP)) {
-+ if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
-+ ieee80211_sta_ps_deliver_poll_response(rx->sta);
-+ else
-+ set_sta_flag(rx->sta, WLAN_STA_PSPOLL);
++ WARN_ON(start > offset + len);
++
++ end = start + frag_iter->len;
++ if ((copy = end - offset) > 0) {
++ if (copy > len)
++ copy = len;
++ if (skb_copy_bits(frag_iter, offset - start, to, copy))
++ goto fault;
++ if ((len -= copy) == 0)
++ return 0;
++ offset += copy;
++ to += copy;
+ }
++ start = end;
++ }
+
-+ /* Free PS Poll skb here instead of returning RX_DROP that would
-+ * count as an dropped frame. */
-+ dev_kfree_skb(rx->skb);
++ if (!len)
++ return 0;
+
-+ return RX_QUEUED;
-+ } else if (!ieee80211_has_morefrags(hdr->frame_control) &&
-+ !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
-+ ieee80211_has_pm(hdr->frame_control) &&
-+ (ieee80211_is_data_qos(hdr->frame_control) ||
-+ ieee80211_is_qos_nullfunc(hdr->frame_control))) {
-+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
-+ ac = ieee802_1d_to_ac[tid & 7];
++fault:
++ return -EFAULT;
++}
++EXPORT_SYMBOL(skb_copy_bits);
+
-+ /*
-+ * If this AC is not trigger-enabled do nothing.
-+ *
-+ * NB: This could/should check a separate bitmap of trigger-
-+ * enabled queues, but for now we only implement uAPSD w/o
-+ * TSPEC changes to the ACs, so they're always the same.
-+ */
-+ if (!(rx->sta->sta.uapsd_queues & BIT(ac)))
-+ return RX_CONTINUE;
++/*
++ * Callback from splice_to_pipe(), if we need to release some pages
++ * at the end of the spd in case we error'ed out in filling the pipe.
++ */
++static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
++{
++ put_page(spd->pages[i]);
++}
++
++static struct page *linear_to_page(struct page *page, unsigned int *len,
++ unsigned int *offset,
++ struct sock *sk)
++{
++ struct page_frag *pfrag = sk_page_frag(sk);
+
-+ /* if we are in a service period, do nothing */
-+ if (test_sta_flag(rx->sta, WLAN_STA_SP))
-+ return RX_CONTINUE;
++ if (!sk_page_frag_refill(sk, pfrag))
++ return NULL;
+
-+ if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
-+ ieee80211_sta_ps_deliver_uapsd(rx->sta);
-+ else
-+ set_sta_flag(rx->sta, WLAN_STA_UAPSD);
-+ }
++ *len = min_t(unsigned int, *len, pfrag->size - pfrag->offset);
+
-+ return RX_CONTINUE;
++ memcpy(page_address(pfrag->page) + pfrag->offset,
++ page_address(page) + *offset, *len);
++ *offset = pfrag->offset;
++ pfrag->offset += *len;
++
++ return pfrag->page;
+}
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
++static bool spd_can_coalesce(const struct splice_pipe_desc *spd,
++ struct page *page,
++ unsigned int offset)
+{
-+ struct sta_info *sta = rx->sta;
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ int i;
++ return spd->nr_pages &&
++ spd->pages[spd->nr_pages - 1] == page &&
++ (spd->partial[spd->nr_pages - 1].offset +
++ spd->partial[spd->nr_pages - 1].len == offset);
++}
+
-+ if (!sta)
-+ return RX_CONTINUE;
++/*
++ * Fill page/offset/length into spd, if it can hold more pages.
++ */
++static bool spd_fill_page(struct splice_pipe_desc *spd,
++ struct pipe_inode_info *pipe, struct page *page,
++ unsigned int *len, unsigned int offset,
++ bool linear,
++ struct sock *sk)
++{
++ if (unlikely(spd->nr_pages == MAX_SKB_FRAGS))
++ return true;
+
-+ /*
-+ * Update last_rx only for IBSS packets which are for the current
-+ * BSSID and for station already AUTHORIZED to avoid keeping the
-+ * current IBSS network alive in cases where other STAs start
-+ * using different BSSID. This will also give the station another
-+ * chance to restart the authentication/authorization in case
-+ * something went wrong the first time.
-+ */
-+ if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
-+ u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
-+ NL80211_IFTYPE_ADHOC);
-+ if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
-+ test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
-+ sta->last_rx = jiffies;
-+ if (ieee80211_is_data(hdr->frame_control) &&
-+ !is_multicast_ether_addr(hdr->addr1)) {
-+ sta->last_rx_rate_idx = status->rate_idx;
-+ sta->last_rx_rate_flag = status->flag;
-+ sta->last_rx_rate_vht_flag = status->vht_flag;
-+ sta->last_rx_rate_vht_nss = status->vht_nss;
-+ }
-+ }
-+ } else if (!is_multicast_ether_addr(hdr->addr1)) {
-+ /*
-+ * Mesh beacons will update last_rx when if they are found to
-+ * match the current local configuration when processed.
-+ */
-+ sta->last_rx = jiffies;
-+ if (ieee80211_is_data(hdr->frame_control)) {
-+ sta->last_rx_rate_idx = status->rate_idx;
-+ sta->last_rx_rate_flag = status->flag;
-+ sta->last_rx_rate_vht_flag = status->vht_flag;
-+ sta->last_rx_rate_vht_nss = status->vht_nss;
-+ }
++ if (linear) {
++ page = linear_to_page(page, len, &offset, sk);
++ if (!page)
++ return true;
++ }
++ if (spd_can_coalesce(spd, page, offset)) {
++ spd->partial[spd->nr_pages - 1].len += *len;
++ return false;
+ }
++ get_page(page);
++ spd->pages[spd->nr_pages] = page;
++ spd->partial[spd->nr_pages].len = *len;
++ spd->partial[spd->nr_pages].offset = offset;
++ spd->nr_pages++;
+
-+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ return RX_CONTINUE;
++ return false;
++}
+
-+ if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
-+ ieee80211_sta_rx_notify(rx->sdata, hdr);
++static bool __splice_segment(struct page *page, unsigned int poff,
++ unsigned int plen, unsigned int *off,
++ unsigned int *len,
++ struct splice_pipe_desc *spd, bool linear,
++ struct sock *sk,
++ struct pipe_inode_info *pipe)
++{
++ if (!*len)
++ return true;
+
-+ sta->rx_fragments++;
-+ sta->rx_bytes += rx->skb->len;
-+ if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
-+ sta->last_signal = status->signal;
-+ ewma_add(&sta->avg_signal, -status->signal);
++ /* skip this segment if already processed */
++ if (*off >= plen) {
++ *off -= plen;
++ return false;
+ }
+
-+ if (status->chains) {
-+ sta->chains = status->chains;
-+ for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
-+ int signal = status->chain_signal[i];
++ /* ignore any bits we already processed */
++ poff += *off;
++ plen -= *off;
++ *off = 0;
+
-+ if (!(status->chains & BIT(i)))
-+ continue;
++ do {
++ unsigned int flen = min(*len, plen);
+
-+ sta->chain_signal_last[i] = signal;
-+ ewma_add(&sta->chain_signal_avg[i], -signal);
-+ }
-+ }
++ if (spd_fill_page(spd, pipe, page, &flen, poff,
++ linear, sk))
++ return true;
++ poff += flen;
++ plen -= flen;
++ *len -= flen;
++ } while (*len && plen);
+
-+ /*
-+ * Change STA power saving mode only at the end of a frame
-+ * exchange sequence.
-+ */
-+ if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) &&
-+ !ieee80211_has_morefrags(hdr->frame_control) &&
-+ !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
-+ (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
-+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-+ /* PM bit is only checked in frames where it isn't reserved,
-+ * in AP mode it's reserved in non-bufferable management frames
-+ * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
-+ */
-+ (!ieee80211_is_mgmt(hdr->frame_control) ||
-+ ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
-+ if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
-+ if (!ieee80211_has_pm(hdr->frame_control))
-+ sta_ps_end(sta);
-+ } else {
-+ if (ieee80211_has_pm(hdr->frame_control))
-+ sta_ps_start(sta);
-+ }
-+ }
++ return false;
++}
++
++/*
++ * Map linear and fragment data from the skb to spd. It reports true if the
++ * pipe is full or if we already spliced the requested length.
++ */
++static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
++ unsigned int *offset, unsigned int *len,
++ struct splice_pipe_desc *spd, struct sock *sk)
++{
++ int seg;
+
-+ /* mesh power save support */
-+ if (ieee80211_vif_is_mesh(&rx->sdata->vif))
-+ ieee80211_mps_rx_h_sta_process(sta, hdr);
++ /* map the linear part :
++ * If skb->head_frag is set, this 'linear' part is backed by a
++ * fragment, and if the head is not shared with any clones then
++ * we can avoid a copy since we own the head portion of this page.
++ */
++ if (__splice_segment(virt_to_page(skb->data),
++ (unsigned long) skb->data & (PAGE_SIZE - 1),
++ skb_headlen(skb),
++ offset, len, spd,
++ skb_head_is_locked(skb),
++ sk, pipe))
++ return true;
+
+ /*
-+ * Drop (qos-)data::nullfunc frames silently, since they
-+ * are used only to control station power saving mode.
++ * then map the fragments
+ */
-+ if (ieee80211_is_nullfunc(hdr->frame_control) ||
-+ ieee80211_is_qos_nullfunc(hdr->frame_control)) {
-+ I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
++ for (seg = 0; seg < skb_shinfo(skb)->nr_frags; seg++) {
++ const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
+
-+ /*
-+ * If we receive a 4-addr nullfunc frame from a STA
-+ * that was not moved to a 4-addr STA vlan yet send
-+ * the event to userspace and for older hostapd drop
-+ * the frame to the monitor interface.
-+ */
-+ if (ieee80211_has_a4(hdr->frame_control) &&
-+ (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
-+ (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-+ !rx->sdata->u.vlan.sta))) {
-+ if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT))
-+ cfg80211_rx_unexpected_4addr_frame(
-+ rx->sdata->dev, sta->sta.addr,
-+ GFP_ATOMIC);
-+ return RX_DROP_MONITOR;
-+ }
-+ /*
-+ * Update counter and free packet here to avoid
-+ * counting this as a dropped packed.
-+ */
-+ sta->rx_packets++;
-+ dev_kfree_skb(rx->skb);
-+ return RX_QUEUED;
++ if (__splice_segment(skb_frag_page(f),
++ f->page_offset, skb_frag_size(f),
++ offset, len, spd, false, sk, pipe))
++ return true;
+ }
+
-+ return RX_CONTINUE;
-+} /* ieee80211_rx_h_sta_process */
++ return false;
++}
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
-+{
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ int keyidx;
-+ int hdrlen;
-+ ieee80211_rx_result result = RX_DROP_UNUSABLE;
-+ struct ieee80211_key *sta_ptk = NULL;
-+ int mmie_keyidx = -1;
-+ __le16 fc;
-+ const struct ieee80211_cipher_scheme *cs = NULL;
++/*
++ * Map data from the skb to a pipe. Should handle both the linear part,
++ * the fragments, and the frag list. It does NOT handle frag lists within
++ * the frag list, if such a thing exists. We'd probably need to recurse to
++ * handle that cleanly.
++ */
++int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
++ struct pipe_inode_info *pipe, unsigned int tlen,
++ unsigned int flags)
++{
++ struct partial_page partial[MAX_SKB_FRAGS];
++ struct page *pages[MAX_SKB_FRAGS];
++ struct splice_pipe_desc spd = {
++ .pages = pages,
++ .partial = partial,
++ .nr_pages_max = MAX_SKB_FRAGS,
++ .flags = flags,
++ .ops = &nosteal_pipe_buf_ops,
++ .spd_release = sock_spd_release,
++ };
++ struct sk_buff *frag_iter;
++ struct sock *sk = skb->sk;
++ int ret = 0;
+
+ /*
-+ * Key selection 101
-+ *
-+ * There are four types of keys:
-+ * - GTK (group keys)
-+ * - IGTK (group keys for management frames)
-+ * - PTK (pairwise keys)
-+ * - STK (station-to-station pairwise keys)
-+ *
-+ * When selecting a key, we have to distinguish between multicast
-+ * (including broadcast) and unicast frames, the latter can only
-+ * use PTKs and STKs while the former always use GTKs and IGTKs.
-+ * Unless, of course, actual WEP keys ("pre-RSNA") are used, then
-+ * unicast frames can also use key indices like GTKs. Hence, if we
-+ * don't have a PTK/STK we check the key index for a WEP key.
-+ *
-+ * Note that in a regular BSS, multicast frames are sent by the
-+ * AP only, associated stations unicast the frame to the AP first
-+ * which then multicasts it on their behalf.
-+ *
-+ * There is also a slight problem in IBSS mode: GTKs are negotiated
-+ * with each station, that is something we don't currently handle.
-+ * The spec seems to expect that one negotiates the same key with
-+ * every station but there's no such requirement; VLANs could be
-+ * possible.
++ * __skb_splice_bits() only fails if the output has no room left,
++ * so no point in going over the frag_list for the error case.
+ */
++ if (__skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk))
++ goto done;
++ else if (!tlen)
++ goto done;
+
+ /*
-+ * No point in finding a key and decrypting if the frame is neither
-+ * addressed to us nor a multicast frame.
++ * now see if we have a frag_list to map
+ */
-+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ return RX_CONTINUE;
-+
-+ /* start without a key */
-+ rx->key = NULL;
-+ fc = hdr->frame_control;
-+
-+ if (rx->sta) {
-+ int keyid = rx->sta->ptk_idx;
++ skb_walk_frags(skb, frag_iter) {
++ if (!tlen)
++ break;
++ if (__skb_splice_bits(frag_iter, pipe, &offset, &tlen, &spd, sk))
++ break;
++ }
+
-+ if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
-+ cs = rx->sta->cipher_scheme;
-+ keyid = iwl80211_get_cs_keyid(cs, rx->skb);
-+ if (unlikely(keyid < 0))
-+ return RX_DROP_UNUSABLE;
-+ }
-+ sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
-+ }
-+
-+ if (!ieee80211_has_protected(fc))
-+ mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
-+
-+ if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
-+ rx->key = sta_ptk;
-+ if ((status->flag & RX_FLAG_DECRYPTED) &&
-+ (status->flag & RX_FLAG_IV_STRIPPED))
-+ return RX_CONTINUE;
-+ /* Skip decryption if the frame is not protected. */
-+ if (!ieee80211_has_protected(fc))
-+ return RX_CONTINUE;
-+ } else if (mmie_keyidx >= 0) {
-+ /* Broadcast/multicast robust management frame / BIP */
-+ if ((status->flag & RX_FLAG_DECRYPTED) &&
-+ (status->flag & RX_FLAG_IV_STRIPPED))
-+ return RX_CONTINUE;
-+
-+ if (mmie_keyidx < NUM_DEFAULT_KEYS ||
-+ mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
-+ return RX_DROP_MONITOR; /* unexpected BIP keyidx */
-+ if (rx->sta)
-+ rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
-+ if (!rx->key)
-+ rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
-+ } else if (!ieee80211_has_protected(fc)) {
++done:
++ if (spd.nr_pages) {
+ /*
-+ * The frame was not protected, so skip decryption. However, we
-+ * need to set rx->key if there is a key that could have been
-+ * used so that the frame may be dropped if encryption would
-+ * have been expected.
++ * Drop the socket lock, otherwise we have reverse
++ * locking dependencies between sk_lock and i_mutex
++ * here as compared to sendfile(). We enter here
++ * with the socket lock held, and splice_to_pipe() will
++ * grab the pipe inode lock. For sendfile() emulation,
++ * we call into ->sendpage() with the i_mutex lock held
++ * and networking will grab the socket lock.
+ */
-+ struct ieee80211_key *key = NULL;
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ int i;
++ release_sock(sk);
++ ret = splice_to_pipe(pipe, &spd);
++ lock_sock(sk);
++ }
+
-+ if (ieee80211_is_mgmt(fc) &&
-+ is_multicast_ether_addr(hdr->addr1) &&
-+ (key = rcu_dereference(rx->sdata->default_mgmt_key)))
-+ rx->key = key;
-+ else {
-+ if (rx->sta) {
-+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-+ key = rcu_dereference(rx->sta->gtk[i]);
-+ if (key)
-+ break;
-+ }
-+ }
-+ if (!key) {
-+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-+ key = rcu_dereference(sdata->keys[i]);
-+ if (key)
-+ break;
-+ }
-+ }
-+ if (key)
-+ rx->key = key;
-+ }
-+ return RX_CONTINUE;
-+ } else {
-+ u8 keyid;
++ return ret;
++}
+
-+ /*
-+ * The device doesn't give us the IV so we won't be
-+ * able to look up the key. That's ok though, we
-+ * don't need to decrypt the frame, we just won't
-+ * be able to keep statistics accurate.
-+ * Except for key threshold notifications, should
-+ * we somehow allow the driver to tell us which key
-+ * the hardware used if this flag is set?
-+ */
-+ if ((status->flag & RX_FLAG_DECRYPTED) &&
-+ (status->flag & RX_FLAG_IV_STRIPPED))
-+ return RX_CONTINUE;
++/**
++ * skb_store_bits - store bits from kernel buffer to skb
++ * @skb: destination buffer
++ * @offset: offset in destination
++ * @from: source buffer
++ * @len: number of bytes to copy
++ *
++ * Copy the specified number of bytes from the source buffer to the
++ * destination skb. This function handles all the messy bits of
++ * traversing fragment lists and such.
++ */
+
-+ hdrlen = ieee80211_hdrlen(fc);
++int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
++{
++ int start = skb_headlen(skb);
++ struct sk_buff *frag_iter;
++ int i, copy;
+
-+ if (cs) {
-+ keyidx = iwl80211_get_cs_keyid(cs, rx->skb);
++ if (offset > (int)skb->len - len)
++ goto fault;
+
-+ if (unlikely(keyidx < 0))
-+ return RX_DROP_UNUSABLE;
-+ } else {
-+ if (rx->skb->len < 8 + hdrlen)
-+ return RX_DROP_UNUSABLE; /* TODO: count this? */
-+ /*
-+ * no need to call ieee80211_wep_get_keyidx,
-+ * it verifies a bunch of things we've done already
-+ */
-+ skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
-+ keyidx = keyid >> 6;
-+ }
++ if ((copy = start - offset) > 0) {
++ if (copy > len)
++ copy = len;
++ skb_copy_to_linear_data_offset(skb, offset, from, copy);
++ if ((len -= copy) == 0)
++ return 0;
++ offset += copy;
++ from += copy;
++ }
+
-+ /* check per-station GTK first, if multicast packet */
-+ if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
-+ rx->key = rcu_dereference(rx->sta->gtk[keyidx]);
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++ int end;
+
-+ /* if not found, try default key */
-+ if (!rx->key) {
-+ rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
++ WARN_ON(start > offset + len);
+
-+ /*
-+ * RSNA-protected unicast frames should always be
-+ * sent with pairwise or station-to-station keys,
-+ * but for WEP we allow using a key index as well.
-+ */
-+ if (rx->key &&
-+ rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 &&
-+ rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 &&
-+ !is_multicast_ether_addr(hdr->addr1))
-+ rx->key = NULL;
++ end = start + skb_frag_size(frag);
++ if ((copy = end - offset) > 0) {
++ u8 *vaddr;
++
++ if (copy > len)
++ copy = len;
++
++ vaddr = kmap_atomic(skb_frag_page(frag));
++ memcpy(vaddr + frag->page_offset + offset - start,
++ from, copy);
++ kunmap_atomic(vaddr);
++
++ if ((len -= copy) == 0)
++ return 0;
++ offset += copy;
++ from += copy;
+ }
++ start = end;
+ }
+
-+ if (rx->key) {
-+ if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
-+ return RX_DROP_MONITOR;
++ skb_walk_frags(skb, frag_iter) {
++ int end;
+
-+ rx->key->tx_rx_count++;
-+ /* TODO: add threshold stuff again */
-+ } else {
-+ return RX_DROP_MONITOR;
++ WARN_ON(start > offset + len);
++
++ end = start + frag_iter->len;
++ if ((copy = end - offset) > 0) {
++ if (copy > len)
++ copy = len;
++ if (skb_store_bits(frag_iter, offset - start,
++ from, copy))
++ goto fault;
++ if ((len -= copy) == 0)
++ return 0;
++ offset += copy;
++ from += copy;
++ }
++ start = end;
+ }
++ if (!len)
++ return 0;
+
-+ switch (rx->key->conf.cipher) {
-+ case WLAN_CIPHER_SUITE_WEP40:
-+ case WLAN_CIPHER_SUITE_WEP104:
-+ result = ieee80211_crypto_wep_decrypt(rx);
-+ break;
-+ case WLAN_CIPHER_SUITE_TKIP:
-+ result = ieee80211_crypto_tkip_decrypt(rx);
-+ break;
-+ case WLAN_CIPHER_SUITE_CCMP:
-+ result = ieee80211_crypto_ccmp_decrypt(rx);
-+ break;
-+ case WLAN_CIPHER_SUITE_AES_CMAC:
-+ result = ieee80211_crypto_aes_cmac_decrypt(rx);
-+ break;
-+ default:
-+ result = ieee80211_crypto_hw_decrypt(rx);
++fault:
++ return -EFAULT;
++}
++EXPORT_SYMBOL(skb_store_bits);
++
++/* Checksum skb data. */
++__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
++ __wsum csum, const struct skb_checksum_ops *ops)
++{
++ int start = skb_headlen(skb);
++ int i, copy = start - offset;
++ struct sk_buff *frag_iter;
++ int pos = 0;
++
++ /* Checksum header. */
++ if (copy > 0) {
++ if (copy > len)
++ copy = len;
++ csum = ops->update(skb->data + offset, copy, csum);
++ if ((len -= copy) == 0)
++ return csum;
++ offset += copy;
++ pos = copy;
++ }
++
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ int end;
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++
++ WARN_ON(start > offset + len);
++
++ end = start + skb_frag_size(frag);
++ if ((copy = end - offset) > 0) {
++ __wsum csum2;
++ u8 *vaddr;
++
++ if (copy > len)
++ copy = len;
++ vaddr = kmap_atomic(skb_frag_page(frag));
++ csum2 = ops->update(vaddr + frag->page_offset +
++ offset - start, copy, 0);
++ kunmap_atomic(vaddr);
++ csum = ops->combine(csum, csum2, pos, copy);
++ if (!(len -= copy))
++ return csum;
++ offset += copy;
++ pos += copy;
++ }
++ start = end;
++ }
++
++ skb_walk_frags(skb, frag_iter) {
++ int end;
++
++ WARN_ON(start > offset + len);
++
++ end = start + frag_iter->len;
++ if ((copy = end - offset) > 0) {
++ __wsum csum2;
++ if (copy > len)
++ copy = len;
++ csum2 = __skb_checksum(frag_iter, offset - start,
++ copy, 0, ops);
++ csum = ops->combine(csum, csum2, pos, copy);
++ if ((len -= copy) == 0)
++ return csum;
++ offset += copy;
++ pos += copy;
++ }
++ start = end;
+ }
++ BUG_ON(len);
+
-+ /* the hdr variable is invalid after the decrypt handlers */
++ return csum;
++}
++EXPORT_SYMBOL(__skb_checksum);
+
-+ /* either the frame has been decrypted or will be dropped */
-+ status->flag |= RX_FLAG_DECRYPTED;
++__wsum skb_checksum(const struct sk_buff *skb, int offset,
++ int len, __wsum csum)
++{
++ const struct skb_checksum_ops ops = {
++ .update = csum_partial_ext,
++ .combine = csum_block_add_ext,
++ };
+
-+ return result;
++ return __skb_checksum(skb, offset, len, csum, &ops);
++}
++EXPORT_SYMBOL(skb_checksum);
++
++/* Both of above in one bottle. */
++
++__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
++ u8 *to, int len, __wsum csum)
++{
++ int start = skb_headlen(skb);
++ int i, copy = start - offset;
++ struct sk_buff *frag_iter;
++ int pos = 0;
++
++ /* Copy header. */
++ if (copy > 0) {
++ if (copy > len)
++ copy = len;
++ csum = csum_partial_copy_nocheck(skb->data + offset, to,
++ copy, csum);
++ if ((len -= copy) == 0)
++ return csum;
++ offset += copy;
++ to += copy;
++ pos = copy;
++ }
++
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ int end;
++
++ WARN_ON(start > offset + len);
++
++ end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]);
++ if ((copy = end - offset) > 0) {
++ __wsum csum2;
++ u8 *vaddr;
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++
++ if (copy > len)
++ copy = len;
++ vaddr = kmap_atomic(skb_frag_page(frag));
++ csum2 = csum_partial_copy_nocheck(vaddr +
++ frag->page_offset +
++ offset - start, to,
++ copy, 0);
++ kunmap_atomic(vaddr);
++ csum = csum_block_add(csum, csum2, pos);
++ if (!(len -= copy))
++ return csum;
++ offset += copy;
++ to += copy;
++ pos += copy;
++ }
++ start = end;
++ }
++
++ skb_walk_frags(skb, frag_iter) {
++ __wsum csum2;
++ int end;
++
++ WARN_ON(start > offset + len);
++
++ end = start + frag_iter->len;
++ if ((copy = end - offset) > 0) {
++ if (copy > len)
++ copy = len;
++ csum2 = skb_copy_and_csum_bits(frag_iter,
++ offset - start,
++ to, copy, 0);
++ csum = csum_block_add(csum, csum2, pos);
++ if ((len -= copy) == 0)
++ return csum;
++ offset += copy;
++ to += copy;
++ pos += copy;
++ }
++ start = end;
++ }
++ BUG_ON(len);
++ return csum;
+}
++EXPORT_SYMBOL(skb_copy_and_csum_bits);
+
-+static inline struct ieee80211_fragment_entry *
-+ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
-+ unsigned int frag, unsigned int seq, int rx_queue,
-+ struct sk_buff **skb)
++ /**
++ * skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy()
++ * @from: source buffer
++ *
++ * Calculates the amount of linear headroom needed in the 'to' skb passed
++ * into skb_zerocopy().
++ */
++unsigned int
++skb_zerocopy_headlen(const struct sk_buff *from)
+{
-+ struct ieee80211_fragment_entry *entry;
++ unsigned int hlen = 0;
+
-+ entry = &sdata->fragments[sdata->fragment_next++];
-+ if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
-+ sdata->fragment_next = 0;
++ if (!from->head_frag ||
++ skb_headlen(from) < L1_CACHE_BYTES ||
++ skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
++ hlen = skb_headlen(from);
+
-+ if (!skb_queue_empty(&entry->skb_list))
-+ __skb_queue_purge(&entry->skb_list);
++ if (skb_has_frag_list(from))
++ hlen = from->len;
+
-+ __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
-+ *skb = NULL;
-+ entry->first_frag_time = jiffies;
-+ entry->seq = seq;
-+ entry->rx_queue = rx_queue;
-+ entry->last_frag = frag;
-+ entry->ccmp = 0;
-+ entry->extra_len = 0;
-+
-+ return entry;
++ return hlen;
+}
++EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
+
-+static inline struct ieee80211_fragment_entry *
-+ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
-+ unsigned int frag, unsigned int seq,
-+ int rx_queue, struct ieee80211_hdr *hdr)
++/**
++ * skb_zerocopy - Zero copy skb to skb
++ * @to: destination buffer
++ * @from: source buffer
++ * @len: number of bytes to copy from source buffer
++ * @hlen: size of linear headroom in destination buffer
++ *
++ * Copies up to `len` bytes from `from` to `to` by creating references
++ * to the frags in the source buffer.
++ *
++ * The `hlen` as calculated by skb_zerocopy_headlen() specifies the
++ * headroom in the `to` buffer.
++ *
++ * Return value:
++ * 0: everything is OK
++ * -ENOMEM: couldn't orphan frags of @from due to lack of memory
++ * -EFAULT: skb_copy_bits() found some problem with skb geometry
++ */
++int
++skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
+{
-+ struct ieee80211_fragment_entry *entry;
-+ int i, idx;
++ int i, j = 0;
++ int plen = 0; /* length of skb->head fragment */
++ int ret;
++ struct page *page;
++ unsigned int offset;
+
-+ idx = sdata->fragment_next;
-+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
-+ struct ieee80211_hdr *f_hdr;
++ BUG_ON(!from->head_frag && !hlen);
+
-+ idx--;
-+ if (idx < 0)
-+ idx = IEEE80211_FRAGMENT_MAX - 1;
++ /* dont bother with small payloads */
++ if (len <= skb_tailroom(to))
++ return skb_copy_bits(from, 0, skb_put(to, len), len);
+
-+ entry = &sdata->fragments[idx];
-+ if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
-+ entry->rx_queue != rx_queue ||
-+ entry->last_frag + 1 != frag)
-+ continue;
++ if (hlen) {
++ ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
++ if (unlikely(ret))
++ return ret;
++ len -= hlen;
++ } else {
++ plen = min_t(int, skb_headlen(from), len);
++ if (plen) {
++ page = virt_to_head_page(from->head);
++ offset = from->data - (unsigned char *)page_address(page);
++ __skb_fill_page_desc(to, 0, page, offset, plen);
++ get_page(page);
++ j = 1;
++ len -= plen;
++ }
++ }
+
-+ f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data;
++ to->truesize += len + plen;
++ to->len += len + plen;
++ to->data_len += len + plen;
+
-+ /*
-+ * Check ftype and addresses are equal, else check next fragment
-+ */
-+ if (((hdr->frame_control ^ f_hdr->frame_control) &
-+ cpu_to_le16(IEEE80211_FCTL_FTYPE)) ||
-+ !ether_addr_equal(hdr->addr1, f_hdr->addr1) ||
-+ !ether_addr_equal(hdr->addr2, f_hdr->addr2))
-+ continue;
++ if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
++ skb_tx_error(from);
++ return -ENOMEM;
++ }
+
-+ if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
-+ __skb_queue_purge(&entry->skb_list);
-+ continue;
-+ }
-+ return entry;
++ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
++ if (!len)
++ break;
++ skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
++ skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len);
++ len -= skb_shinfo(to)->frags[j].size;
++ skb_frag_ref(to, j);
++ j++;
+ }
++ skb_shinfo(to)->nr_frags = j;
+
-+ return NULL;
++ return 0;
+}
++EXPORT_SYMBOL_GPL(skb_zerocopy);
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
++void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
+{
-+ struct ieee80211_hdr *hdr;
-+ u16 sc;
-+ __le16 fc;
-+ unsigned int frag, seq;
-+ struct ieee80211_fragment_entry *entry;
-+ struct sk_buff *skb;
-+ struct ieee80211_rx_status *status;
++ __wsum csum;
++ long csstart;
+
-+ hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ fc = hdr->frame_control;
-+
-+ if (ieee80211_is_ctl(fc))
-+ return RX_CONTINUE;
-+
-+ sc = le16_to_cpu(hdr->seq_ctrl);
-+ frag = sc & IEEE80211_SCTL_FRAG;
-+
-+ if (is_multicast_ether_addr(hdr->addr1)) {
-+ rx->local->dot11MulticastReceivedFrameCount++;
-+ goto out_no_led;
-+ }
++ if (skb->ip_summed == CHECKSUM_PARTIAL)
++ csstart = skb_checksum_start_offset(skb);
++ else
++ csstart = skb_headlen(skb);
+
-+ if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
-+ goto out;
++ BUG_ON(csstart > skb_headlen(skb));
+
-+ I802_DEBUG_INC(rx->local->rx_handlers_fragments);
++ skb_copy_from_linear_data(skb, to, csstart);
+
-+ if (skb_linearize(rx->skb))
-+ return RX_DROP_UNUSABLE;
++ csum = 0;
++ if (csstart != skb->len)
++ csum = skb_copy_and_csum_bits(skb, csstart, to + csstart,
++ skb->len - csstart, 0);
+
-+ /*
-+ * skb_linearize() might change the skb->data and
-+ * previously cached variables (in this case, hdr) need to
-+ * be refreshed with the new data.
-+ */
-+ hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-+
-+ if (frag == 0) {
-+ /* This is the first fragment of a new frame. */
-+ entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
-+ rx->seqno_idx, &(rx->skb));
-+ if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP &&
-+ ieee80211_has_protected(fc)) {
-+ int queue = rx->security_idx;
-+ /* Store CCMP PN so that we can verify that the next
-+ * fragment has a sequential PN value. */
-+ entry->ccmp = 1;
-+ memcpy(entry->last_pn,
-+ rx->key->u.ccmp.rx_pn[queue],
-+ IEEE80211_CCMP_PN_LEN);
-+ }
-+ return RX_QUEUED;
-+ }
++ if (skb->ip_summed == CHECKSUM_PARTIAL) {
++ long csstuff = csstart + skb->csum_offset;
+
-+ /* This is a fragment for a frame that should already be pending in
-+ * fragment cache. Add this fragment to the end of the pending entry.
-+ */
-+ entry = ieee80211_reassemble_find(rx->sdata, frag, seq,
-+ rx->seqno_idx, hdr);
-+ if (!entry) {
-+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
-+ return RX_DROP_MONITOR;
++ *((__sum16 *)(to + csstuff)) = csum_fold(csum);
+ }
++}
++EXPORT_SYMBOL(skb_copy_and_csum_dev);
+
-+ /* Verify that MPDUs within one MSDU have sequential PN values.
-+ * (IEEE 802.11i, 8.3.3.4.5) */
-+ if (entry->ccmp) {
-+ int i;
-+ u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
-+ int queue;
-+ if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
-+ return RX_DROP_UNUSABLE;
-+ memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
-+ for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
-+ pn[i]++;
-+ if (pn[i])
-+ break;
-+ }
-+ queue = rx->security_idx;
-+ rpn = rx->key->u.ccmp.rx_pn[queue];
-+ if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
-+ return RX_DROP_UNUSABLE;
-+ memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
-+ }
-+
-+ skb_pull(rx->skb, ieee80211_hdrlen(fc));
-+ __skb_queue_tail(&entry->skb_list, rx->skb);
-+ entry->last_frag = frag;
-+ entry->extra_len += rx->skb->len;
-+ if (ieee80211_has_morefrags(fc)) {
-+ rx->skb = NULL;
-+ return RX_QUEUED;
-+ }
-+
-+ rx->skb = __skb_dequeue(&entry->skb_list);
-+ if (skb_tailroom(rx->skb) < entry->extra_len) {
-+ I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
-+ if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
-+ GFP_ATOMIC))) {
-+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
-+ __skb_queue_purge(&entry->skb_list);
-+ return RX_DROP_UNUSABLE;
-+ }
-+ }
-+ while ((skb = __skb_dequeue(&entry->skb_list))) {
-+ memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
-+ dev_kfree_skb(skb);
-+ }
++/**
++ * skb_dequeue - remove from the head of the queue
++ * @list: list to dequeue from
++ *
++ * Remove the head of the list. The list lock is taken so the function
++ * may be used safely with other locking list functions. The head item is
++ * returned or %NULL if the list is empty.
++ */
+
-+ /* Complete frame has been reassembled - process it now */
-+ status = IEEE80211_SKB_RXCB(rx->skb);
-+ status->rx_flags |= IEEE80211_RX_FRAGMENTED;
++struct sk_buff *skb_dequeue(struct sk_buff_head *list)
++{
++ unsigned long flags;
++ struct sk_buff *result;
+
-+ out:
-+ ieee80211_led_rx(rx->local);
-+ out_no_led:
-+ if (rx->sta)
-+ rx->sta->rx_packets++;
-+ return RX_CONTINUE;
++ spin_lock_irqsave(&list->lock, flags);
++ result = __skb_dequeue(list);
++ spin_unlock_irqrestore(&list->lock, flags);
++ return result;
+}
++EXPORT_SYMBOL(skb_dequeue);
+
-+static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
++/**
++ * skb_dequeue_tail - remove from the tail of the queue
++ * @list: list to dequeue from
++ *
++ * Remove the tail of the list. The list lock is taken so the function
++ * may be used safely with other locking list functions. The tail item is
++ * returned or %NULL if the list is empty.
++ */
++struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
+{
-+ if (unlikely(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
-+ return -EACCES;
++ unsigned long flags;
++ struct sk_buff *result;
+
-+ return 0;
++ spin_lock_irqsave(&list->lock, flags);
++ result = __skb_dequeue_tail(list);
++ spin_unlock_irqrestore(&list->lock, flags);
++ return result;
+}
++EXPORT_SYMBOL(skb_dequeue_tail);
+
-+static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
++/**
++ * skb_queue_purge - empty a list
++ * @list: list to empty
++ *
++ * Delete all buffers on an &sk_buff list. Each buffer is removed from
++ * the list and one reference dropped. This function takes the list
++ * lock and is atomic with respect to other list locking functions.
++ */
++void skb_queue_purge(struct sk_buff_head *list)
+{
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
++ struct sk_buff *skb;
++ while ((skb = skb_dequeue(list)) != NULL)
++ kfree_skb(skb);
++}
++EXPORT_SYMBOL(skb_queue_purge);
+
-+ /*
-+ * Pass through unencrypted frames if the hardware has
-+ * decrypted them already.
-+ */
-+ if (status->flag & RX_FLAG_DECRYPTED)
-+ return 0;
++/**
++ * skb_queue_head - queue a buffer at the list head
++ * @list: list to use
++ * @newsk: buffer to queue
++ *
++ * Queue a buffer at the start of the list. This function takes the
++ * list lock and can be used safely with other locking &sk_buff functions
++ * safely.
++ *
++ * A buffer cannot be placed on two lists at the same time.
++ */
++void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
++{
++ unsigned long flags;
+
-+ /* Drop unencrypted frames if key is set. */
-+ if (unlikely(!ieee80211_has_protected(fc) &&
-+ !ieee80211_is_nullfunc(fc) &&
-+ ieee80211_is_data(fc) &&
-+ (rx->key || rx->sdata->drop_unencrypted)))
-+ return -EACCES;
++ spin_lock_irqsave(&list->lock, flags);
++ __skb_queue_head(list, newsk);
++ spin_unlock_irqrestore(&list->lock, flags);
++}
++EXPORT_SYMBOL(skb_queue_head);
+
-+ return 0;
++/**
++ * skb_queue_tail - queue a buffer at the list tail
++ * @list: list to use
++ * @newsk: buffer to queue
++ *
++ * Queue a buffer at the tail of the list. This function takes the
++ * list lock and can be used safely with other locking &sk_buff functions
++ * safely.
++ *
++ * A buffer cannot be placed on two lists at the same time.
++ */
++void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&list->lock, flags);
++ __skb_queue_tail(list, newsk);
++ spin_unlock_irqrestore(&list->lock, flags);
+}
++EXPORT_SYMBOL(skb_queue_tail);
+
-+static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
++/**
++ * skb_unlink - remove a buffer from a list
++ * @skb: buffer to remove
++ * @list: list to use
++ *
++ * Remove a packet from a list. The list locks are taken and this
++ * function is atomic with respect to other list locked calls
++ *
++ * You must know what list the SKB is on.
++ */
++void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+{
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-+ __le16 fc = hdr->frame_control;
++ unsigned long flags;
+
-+ /*
-+ * Pass through unencrypted frames if the hardware has
-+ * decrypted them already.
-+ */
-+ if (status->flag & RX_FLAG_DECRYPTED)
-+ return 0;
++ spin_lock_irqsave(&list->lock, flags);
++ __skb_unlink(skb, list);
++ spin_unlock_irqrestore(&list->lock, flags);
++}
++EXPORT_SYMBOL(skb_unlink);
+
-+ if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) {
-+ if (unlikely(!ieee80211_has_protected(fc) &&
-+ ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
-+ rx->key)) {
-+ if (ieee80211_is_deauth(fc) ||
-+ ieee80211_is_disassoc(fc))
-+ cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
-+ rx->skb->data,
-+ rx->skb->len);
-+ return -EACCES;
-+ }
-+ /* BIP does not use Protected field, so need to check MMIE */
-+ if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
-+ ieee80211_get_mmie_keyidx(rx->skb) < 0)) {
-+ if (ieee80211_is_deauth(fc) ||
-+ ieee80211_is_disassoc(fc))
-+ cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
-+ rx->skb->data,
-+ rx->skb->len);
-+ return -EACCES;
-+ }
-+ /*
-+ * When using MFP, Action frames are not allowed prior to
-+ * having configured keys.
-+ */
-+ if (unlikely(ieee80211_is_action(fc) && !rx->key &&
-+ ieee80211_is_robust_mgmt_frame(rx->skb)))
-+ return -EACCES;
-+ }
++/**
++ * skb_append - append a buffer
++ * @old: buffer to insert after
++ * @newsk: buffer to insert
++ * @list: list to use
++ *
++ * Place a packet after a given packet in a list. The list locks are taken
++ * and this function is atomic with respect to other list locked calls.
++ * A buffer cannot be placed on two lists at the same time.
++ */
++void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
++{
++ unsigned long flags;
+
-+ return 0;
++ spin_lock_irqsave(&list->lock, flags);
++ __skb_queue_after(list, old, newsk);
++ spin_unlock_irqrestore(&list->lock, flags);
+}
++EXPORT_SYMBOL(skb_append);
+
-+static int
-+__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
++/**
++ * skb_insert - insert a buffer
++ * @old: buffer to insert before
++ * @newsk: buffer to insert
++ * @list: list to use
++ *
++ * Place a packet before a given packet in a list. The list locks are
++ * taken and this function is atomic with respect to other list locked
++ * calls.
++ *
++ * A buffer cannot be placed on two lists at the same time.
++ */
++void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
+{
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ bool check_port_control = false;
-+ struct ethhdr *ehdr;
-+ int ret;
++ unsigned long flags;
+
-+ *port_control = false;
-+ if (ieee80211_has_a4(hdr->frame_control) &&
-+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
-+ return -1;
++ spin_lock_irqsave(&list->lock, flags);
++ __skb_insert(newsk, old->prev, old, list);
++ spin_unlock_irqrestore(&list->lock, flags);
++}
++EXPORT_SYMBOL(skb_insert);
+
-+ if (sdata->vif.type == NL80211_IFTYPE_STATION &&
-+ !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) {
++static inline void skb_split_inside_header(struct sk_buff *skb,
++ struct sk_buff* skb1,
++ const u32 len, const int pos)
++{
++ int i;
+
-+ if (!sdata->u.mgd.use_4addr)
-+ return -1;
-+ else
-+ check_port_control = true;
++ skb_copy_from_linear_data_offset(skb, len, skb_put(skb1, pos - len),
++ pos - len);
++ /* And move data appendix as is. */
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
++ skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
++
++ skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags;
++ skb_shinfo(skb)->nr_frags = 0;
++ skb1->data_len = skb->data_len;
++ skb1->len += skb1->data_len;
++ skb->data_len = 0;
++ skb->len = len;
++ skb_set_tail_pointer(skb, len);
++}
++
++static inline void skb_split_no_header(struct sk_buff *skb,
++ struct sk_buff* skb1,
++ const u32 len, int pos)
++{
++ int i, k = 0;
++ const int nfrags = skb_shinfo(skb)->nr_frags;
++
++ skb_shinfo(skb)->nr_frags = 0;
++ skb1->len = skb1->data_len = skb->len - len;
++ skb->len = len;
++ skb->data_len = len - pos;
++
++ for (i = 0; i < nfrags; i++) {
++ int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
++
++ if (pos + size > len) {
++ skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i];
++
++ if (pos < len) {
++ /* Split frag.
++ * We have two variants in this case:
++ * 1. Move all the frag to the second
++ * part, if it is possible. F.e.
++ * this approach is mandatory for TUX,
++ * where splitting is expensive.
++ * 2. Split is accurately. We make this.
++ */
++ skb_frag_ref(skb, i);
++ skb_shinfo(skb1)->frags[0].page_offset += len - pos;
++ skb_frag_size_sub(&skb_shinfo(skb1)->frags[0], len - pos);
++ skb_frag_size_set(&skb_shinfo(skb)->frags[i], len - pos);
++ skb_shinfo(skb)->nr_frags++;
++ }
++ k++;
++ } else
++ skb_shinfo(skb)->nr_frags++;
++ pos += size;
+ }
++ skb_shinfo(skb1)->nr_frags = k;
++}
+
-+ if (is_multicast_ether_addr(hdr->addr1) &&
-+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)
-+ return -1;
-+
-+ ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
-+ if (ret < 0)
-+ return ret;
++/**
++ * skb_split - Split fragmented skb to two parts at length len.
++ * @skb: the buffer to split
++ * @skb1: the buffer to receive the second part
++ * @len: new length for skb
++ */
++void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
++{
++ int pos = skb_headlen(skb);
+
-+ ehdr = (struct ethhdr *) rx->skb->data;
-+ if (ehdr->h_proto == rx->sdata->control_port_protocol)
-+ *port_control = true;
-+ else if (check_port_control)
-+ return -1;
++ skb_shinfo(skb1)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
++ if (len < pos) /* Split line is inside header. */
++ skb_split_inside_header(skb, skb1, len, pos);
++ else /* Second chunk has no header, nothing to copy. */
++ skb_split_no_header(skb, skb1, len, pos);
++}
++EXPORT_SYMBOL(skb_split);
+
-+ return 0;
++/* Shifting from/to a cloned skb is a no-go.
++ *
++ * Caller cannot keep skb_shinfo related pointers past calling here!
++ */
++static int skb_prepare_for_shift(struct sk_buff *skb)
++{
++ return skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+}
+
-+/*
-+ * requires that rx->skb is a frame with ethernet header
++/**
++ * skb_shift - Shifts paged data partially from skb to another
++ * @tgt: buffer into which tail data gets added
++ * @skb: buffer from which the paged data comes from
++ * @shiftlen: shift up to this many bytes
++ *
++ * Attempts to shift up to shiftlen worth of bytes, which may be less than
++ * the length of the skb, from skb to tgt. Returns number bytes shifted.
++ * It's up to caller to free skb if everything was shifted.
++ *
++ * If @tgt runs out of frags, the whole operation is aborted.
++ *
++ * Skb cannot include anything else but paged data while tgt is allowed
++ * to have non-paged data as well.
++ *
++ * TODO: full sized shift could be optimized but that would need
++ * specialized skb free'er to handle frags without up-to-date nr_frags.
+ */
-+static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
++int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
+{
-+ static const u8 pae_group_addr[ETH_ALEN] __aligned(2)
-+ = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
-+ struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
++ int from, to, merge, todo;
++ struct skb_frag_struct *fragfrom, *fragto;
+
-+ /*
-+ * Allow EAPOL frames to us/the PAE group address regardless
-+ * of whether the frame was encrypted or not.
-+ */
-+ if (ehdr->h_proto == rx->sdata->control_port_protocol &&
-+ (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
-+ ether_addr_equal(ehdr->h_dest, pae_group_addr)))
-+ return true;
++ BUG_ON(shiftlen > skb->len);
++ BUG_ON(skb_headlen(skb)); /* Would corrupt stream */
+
-+ if (ieee80211_802_1x_port_control(rx) ||
-+ ieee80211_drop_unencrypted(rx, fc))
-+ return false;
++ todo = shiftlen;
++ from = 0;
++ to = skb_shinfo(tgt)->nr_frags;
++ fragfrom = &skb_shinfo(skb)->frags[from];
+
-+ return true;
-+}
++ /* Actual merge is delayed until the point when we know we can
++ * commit all, so that we don't have to undo partial changes
++ */
++ if (!to ||
++ !skb_can_coalesce(tgt, to, skb_frag_page(fragfrom),
++ fragfrom->page_offset)) {
++ merge = -1;
++ } else {
++ merge = to - 1;
+
-+/*
-+ * requires that rx->skb is a frame with ethernet header
-+ */
-+static void
-+ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
-+{
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct net_device *dev = sdata->dev;
-+ struct sk_buff *skb, *xmit_skb;
-+ struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
-+ struct sta_info *dsta;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-+
-+ skb = rx->skb;
-+ xmit_skb = NULL;
-+
-+ if ((sdata->vif.type == NL80211_IFTYPE_AP ||
-+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-+ !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
-+ (status->rx_flags & IEEE80211_RX_RA_MATCH) &&
-+ (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
-+ if (is_multicast_ether_addr(ehdr->h_dest)) {
-+ /*
-+ * send multicast frames both to higher layers in
-+ * local net stack and back to the wireless medium
-+ */
-+ xmit_skb = skb_copy(skb, GFP_ATOMIC);
-+ if (!xmit_skb)
-+ net_info_ratelimited("%s: failed to clone multicast frame\n",
-+ dev->name);
-+ } else {
-+ dsta = sta_info_get(sdata, skb->data);
-+ if (dsta) {
-+ /*
-+ * The destination station is associated to
-+ * this AP (in this VLAN), so send the frame
-+ * directly to it and do not pass it to local
-+ * net stack.
-+ */
-+ xmit_skb = skb;
-+ skb = NULL;
-+ }
-+ }
-+ }
++ todo -= skb_frag_size(fragfrom);
++ if (todo < 0) {
++ if (skb_prepare_for_shift(skb) ||
++ skb_prepare_for_shift(tgt))
++ return 0;
+
-+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-+ if (skb) {
-+ /* 'align' will only take the values 0 or 2 here since all
-+ * frames are required to be aligned to 2-byte boundaries
-+ * when being passed to mac80211; the code here works just
-+ * as well if that isn't true, but mac80211 assumes it can
-+ * access fields as 2-byte aligned (e.g. for ether_addr_equal)
-+ */
-+ int align;
++ /* All previous frag pointers might be stale! */
++ fragfrom = &skb_shinfo(skb)->frags[from];
++ fragto = &skb_shinfo(tgt)->frags[merge];
+
-+ align = (unsigned long)(skb->data + sizeof(struct ethhdr)) & 3;
-+ if (align) {
-+ if (WARN_ON(skb_headroom(skb) < 3)) {
-+ dev_kfree_skb(skb);
-+ skb = NULL;
-+ } else {
-+ u8 *data = skb->data;
-+ size_t len = skb_headlen(skb);
-+ skb->data -= align;
-+ memmove(skb->data, data, len);
-+ skb_set_tail_pointer(skb, len);
-+ }
++ skb_frag_size_add(fragto, shiftlen);
++ skb_frag_size_sub(fragfrom, shiftlen);
++ fragfrom->page_offset += shiftlen;
++
++ goto onlymerged;
+ }
-+ }
-+#endif
+
-+ if (skb) {
-+ /* deliver to local stack */
-+ skb->protocol = eth_type_trans(skb, dev);
-+ memset(skb->cb, 0, sizeof(skb->cb));
-+ if (rx->local->napi)
-+ napi_gro_receive(rx->local->napi, skb);
-+ else
-+ netif_receive_skb(skb);
++ from++;
+ }
+
-+ if (xmit_skb) {
-+ /*
-+ * Send to wireless media and increase priority by 256 to
-+ * keep the received priority instead of reclassifying
-+ * the frame (see cfg80211_classify8021d).
-+ */
-+ xmit_skb->priority += 256;
-+ xmit_skb->protocol = htons(ETH_P_802_3);
-+ skb_reset_network_header(xmit_skb);
-+ skb_reset_mac_header(xmit_skb);
-+ dev_queue_xmit(xmit_skb);
-+ }
-+}
++ /* Skip full, not-fitting skb to avoid expensive operations */
++ if ((shiftlen == skb->len) &&
++ (skb_shinfo(skb)->nr_frags - from) > (MAX_SKB_FRAGS - to))
++ return 0;
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
-+{
-+ struct net_device *dev = rx->sdata->dev;
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ __le16 fc = hdr->frame_control;
-+ struct sk_buff_head frame_list;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
++ if (skb_prepare_for_shift(skb) || skb_prepare_for_shift(tgt))
++ return 0;
+
-+ if (unlikely(!ieee80211_is_data(fc)))
-+ return RX_CONTINUE;
++ while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) {
++ if (to == MAX_SKB_FRAGS)
++ return 0;
+
-+ if (unlikely(!ieee80211_is_data_present(fc)))
-+ return RX_DROP_MONITOR;
++ fragfrom = &skb_shinfo(skb)->frags[from];
++ fragto = &skb_shinfo(tgt)->frags[to];
+
-+ if (!(status->rx_flags & IEEE80211_RX_AMSDU))
-+ return RX_CONTINUE;
++ if (todo >= skb_frag_size(fragfrom)) {
++ *fragto = *fragfrom;
++ todo -= skb_frag_size(fragfrom);
++ from++;
++ to++;
+
-+ if (ieee80211_has_a4(hdr->frame_control) &&
-+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-+ !rx->sdata->u.vlan.sta)
-+ return RX_DROP_UNUSABLE;
++ } else {
++ __skb_frag_ref(fragfrom);
++ fragto->page = fragfrom->page;
++ fragto->page_offset = fragfrom->page_offset;
++ skb_frag_size_set(fragto, todo);
+
-+ if (is_multicast_ether_addr(hdr->addr1) &&
-+ ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-+ rx->sdata->u.vlan.sta) ||
-+ (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
-+ rx->sdata->u.mgd.use_4addr)))
-+ return RX_DROP_UNUSABLE;
++ fragfrom->page_offset += todo;
++ skb_frag_size_sub(fragfrom, todo);
++ todo = 0;
+
-+ skb->dev = dev;
-+ __skb_queue_head_init(&frame_list);
++ to++;
++ break;
++ }
++ }
+
-+ if (skb_linearize(skb))
-+ return RX_DROP_UNUSABLE;
++ /* Ready to "commit" this state change to tgt */
++ skb_shinfo(tgt)->nr_frags = to;
+
-+ ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
-+ rx->sdata->vif.type,
-+ rx->local->hw.extra_tx_headroom, true);
++ if (merge >= 0) {
++ fragfrom = &skb_shinfo(skb)->frags[0];
++ fragto = &skb_shinfo(tgt)->frags[merge];
+
-+ while (!skb_queue_empty(&frame_list)) {
-+ rx->skb = __skb_dequeue(&frame_list);
++ skb_frag_size_add(fragto, skb_frag_size(fragfrom));
++ __skb_frag_unref(fragfrom);
++ }
+
-+ if (!ieee80211_frame_allowed(rx, fc)) {
-+ dev_kfree_skb(rx->skb);
-+ continue;
-+ }
-+ dev->stats.rx_packets++;
-+ dev->stats.rx_bytes += rx->skb->len;
++ /* Reposition in the original skb */
++ to = 0;
++ while (from < skb_shinfo(skb)->nr_frags)
++ skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++];
++ skb_shinfo(skb)->nr_frags = to;
+
-+ ieee80211_deliver_skb(rx);
-+ }
++ BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags);
+
-+ return RX_QUEUED;
-+}
++onlymerged:
++ /* Most likely the tgt won't ever need its checksum anymore, skb on
++ * the other hand might need it if it needs to be resent
++ */
++ tgt->ip_summed = CHECKSUM_PARTIAL;
++ skb->ip_summed = CHECKSUM_PARTIAL;
+
-+#ifdef CONFIG_MAC80211_MESH
-+static ieee80211_rx_result
-+ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
-+{
-+ struct ieee80211_hdr *fwd_hdr, *hdr;
-+ struct ieee80211_tx_info *info;
-+ struct ieee80211s_hdr *mesh_hdr;
-+ struct sk_buff *skb = rx->skb, *fwd_skb;
-+ struct ieee80211_local *local = rx->local;
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ u16 q, hdrlen;
++ /* Yak, is it really working this way? Some helper please? */
++ skb->len -= shiftlen;
++ skb->data_len -= shiftlen;
++ skb->truesize -= shiftlen;
++ tgt->len += shiftlen;
++ tgt->data_len += shiftlen;
++ tgt->truesize += shiftlen;
+
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ return shiftlen;
++}
+
-+ /* make sure fixed part of mesh header is there, also checks skb len */
-+ if (!pskb_may_pull(rx->skb, hdrlen + 6))
-+ return RX_DROP_MONITOR;
++/**
++ * skb_prepare_seq_read - Prepare a sequential read of skb data
++ * @skb: the buffer to read
++ * @from: lower offset of data to be read
++ * @to: upper offset of data to be read
++ * @st: state variable
++ *
++ * Initializes the specified state variable. Must be called before
++ * invoking skb_seq_read() for the first time.
++ */
++void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
++ unsigned int to, struct skb_seq_state *st)
++{
++ st->lower_offset = from;
++ st->upper_offset = to;
++ st->root_skb = st->cur_skb = skb;
++ st->frag_idx = st->stepped_offset = 0;
++ st->frag_data = NULL;
++}
++EXPORT_SYMBOL(skb_prepare_seq_read);
+
-+ mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
++/**
++ * skb_seq_read - Sequentially read skb data
++ * @consumed: number of bytes consumed by the caller so far
++ * @data: destination pointer for data to be returned
++ * @st: state variable
++ *
++ * Reads a block of skb data at @consumed relative to the
++ * lower offset specified to skb_prepare_seq_read(). Assigns
++ * the head of the data block to @data and returns the length
++ * of the block or 0 if the end of the skb data or the upper
++ * offset has been reached.
++ *
++ * The caller is not required to consume all of the data
++ * returned, i.e. @consumed is typically set to the number
++ * of bytes already consumed and the next call to
++ * skb_seq_read() will return the remaining part of the block.
++ *
++ * Note 1: The size of each block of data returned can be arbitrary,
++ * this limitation is the cost for zerocopy sequential
++ * reads of potentially non linear data.
++ *
++ * Note 2: Fragment lists within fragments are not implemented
++ * at the moment, state->root_skb could be replaced with
++ * a stack for this purpose.
++ */
++unsigned int skb_seq_read(unsigned int consumed, const u8 **data,
++ struct skb_seq_state *st)
++{
++ unsigned int block_limit, abs_offset = consumed + st->lower_offset;
++ skb_frag_t *frag;
+
-+ /* make sure full mesh header is there, also checks skb len */
-+ if (!pskb_may_pull(rx->skb,
-+ hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
-+ return RX_DROP_MONITOR;
++ if (unlikely(abs_offset >= st->upper_offset)) {
++ if (st->frag_data) {
++ kunmap_atomic(st->frag_data);
++ st->frag_data = NULL;
++ }
++ return 0;
++ }
+
-+ /* reload pointers */
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
++next_skb:
++ block_limit = skb_headlen(st->cur_skb) + st->stepped_offset;
+
-+ if (ieee80211_drop_unencrypted(rx, hdr->frame_control))
-+ return RX_DROP_MONITOR;
++ if (abs_offset < block_limit && !st->frag_data) {
++ *data = st->cur_skb->data + (abs_offset - st->stepped_offset);
++ return block_limit - abs_offset;
++ }
+
-+ /* frame is in RMC, don't forward */
-+ if (ieee80211_is_data(hdr->frame_control) &&
-+ is_multicast_ether_addr(hdr->addr1) &&
-+ mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
-+ return RX_DROP_MONITOR;
++ if (st->frag_idx == 0 && !st->frag_data)
++ st->stepped_offset += skb_headlen(st->cur_skb);
+
-+ if (!ieee80211_is_data(hdr->frame_control) ||
-+ !(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ return RX_CONTINUE;
++ while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) {
++ frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx];
++ block_limit = skb_frag_size(frag) + st->stepped_offset;
+
-+ if (!mesh_hdr->ttl)
-+ return RX_DROP_MONITOR;
++ if (abs_offset < block_limit) {
++ if (!st->frag_data)
++ st->frag_data = kmap_atomic(skb_frag_page(frag));
+
-+ if (mesh_hdr->flags & MESH_FLAGS_AE) {
-+ struct mesh_path *mppath;
-+ char *proxied_addr;
-+ char *mpp_addr;
++ *data = (u8 *) st->frag_data + frag->page_offset +
++ (abs_offset - st->stepped_offset);
+
-+ if (is_multicast_ether_addr(hdr->addr1)) {
-+ mpp_addr = hdr->addr3;
-+ proxied_addr = mesh_hdr->eaddr1;
-+ } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
-+ /* has_a4 already checked in ieee80211_rx_mesh_check */
-+ mpp_addr = hdr->addr4;
-+ proxied_addr = mesh_hdr->eaddr2;
-+ } else {
-+ return RX_DROP_MONITOR;
++ return block_limit - abs_offset;
+ }
+
-+ rcu_read_lock();
-+ mppath = mpp_path_lookup(sdata, proxied_addr);
-+ if (!mppath) {
-+ mpp_path_add(sdata, proxied_addr, mpp_addr);
-+ } else {
-+ spin_lock_bh(&mppath->state_lock);
-+ if (!ether_addr_equal(mppath->mpp, mpp_addr))
-+ memcpy(mppath->mpp, mpp_addr, ETH_ALEN);
-+ spin_unlock_bh(&mppath->state_lock);
++ if (st->frag_data) {
++ kunmap_atomic(st->frag_data);
++ st->frag_data = NULL;
+ }
-+ rcu_read_unlock();
-+ }
+
-+ /* Frame has reached destination. Don't forward */
-+ if (!is_multicast_ether_addr(hdr->addr1) &&
-+ ether_addr_equal(sdata->vif.addr, hdr->addr3))
-+ return RX_CONTINUE;
++ st->frag_idx++;
++ st->stepped_offset += skb_frag_size(frag);
++ }
+
-+ q = ieee80211_select_queue_80211(sdata, skb, hdr);
-+ if (ieee80211_queue_stopped(&local->hw, q)) {
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion);
-+ return RX_DROP_MONITOR;
++ if (st->frag_data) {
++ kunmap_atomic(st->frag_data);
++ st->frag_data = NULL;
+ }
-+ skb_set_queue_mapping(skb, q);
+
-+ if (!--mesh_hdr->ttl) {
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-+ goto out;
++ if (st->root_skb == st->cur_skb && skb_has_frag_list(st->root_skb)) {
++ st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
++ st->frag_idx = 0;
++ goto next_skb;
++ } else if (st->cur_skb->next) {
++ st->cur_skb = st->cur_skb->next;
++ st->frag_idx = 0;
++ goto next_skb;
+ }
+
-+ if (!ifmsh->mshcfg.dot11MeshForwarding)
-+ goto out;
++ return 0;
++}
++EXPORT_SYMBOL(skb_seq_read);
+
-+ fwd_skb = skb_copy(skb, GFP_ATOMIC);
-+ if (!fwd_skb) {
-+ net_info_ratelimited("%s: failed to clone mesh frame\n",
-+ sdata->name);
-+ goto out;
-+ }
++/**
++ * skb_abort_seq_read - Abort a sequential read of skb data
++ * @st: state variable
++ *
++ * Must be called if skb_seq_read() was not called until it
++ * returned 0.
++ */
++void skb_abort_seq_read(struct skb_seq_state *st)
++{
++ if (st->frag_data)
++ kunmap_atomic(st->frag_data);
++}
++EXPORT_SYMBOL(skb_abort_seq_read);
+
-+ fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
-+ fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
-+ info = IEEE80211_SKB_CB(fwd_skb);
-+ memset(info, 0, sizeof(*info));
-+ info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-+ info->control.vif = &rx->sdata->vif;
-+ info->control.jiffies = jiffies;
-+ if (is_multicast_ether_addr(fwd_hdr->addr1)) {
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
-+ memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
-+ /* update power mode indication when forwarding */
-+ ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
-+ } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
-+ /* mesh power mode flags updated in mesh_nexthop_lookup */
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
-+ } else {
-+ /* unable to resolve next hop */
-+ mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
-+ fwd_hdr->addr3, 0,
-+ WLAN_REASON_MESH_PATH_NOFORWARD,
-+ fwd_hdr->addr2);
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
-+ kfree_skb(fwd_skb);
-+ return RX_DROP_MONITOR;
-+ }
-+
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
-+ ieee80211_add_pending_skb(local, fwd_skb);
-+ out:
-+ if (is_multicast_ether_addr(hdr->addr1) ||
-+ sdata->dev->flags & IFF_PROMISC)
-+ return RX_CONTINUE;
-+ else
-+ return RX_DROP_MONITOR;
++#define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb))
++
++static unsigned int skb_ts_get_next_block(unsigned int offset, const u8 **text,
++ struct ts_config *conf,
++ struct ts_state *state)
++{
++ return skb_seq_read(offset, text, TS_SKB_CB(state));
+}
-+#endif
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
++static void skb_ts_finish(struct ts_config *conf, struct ts_state *state)
+{
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_local *local = rx->local;
-+ struct net_device *dev = sdata->dev;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-+ __le16 fc = hdr->frame_control;
-+ bool port_control;
-+ int err;
++ skb_abort_seq_read(TS_SKB_CB(state));
++}
++
++/**
++ * skb_find_text - Find a text pattern in skb data
++ * @skb: the buffer to look in
++ * @from: search offset
++ * @to: search limit
++ * @config: textsearch configuration
++ * @state: uninitialized textsearch state variable
++ *
++ * Finds a pattern in the skb data according to the specified
++ * textsearch configuration. Use textsearch_next() to retrieve
++ * subsequent occurrences of the pattern. Returns the offset
++ * to the first occurrence or UINT_MAX if no match was found.
++ */
++unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
++ unsigned int to, struct ts_config *config,
++ struct ts_state *state)
++{
++ unsigned int ret;
+
-+ if (unlikely(!ieee80211_is_data(hdr->frame_control)))
-+ return RX_CONTINUE;
++ config->get_next_block = skb_ts_get_next_block;
++ config->finish = skb_ts_finish;
+
-+ if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
-+ return RX_DROP_MONITOR;
++ skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state));
+
-+ /*
-+ * Send unexpected-4addr-frame event to hostapd. For older versions,
-+ * also drop the frame to cooked monitor interfaces.
-+ */
-+ if (ieee80211_has_a4(hdr->frame_control) &&
-+ sdata->vif.type == NL80211_IFTYPE_AP) {
-+ if (rx->sta &&
-+ !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT))
-+ cfg80211_rx_unexpected_4addr_frame(
-+ rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC);
-+ return RX_DROP_MONITOR;
-+ }
++ ret = textsearch_find(config, state);
++ return (ret <= to - from ? ret : UINT_MAX);
++}
++EXPORT_SYMBOL(skb_find_text);
+
-+ err = __ieee80211_data_to_8023(rx, &port_control);
-+ if (unlikely(err))
-+ return RX_DROP_UNUSABLE;
++/**
++ * skb_append_datato_frags - append the user data to a skb
++ * @sk: sock structure
++ * @skb: skb structure to be appended with user data.
++ * @getfrag: call back function to be used for getting the user data
++ * @from: pointer to user message iov
++ * @length: length of the iov message
++ *
++ * Description: This procedure append the user data in the fragment part
++ * of the skb if any page alloc fails user this procedure returns -ENOMEM
++ */
++int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
++ int (*getfrag)(void *from, char *to, int offset,
++ int len, int odd, struct sk_buff *skb),
++ void *from, int length)
++{
++ int frg_cnt = skb_shinfo(skb)->nr_frags;
++ int copy;
++ int offset = 0;
++ int ret;
++ struct page_frag *pfrag = &current->task_frag;
+
-+ if (!ieee80211_frame_allowed(rx, fc))
-+ return RX_DROP_MONITOR;
++ do {
++ /* Return error if we don't have space for new frag */
++ if (frg_cnt >= MAX_SKB_FRAGS)
++ return -EMSGSIZE;
+
-+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-+ unlikely(port_control) && sdata->bss) {
-+ sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
-+ u.ap);
-+ dev = sdata->dev;
-+ rx->sdata = sdata;
-+ }
++ if (!sk_page_frag_refill(sk, pfrag))
++ return -ENOMEM;
++
++ /* copy the user data to page */
++ copy = min_t(int, length, pfrag->size - pfrag->offset);
+
-+ rx->skb->dev = dev;
++ ret = getfrag(from, page_address(pfrag->page) + pfrag->offset,
++ offset, copy, 0, skb);
++ if (ret < 0)
++ return -EFAULT;
+
-+ dev->stats.rx_packets++;
-+ dev->stats.rx_bytes += rx->skb->len;
++ /* copy was successful so update the size parameters */
++ skb_fill_page_desc(skb, frg_cnt, pfrag->page, pfrag->offset,
++ copy);
++ frg_cnt++;
++ pfrag->offset += copy;
++ get_page(pfrag->page);
+
-+ if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
-+ !is_multicast_ether_addr(
-+ ((struct ethhdr *)rx->skb->data)->h_dest) &&
-+ (!local->scanning &&
-+ !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) {
-+ mod_timer(&local->dynamic_ps_timer, jiffies +
-+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
-+ }
++ skb->truesize += copy;
++ atomic_add(copy, &sk->sk_wmem_alloc);
++ skb->len += copy;
++ skb->data_len += copy;
++ offset += copy;
++ length -= copy;
+
-+ ieee80211_deliver_skb(rx);
++ } while (length > 0);
+
-+ return RX_QUEUED;
++ return 0;
+}
++EXPORT_SYMBOL(skb_append_datato_frags);
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
++/**
++ * skb_pull_rcsum - pull skb and update receive checksum
++ * @skb: buffer to update
++ * @len: length of data pulled
++ *
++ * This function performs an skb_pull on the packet and updates
++ * the CHECKSUM_COMPLETE checksum. It should be used on
++ * receive path processing instead of skb_pull unless you know
++ * that the checksum difference is zero (e.g., a valid IP header)
++ * or you are setting ip_summed to CHECKSUM_NONE.
++ */
++unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
+{
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
-+ struct tid_ampdu_rx *tid_agg_rx;
-+ u16 start_seq_num;
-+ u16 tid;
++ BUG_ON(len > skb->len);
++ skb->len -= len;
++ BUG_ON(skb->len < skb->data_len);
++ skb_postpull_rcsum(skb, skb->data, len);
++ return skb->data += len;
++}
++EXPORT_SYMBOL_GPL(skb_pull_rcsum);
+
-+ if (likely(!ieee80211_is_ctl(bar->frame_control)))
-+ return RX_CONTINUE;
++/**
++ * skb_segment - Perform protocol segmentation on skb.
++ * @head_skb: buffer to segment
++ * @features: features for the output path (see dev->features)
++ *
++ * This function performs segmentation on the given skb. It returns
++ * a pointer to the first in a list of new skbs for the segments.
++ * In case of error it returns ERR_PTR(err).
++ */
++struct sk_buff *skb_segment(struct sk_buff *head_skb,
++ netdev_features_t features)
++{
++ struct sk_buff *segs = NULL;
++ struct sk_buff *tail = NULL;
++ struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
++ skb_frag_t *frag = skb_shinfo(head_skb)->frags;
++ unsigned int mss = skb_shinfo(head_skb)->gso_size;
++ unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
++ struct sk_buff *frag_skb = head_skb;
++ unsigned int offset = doffset;
++ unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
++ unsigned int headroom;
++ unsigned int len;
++ __be16 proto;
++ bool csum;
++ int sg = !!(features & NETIF_F_SG);
++ int nfrags = skb_shinfo(head_skb)->nr_frags;
++ int err = -ENOMEM;
++ int i = 0;
++ int pos;
++ int dummy;
+
-+ if (ieee80211_is_back_req(bar->frame_control)) {
-+ struct {
-+ __le16 control, start_seq_num;
-+ } __packed bar_data;
++ __skb_push(head_skb, doffset);
++ proto = skb_network_protocol(head_skb, &dummy);
++ if (unlikely(!proto))
++ return ERR_PTR(-EINVAL);
+
-+ if (!rx->sta)
-+ return RX_DROP_MONITOR;
++ csum = !head_skb->encap_hdr_csum &&
++ !!can_checksum_protocol(features, proto);
+
-+ if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
-+ &bar_data, sizeof(bar_data)))
-+ return RX_DROP_MONITOR;
++ headroom = skb_headroom(head_skb);
++ pos = skb_headlen(head_skb);
+
-+ tid = le16_to_cpu(bar_data.control) >> 12;
++ do {
++ struct sk_buff *nskb;
++ skb_frag_t *nskb_frag;
++ int hsize;
++ int size;
++
++ len = head_skb->len - offset;
++ if (len > mss)
++ len = mss;
++
++ hsize = skb_headlen(head_skb) - offset;
++ if (hsize < 0)
++ hsize = 0;
++ if (hsize > len || !sg)
++ hsize = len;
++
++ if (!hsize && i >= nfrags && skb_headlen(list_skb) &&
++ (skb_headlen(list_skb) == len || sg)) {
++ BUG_ON(skb_headlen(list_skb) > len);
++
++ i = 0;
++ nfrags = skb_shinfo(list_skb)->nr_frags;
++ frag = skb_shinfo(list_skb)->frags;
++ frag_skb = list_skb;
++ pos += skb_headlen(list_skb);
++
++ while (pos < offset + len) {
++ BUG_ON(i >= nfrags);
++
++ size = skb_frag_size(frag);
++ if (pos + size > offset + len)
++ break;
++
++ i++;
++ pos += size;
++ frag++;
++ }
+
-+ tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]);
-+ if (!tid_agg_rx)
-+ return RX_DROP_MONITOR;
++ nskb = skb_clone(list_skb, GFP_ATOMIC);
++ list_skb = list_skb->next;
+
-+ start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
++ if (unlikely(!nskb))
++ goto err;
+
-+ /* reset session timer */
-+ if (tid_agg_rx->timeout)
-+ mod_timer(&tid_agg_rx->session_timer,
-+ TU_TO_EXP_TIME(tid_agg_rx->timeout));
++ if (unlikely(pskb_trim(nskb, len))) {
++ kfree_skb(nskb);
++ goto err;
++ }
+
-+ spin_lock(&tid_agg_rx->reorder_lock);
-+ /* release stored frames up to start of BAR */
-+ ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx,
-+ start_seq_num, frames);
-+ spin_unlock(&tid_agg_rx->reorder_lock);
++ hsize = skb_end_offset(nskb);
++ if (skb_cow_head(nskb, doffset + headroom)) {
++ kfree_skb(nskb);
++ goto err;
++ }
+
-+ kfree_skb(skb);
-+ return RX_QUEUED;
-+ }
++ nskb->truesize += skb_end_offset(nskb) - hsize;
++ skb_release_head_state(nskb);
++ __skb_push(nskb, doffset);
++ } else {
++ nskb = __alloc_skb(hsize + doffset + headroom,
++ GFP_ATOMIC, skb_alloc_rx_flag(head_skb),
++ NUMA_NO_NODE);
+
-+ /*
-+ * After this point, we only want management frames,
-+ * so we can drop all remaining control frames to
-+ * cooked monitor interfaces.
-+ */
-+ return RX_DROP_MONITOR;
-+}
++ if (unlikely(!nskb))
++ goto err;
+
-+static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *resp;
++ skb_reserve(nskb, headroom);
++ __skb_put(nskb, doffset);
++ }
+
-+ if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) {
-+ /* Not to own unicast address */
-+ return;
-+ }
++ if (segs)
++ tail->next = nskb;
++ else
++ segs = nskb;
++ tail = nskb;
+
-+ if (!ether_addr_equal(mgmt->sa, sdata->u.mgd.bssid) ||
-+ !ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) {
-+ /* Not from the current AP or not associated yet. */
-+ return;
-+ }
++ __copy_skb_header(nskb, head_skb);
+
-+ if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) {
-+ /* Too short SA Query request frame */
-+ return;
-+ }
++ skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
++ skb_reset_mac_len(nskb);
+
-+ skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom);
-+ if (skb == NULL)
-+ return;
++ skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
++ nskb->data - tnl_hlen,
++ doffset + tnl_hlen);
+
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ resp = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(resp, 0, 24);
-+ memcpy(resp->da, mgmt->sa, ETH_ALEN);
-+ memcpy(resp->sa, sdata->vif.addr, ETH_ALEN);
-+ memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-+ resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-+ IEEE80211_STYPE_ACTION);
-+ skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));
-+ resp->u.action.category = WLAN_CATEGORY_SA_QUERY;
-+ resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE;
-+ memcpy(resp->u.action.u.sa_query.trans_id,
-+ mgmt->u.action.u.sa_query.trans_id,
-+ WLAN_SA_QUERY_TR_ID_LEN);
++ if (nskb->len == len + doffset)
++ goto perform_csum_check;
+
-+ ieee80211_tx_skb(sdata, skb);
-+}
++ if (!sg) {
++ nskb->ip_summed = CHECKSUM_NONE;
++ nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
++ skb_put(nskb, len),
++ len, 0);
++ SKB_GSO_CB(nskb)->csum_start =
++ skb_headroom(nskb) + doffset;
++ continue;
++ }
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
-+{
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
++ nskb_frag = skb_shinfo(nskb)->frags;
+
-+ /*
-+ * From here on, look only at management frames.
-+ * Data and control frames are already handled,
-+ * and unknown (reserved) frames are useless.
-+ */
-+ if (rx->skb->len < 24)
-+ return RX_DROP_MONITOR;
++ skb_copy_from_linear_data_offset(head_skb, offset,
++ skb_put(nskb, hsize), hsize);
+
-+ if (!ieee80211_is_mgmt(mgmt->frame_control))
-+ return RX_DROP_MONITOR;
++ skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags &
++ SKBTX_SHARED_FRAG;
+
-+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
-+ ieee80211_is_beacon(mgmt->frame_control) &&
-+ !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
-+ int sig = 0;
++ while (pos < offset + len) {
++ if (i >= nfrags) {
++ BUG_ON(skb_headlen(list_skb));
+
-+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
-+ sig = status->signal;
++ i = 0;
++ nfrags = skb_shinfo(list_skb)->nr_frags;
++ frag = skb_shinfo(list_skb)->frags;
++ frag_skb = list_skb;
+
-+ cfg80211_report_obss_beacon(rx->local->hw.wiphy,
-+ rx->skb->data, rx->skb->len,
-+ status->freq, sig);
-+ rx->flags |= IEEE80211_RX_BEACON_REPORTED;
-+ }
++ BUG_ON(!nfrags);
++
++ list_skb = list_skb->next;
++ }
+
-+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ return RX_DROP_MONITOR;
++ if (unlikely(skb_shinfo(nskb)->nr_frags >=
++ MAX_SKB_FRAGS)) {
++ net_warn_ratelimited(
++ "skb_segment: too many frags: %u %u\n",
++ pos, mss);
++ goto err;
++ }
++
++ if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC)))
++ goto err;
++
++ *nskb_frag = *frag;
++ __skb_frag_ref(nskb_frag);
++ size = skb_frag_size(nskb_frag);
++
++ if (pos < offset) {
++ nskb_frag->page_offset += offset - pos;
++ skb_frag_size_sub(nskb_frag, offset - pos);
++ }
++
++ skb_shinfo(nskb)->nr_frags++;
++
++ if (pos + size <= offset + len) {
++ i++;
++ frag++;
++ pos += size;
++ } else {
++ skb_frag_size_sub(nskb_frag, pos + size - (offset + len));
++ goto skip_fraglist;
++ }
++
++ nskb_frag++;
++ }
++
++skip_fraglist:
++ nskb->data_len = len - hsize;
++ nskb->len += nskb->data_len;
++ nskb->truesize += nskb->data_len;
++
++perform_csum_check:
++ if (!csum) {
++ nskb->csum = skb_checksum(nskb, doffset,
++ nskb->len - doffset, 0);
++ nskb->ip_summed = CHECKSUM_NONE;
++ SKB_GSO_CB(nskb)->csum_start =
++ skb_headroom(nskb) + doffset;
++ }
++ } while ((offset += len) < head_skb->len);
+
-+ if (ieee80211_drop_unencrypted_mgmt(rx))
-+ return RX_DROP_UNUSABLE;
++ /* Some callers want to get the end of the list.
++ * Put it in segs->prev to avoid walking the list.
++ * (see validate_xmit_skb_list() for example)
++ */
++ segs->prev = tail;
++ return segs;
+
-+ return RX_CONTINUE;
++err:
++ kfree_skb_list(segs);
++ return ERR_PTR(err);
+}
++EXPORT_SYMBOL_GPL(skb_segment);
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
++int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+{
-+ struct ieee80211_local *local = rx->local;
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-+ int len = rx->skb->len;
++ struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);
++ unsigned int offset = skb_gro_offset(skb);
++ unsigned int headlen = skb_headlen(skb);
++ struct sk_buff *nskb, *lp, *p = *head;
++ unsigned int len = skb_gro_len(skb);
++ unsigned int delta_truesize;
++ unsigned int headroom;
+
-+ if (!ieee80211_is_action(mgmt->frame_control))
-+ return RX_CONTINUE;
++ if (unlikely(p->len + len >= 65536))
++ return -E2BIG;
+
-+ /* drop too small frames */
-+ if (len < IEEE80211_MIN_ACTION_SIZE)
-+ return RX_DROP_UNUSABLE;
++ lp = NAPI_GRO_CB(p)->last;
++ pinfo = skb_shinfo(lp);
+
-+ if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
-+ mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED &&
-+ mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
-+ return RX_DROP_UNUSABLE;
++ if (headlen <= offset) {
++ skb_frag_t *frag;
++ skb_frag_t *frag2;
++ int i = skbinfo->nr_frags;
++ int nr_frags = pinfo->nr_frags + i;
+
-+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-+ return RX_DROP_UNUSABLE;
++ if (nr_frags > MAX_SKB_FRAGS)
++ goto merge;
+
-+ switch (mgmt->u.action.category) {
-+ case WLAN_CATEGORY_HT:
-+ /* reject HT action frames from stations not supporting HT */
-+ if (!rx->sta->sta.ht_cap.ht_supported)
-+ goto invalid;
++ offset -= headlen;
++ pinfo->nr_frags = nr_frags;
++ skbinfo->nr_frags = 0;
+
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-+ sdata->vif.type != NL80211_IFTYPE_AP &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
-+ break;
++ frag = pinfo->frags + nr_frags;
++ frag2 = skbinfo->frags + i;
++ do {
++ *--frag = *--frag2;
++ } while (--i);
+
-+ /* verify action & smps_control/chanwidth are present */
-+ if (len < IEEE80211_MIN_ACTION_SIZE + 2)
-+ goto invalid;
++ frag->page_offset += offset;
++ skb_frag_size_sub(frag, offset);
+
-+ switch (mgmt->u.action.u.ht_smps.action) {
-+ case WLAN_HT_ACTION_SMPS: {
-+ struct ieee80211_supported_band *sband;
-+ enum ieee80211_smps_mode smps_mode;
++ /* all fragments truesize : remove (head size + sk_buff) */
++ delta_truesize = skb->truesize -
++ SKB_TRUESIZE(skb_end_offset(skb));
+
-+ /* convert to HT capability */
-+ switch (mgmt->u.action.u.ht_smps.smps_control) {
-+ case WLAN_HT_SMPS_CONTROL_DISABLED:
-+ smps_mode = IEEE80211_SMPS_OFF;
-+ break;
-+ case WLAN_HT_SMPS_CONTROL_STATIC:
-+ smps_mode = IEEE80211_SMPS_STATIC;
-+ break;
-+ case WLAN_HT_SMPS_CONTROL_DYNAMIC:
-+ smps_mode = IEEE80211_SMPS_DYNAMIC;
-+ break;
-+ default:
-+ goto invalid;
-+ }
++ skb->truesize -= skb->data_len;
++ skb->len -= skb->data_len;
++ skb->data_len = 0;
+
-+ /* if no change do nothing */
-+ if (rx->sta->sta.smps_mode == smps_mode)
-+ goto handled;
-+ rx->sta->sta.smps_mode = smps_mode;
++ NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE;
++ goto done;
++ } else if (skb->head_frag) {
++ int nr_frags = pinfo->nr_frags;
++ skb_frag_t *frag = pinfo->frags + nr_frags;
++ struct page *page = virt_to_head_page(skb->head);
++ unsigned int first_size = headlen - offset;
++ unsigned int first_offset;
+
-+ sband = rx->local->hw.wiphy->bands[status->band];
++ if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS)
++ goto merge;
+
-+ rate_control_rate_update(local, sband, rx->sta,
-+ IEEE80211_RC_SMPS_CHANGED);
-+ goto handled;
-+ }
-+ case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
-+ struct ieee80211_supported_band *sband;
-+ u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
-+ enum ieee80211_sta_rx_bandwidth new_bw;
-+
-+ /* If it doesn't support 40 MHz it can't change ... */
-+ if (!(rx->sta->sta.ht_cap.cap &
-+ IEEE80211_HT_CAP_SUP_WIDTH_20_40))
-+ goto handled;
-+
-+ if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ)
-+ new_bw = IEEE80211_STA_RX_BW_20;
-+ else
-+ new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
++ first_offset = skb->data -
++ (unsigned char *)page_address(page) +
++ offset;
+
-+ if (rx->sta->sta.bandwidth == new_bw)
-+ goto handled;
++ pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags;
+
-+ sband = rx->local->hw.wiphy->bands[status->band];
++ frag->page.p = page;
++ frag->page_offset = first_offset;
++ skb_frag_size_set(frag, first_size);
+
-+ rate_control_rate_update(local, sband, rx->sta,
-+ IEEE80211_RC_BW_CHANGED);
-+ goto handled;
-+ }
-+ default:
-+ goto invalid;
-+ }
++ memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags);
++ /* We dont need to clear skbinfo->nr_frags here */
+
-+ break;
-+ case WLAN_CATEGORY_PUBLIC:
-+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
-+ goto invalid;
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
-+ break;
-+ if (!rx->sta)
-+ break;
-+ if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid))
-+ break;
-+ if (mgmt->u.action.u.ext_chan_switch.action_code !=
-+ WLAN_PUB_ACTION_EXT_CHANSW_ANN)
-+ break;
-+ if (len < offsetof(struct ieee80211_mgmt,
-+ u.action.u.ext_chan_switch.variable))
-+ goto invalid;
-+ goto queue;
-+ case WLAN_CATEGORY_VHT:
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-+ sdata->vif.type != NL80211_IFTYPE_AP &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
-+ break;
++ delta_truesize = skb->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));
++ NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
++ goto done;
++ }
++ /* switch back to head shinfo */
++ pinfo = skb_shinfo(p);
+
-+ /* verify action code is present */
-+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
-+ goto invalid;
++ if (pinfo->frag_list)
++ goto merge;
++ if (skb_gro_len(p) != pinfo->gso_size)
++ return -E2BIG;
+
-+ switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
-+ case WLAN_VHT_ACTION_OPMODE_NOTIF: {
-+ u8 opmode;
++ headroom = skb_headroom(p);
++ nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
++ if (unlikely(!nskb))
++ return -ENOMEM;
+
-+ /* verify opmode is present */
-+ if (len < IEEE80211_MIN_ACTION_SIZE + 2)
-+ goto invalid;
++ __copy_skb_header(nskb, p);
++ nskb->mac_len = p->mac_len;
+
-+ opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
++ skb_reserve(nskb, headroom);
++ __skb_put(nskb, skb_gro_offset(p));
+
-+ ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
-+ opmode, status->band,
-+ false);
-+ goto handled;
-+ }
-+ default:
-+ break;
-+ }
-+ break;
-+ case WLAN_CATEGORY_BACK:
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
-+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
-+ sdata->vif.type != NL80211_IFTYPE_AP &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
-+ break;
++ skb_set_mac_header(nskb, skb_mac_header(p) - p->data);
++ skb_set_network_header(nskb, skb_network_offset(p));
++ skb_set_transport_header(nskb, skb_transport_offset(p));
+
-+ /* verify action_code is present */
-+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
-+ break;
++ __skb_pull(p, skb_gro_offset(p));
++ memcpy(skb_mac_header(nskb), skb_mac_header(p),
++ p->data - skb_mac_header(p));
+
-+ switch (mgmt->u.action.u.addba_req.action_code) {
-+ case WLAN_ACTION_ADDBA_REQ:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.addba_req)))
-+ goto invalid;
-+ break;
-+ case WLAN_ACTION_ADDBA_RESP:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.addba_resp)))
-+ goto invalid;
-+ break;
-+ case WLAN_ACTION_DELBA:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.delba)))
-+ goto invalid;
-+ break;
-+ default:
-+ goto invalid;
-+ }
++ skb_shinfo(nskb)->frag_list = p;
++ skb_shinfo(nskb)->gso_size = pinfo->gso_size;
++ pinfo->gso_size = 0;
++ __skb_header_release(p);
++ NAPI_GRO_CB(nskb)->last = p;
+
-+ goto queue;
-+ case WLAN_CATEGORY_SPECTRUM_MGMT:
-+ /* verify action_code is present */
-+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
-+ break;
++ nskb->data_len += p->len;
++ nskb->truesize += p->truesize;
++ nskb->len += p->len;
+
-+ switch (mgmt->u.action.u.measurement.action_code) {
-+ case WLAN_ACTION_SPCT_MSR_REQ:
-+ if (status->band != IEEE80211_BAND_5GHZ)
-+ break;
++ *head = nskb;
++ nskb->next = p->next;
++ p->next = NULL;
+
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.measurement)))
-+ break;
++ p = nskb;
+
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
-+ break;
++merge:
++ delta_truesize = skb->truesize;
++ if (offset > headlen) {
++ unsigned int eat = offset - headlen;
+
-+ ieee80211_process_measurement_req(sdata, mgmt, len);
-+ goto handled;
-+ case WLAN_ACTION_SPCT_CHL_SWITCH: {
-+ u8 *bssid;
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.chan_switch)))
-+ break;
++ skbinfo->frags[0].page_offset += eat;
++ skb_frag_size_sub(&skbinfo->frags[0], eat);
++ skb->data_len -= eat;
++ skb->len -= eat;
++ offset = headlen;
++ }
+
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
-+ break;
++ __skb_pull(skb, offset);
+
-+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
-+ bssid = sdata->u.mgd.bssid;
-+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+ bssid = sdata->u.ibss.bssid;
-+ else if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-+ bssid = mgmt->sa;
-+ else
-+ break;
++ if (NAPI_GRO_CB(p)->last == p)
++ skb_shinfo(p)->frag_list = skb;
++ else
++ NAPI_GRO_CB(p)->last->next = skb;
++ NAPI_GRO_CB(p)->last = skb;
++ __skb_header_release(skb);
++ lp = p;
+
-+ if (!ether_addr_equal(mgmt->bssid, bssid))
-+ break;
++done:
++ NAPI_GRO_CB(p)->count++;
++ p->data_len += len;
++ p->truesize += delta_truesize;
++ p->len += len;
++ if (lp != p) {
++ lp->data_len += len;
++ lp->truesize += delta_truesize;
++ lp->len += len;
++ }
++ NAPI_GRO_CB(skb)->same_flow = 1;
++ return 0;
++}
+
-+ goto queue;
-+ }
-+ }
-+ break;
-+ case WLAN_CATEGORY_SA_QUERY:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.sa_query)))
-+ break;
++void __init skb_init(void)
++{
++ skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
++ sizeof(struct sk_buff),
++ 0,
++ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
++ NULL);
++ skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
++ sizeof(struct sk_buff_fclones),
++ 0,
++ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
++ NULL);
++}
+
-+ switch (mgmt->u.action.u.sa_query.action) {
-+ case WLAN_ACTION_SA_QUERY_REQUEST:
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
-+ break;
-+ ieee80211_process_sa_query_req(sdata, mgmt, len);
-+ goto handled;
++/**
++ * skb_to_sgvec - Fill a scatter-gather list from a socket buffer
++ * @skb: Socket buffer containing the buffers to be mapped
++ * @sg: The scatter-gather list to map into
++ * @offset: The offset into the buffer's contents to start mapping
++ * @len: Length of buffer space to be mapped
++ *
++ * Fill the specified scatter-gather list with mappings/pointers into a
++ * region of the buffer space attached to a socket buffer.
++ */
++static int
++__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
++{
++ int start = skb_headlen(skb);
++ int i, copy = start - offset;
++ struct sk_buff *frag_iter;
++ int elt = 0;
++
++ if (copy > 0) {
++ if (copy > len)
++ copy = len;
++ sg_set_buf(sg, skb->data + offset, copy);
++ elt++;
++ if ((len -= copy) == 0)
++ return elt;
++ offset += copy;
++ }
++
++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++ int end;
++
++ WARN_ON(start > offset + len);
++
++ end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]);
++ if ((copy = end - offset) > 0) {
++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++
++ if (copy > len)
++ copy = len;
++ sg_set_page(&sg[elt], skb_frag_page(frag), copy,
++ frag->page_offset+offset-start);
++ elt++;
++ if (!(len -= copy))
++ return elt;
++ offset += copy;
+ }
-+ break;
-+ case WLAN_CATEGORY_SELF_PROTECTED:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.self_prot.action_code)))
-+ break;
++ start = end;
++ }
+
-+ switch (mgmt->u.action.u.self_prot.action_code) {
-+ case WLAN_SP_MESH_PEERING_OPEN:
-+ case WLAN_SP_MESH_PEERING_CLOSE:
-+ case WLAN_SP_MESH_PEERING_CONFIRM:
-+ if (!ieee80211_vif_is_mesh(&sdata->vif))
-+ goto invalid;
-+ if (sdata->u.mesh.user_mpm)
-+ /* userspace handles this frame */
-+ break;
-+ goto queue;
-+ case WLAN_SP_MGK_INFORM:
-+ case WLAN_SP_MGK_ACK:
-+ if (!ieee80211_vif_is_mesh(&sdata->vif))
-+ goto invalid;
-+ break;
-+ }
-+ break;
-+ case WLAN_CATEGORY_MESH_ACTION:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.mesh_action.action_code)))
-+ break;
++ skb_walk_frags(skb, frag_iter) {
++ int end;
+
-+ if (!ieee80211_vif_is_mesh(&sdata->vif))
-+ break;
-+ if (mesh_action_is_path_sel(mgmt) &&
-+ !mesh_path_sel_is_hwmp(sdata))
-+ break;
-+ goto queue;
++ WARN_ON(start > offset + len);
++
++ end = start + frag_iter->len;
++ if ((copy = end - offset) > 0) {
++ if (copy > len)
++ copy = len;
++ elt += __skb_to_sgvec(frag_iter, sg+elt, offset - start,
++ copy);
++ if ((len -= copy) == 0)
++ return elt;
++ offset += copy;
++ }
++ start = end;
+ }
++ BUG_ON(len);
++ return elt;
++}
+
-+ return RX_CONTINUE;
++/* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given
++ * sglist without mark the sg which contain last skb data as the end.
++ * So the caller can mannipulate sg list as will when padding new data after
++ * the first call without calling sg_unmark_end to expend sg list.
++ *
++ * Scenario to use skb_to_sgvec_nomark:
++ * 1. sg_init_table
++ * 2. skb_to_sgvec_nomark(payload1)
++ * 3. skb_to_sgvec_nomark(payload2)
++ *
++ * This is equivalent to:
++ * 1. sg_init_table
++ * 2. skb_to_sgvec(payload1)
++ * 3. sg_unmark_end
++ * 4. skb_to_sgvec(payload2)
++ *
++ * When mapping mutilple payload conditionally, skb_to_sgvec_nomark
++ * is more preferable.
++ */
++int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
++ int offset, int len)
++{
++ return __skb_to_sgvec(skb, sg, offset, len);
++}
++EXPORT_SYMBOL_GPL(skb_to_sgvec_nomark);
+
-+ invalid:
-+ status->rx_flags |= IEEE80211_RX_MALFORMED_ACTION_FRM;
-+ /* will return in the next handlers */
-+ return RX_CONTINUE;
++int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
++{
++ int nsg = __skb_to_sgvec(skb, sg, offset, len);
+
-+ handled:
-+ if (rx->sta)
-+ rx->sta->rx_packets++;
-+ dev_kfree_skb(rx->skb);
-+ return RX_QUEUED;
++ sg_mark_end(&sg[nsg - 1]);
+
-+ queue:
-+ rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
-+ skb_queue_tail(&sdata->skb_queue, rx->skb);
-+ ieee80211_queue_work(&local->hw, &sdata->work);
-+ if (rx->sta)
-+ rx->sta->rx_packets++;
-+ return RX_QUEUED;
++ return nsg;
+}
++EXPORT_SYMBOL_GPL(skb_to_sgvec);
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
++/**
++ * skb_cow_data - Check that a socket buffer's data buffers are writable
++ * @skb: The socket buffer to check.
++ * @tailbits: Amount of trailing space to be added
++ * @trailer: Returned pointer to the skb where the @tailbits space begins
++ *
++ * Make sure that the data buffers attached to a socket buffer are
++ * writable. If they are not, private copies are made of the data buffers
++ * and the socket buffer is set to use these instead.
++ *
++ * If @tailbits is given, make sure that there is space to write @tailbits
++ * bytes of data beyond current end of socket buffer. @trailer will be
++ * set to point to the skb in which this space begins.
++ *
++ * The number of scatterlist elements required to completely map the
++ * COW'd and extended socket buffer will be returned.
++ */
++int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
+{
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-+ int sig = 0;
++ int copyflag;
++ int elt;
++ struct sk_buff *skb1, **skb_p;
+
-+ /* skip known-bad action frames and return them in the next handler */
-+ if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM)
-+ return RX_CONTINUE;
-+
-+ /*
-+ * Getting here means the kernel doesn't know how to handle
-+ * it, but maybe userspace does ... include returned frames
-+ * so userspace can register for those to know whether ones
-+ * it transmitted were processed or returned.
++ /* If skb is cloned or its head is paged, reallocate
++ * head pulling out all the pages (pages are considered not writable
++ * at the moment even if they are anonymous).
+ */
++ if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
++ __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL)
++ return -ENOMEM;
++
++ /* Easy case. Most of packets will go this way. */
++ if (!skb_has_frag_list(skb)) {
++ /* A little of trouble, not enough of space for trailer.
++ * This should not happen, when stack is tuned to generate
++ * good frames. OK, on miss we reallocate and reserve even more
++ * space, 128 bytes is fair. */
+
-+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
-+ sig = status->signal;
++ if (skb_tailroom(skb) < tailbits &&
++ pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
++ return -ENOMEM;
+
-+ if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
-+ rx->skb->data, rx->skb->len, 0)) {
-+ if (rx->sta)
-+ rx->sta->rx_packets++;
-+ dev_kfree_skb(rx->skb);
-+ return RX_QUEUED;
++ /* Voila! */
++ *trailer = skb;
++ return 1;
+ }
+
-+ return RX_CONTINUE;
-+}
++ /* Misery. We are in troubles, going to mincer fragments... */
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
-+{
-+ struct ieee80211_local *local = rx->local;
-+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
-+ struct sk_buff *nskb;
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
++ elt = 1;
++ skb_p = &skb_shinfo(skb)->frag_list;
++ copyflag = 0;
+
-+ if (!ieee80211_is_action(mgmt->frame_control))
-+ return RX_CONTINUE;
++ while ((skb1 = *skb_p) != NULL) {
++ int ntail = 0;
+
-+ /*
-+ * For AP mode, hostapd is responsible for handling any action
-+ * frames that we didn't handle, including returning unknown
-+ * ones. For all other modes we will return them to the sender,
-+ * setting the 0x80 bit in the action category, as required by
-+ * 802.11-2012 9.24.4.
-+ * Newer versions of hostapd shall also use the management frame
-+ * registration mechanisms, but older ones still use cooked
-+ * monitor interfaces so push all frames there.
-+ */
-+ if (!(status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) &&
-+ (sdata->vif.type == NL80211_IFTYPE_AP ||
-+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
-+ return RX_DROP_MONITOR;
-+
-+ if (is_multicast_ether_addr(mgmt->da))
-+ return RX_DROP_MONITOR;
-+
-+ /* do not return rejected action frames */
-+ if (mgmt->u.action.category & 0x80)
-+ return RX_DROP_UNUSABLE;
-+
-+ nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
-+ GFP_ATOMIC);
-+ if (nskb) {
-+ struct ieee80211_mgmt *nmgmt = (void *)nskb->data;
-+
-+ nmgmt->u.action.category |= 0x80;
-+ memcpy(nmgmt->da, nmgmt->sa, ETH_ALEN);
-+ memcpy(nmgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
-+
-+ memset(nskb->cb, 0, sizeof(nskb->cb));
-+
-+ if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
-+
-+ info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
-+ IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
-+ IEEE80211_TX_CTL_NO_CCK_RATE;
-+ if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
-+ info->hw_queue =
-+ local->hw.offchannel_tx_hw_queue;
++ /* The fragment is partially pulled by someone,
++ * this can happen on input. Copy it and everything
++ * after it. */
++
++ if (skb_shared(skb1))
++ copyflag = 1;
++
++ /* If the skb is the last, worry about trailer. */
++
++ if (skb1->next == NULL && tailbits) {
++ if (skb_shinfo(skb1)->nr_frags ||
++ skb_has_frag_list(skb1) ||
++ skb_tailroom(skb1) < tailbits)
++ ntail = tailbits + 128;
+ }
+
-+ __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
-+ status->band);
++ if (copyflag ||
++ skb_cloned(skb1) ||
++ ntail ||
++ skb_shinfo(skb1)->nr_frags ||
++ skb_has_frag_list(skb1)) {
++ struct sk_buff *skb2;
++
++ /* Fuck, we are miserable poor guys... */
++ if (ntail == 0)
++ skb2 = skb_copy(skb1, GFP_ATOMIC);
++ else
++ skb2 = skb_copy_expand(skb1,
++ skb_headroom(skb1),
++ ntail,
++ GFP_ATOMIC);
++ if (unlikely(skb2 == NULL))
++ return -ENOMEM;
++
++ if (skb1->sk)
++ skb_set_owner_w(skb2, skb1->sk);
++
++ /* Looking around. Are we still alive?
++ * OK, link new skb, drop old one */
++
++ skb2->next = skb1->next;
++ *skb_p = skb2;
++ kfree_skb(skb1);
++ skb1 = skb2;
++ }
++ elt++;
++ *trailer = skb1;
++ skb_p = &skb1->next;
+ }
-+ dev_kfree_skb(rx->skb);
-+ return RX_QUEUED;
++
++ return elt;
+}
++EXPORT_SYMBOL_GPL(skb_cow_data);
+
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
++static void sock_rmem_free(struct sk_buff *skb)
+{
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
-+ __le16 stype;
++ struct sock *sk = skb->sk;
+
-+ stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
++ atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
++}
+
-+ if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-+ sdata->vif.type != NL80211_IFTYPE_STATION)
-+ return RX_DROP_MONITOR;
++/*
++ * Note: We dont mem charge error packets (no sk_forward_alloc changes)
++ */
++int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
++{
++ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
++ (unsigned int)sk->sk_rcvbuf)
++ return -ENOMEM;
+
-+ switch (stype) {
-+ case cpu_to_le16(IEEE80211_STYPE_AUTH):
-+ case cpu_to_le16(IEEE80211_STYPE_BEACON):
-+ case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
-+ /* process for all: mesh, mlme, ibss */
-+ break;
-+ case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
-+ case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
-+ case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-+ case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
-+ if (is_multicast_ether_addr(mgmt->da) &&
-+ !is_broadcast_ether_addr(mgmt->da))
-+ return RX_DROP_MONITOR;
-+
-+ /* process only for station */
-+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
-+ return RX_DROP_MONITOR;
-+ break;
-+ case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
-+ /* process only for ibss and mesh */
-+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
-+ return RX_DROP_MONITOR;
-+ break;
-+ default:
-+ return RX_DROP_MONITOR;
-+ }
++ skb_orphan(skb);
++ skb->sk = sk;
++ skb->destructor = sock_rmem_free;
++ atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+
-+ /* queue up frame and kick off work to process it */
-+ rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
-+ skb_queue_tail(&sdata->skb_queue, rx->skb);
-+ ieee80211_queue_work(&rx->local->hw, &sdata->work);
-+ if (rx->sta)
-+ rx->sta->rx_packets++;
++ /* before exiting rcu section, make sure dst is refcounted */
++ skb_dst_force(skb);
+
-+ return RX_QUEUED;
++ skb_queue_tail(&sk->sk_error_queue, skb);
++ if (!sock_flag(sk, SOCK_DEAD))
++ sk->sk_data_ready(sk);
++ return 0;
+}
++EXPORT_SYMBOL(sock_queue_err_skb);
+
-+/* TODO: use IEEE80211_RX_FRAGMENTED */
-+static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
-+ struct ieee80211_rate *rate)
++struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_local *local = rx->local;
-+ struct sk_buff *skb = rx->skb, *skb2;
-+ struct net_device *prev_dev = NULL;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ int needed_headroom;
++ struct sk_buff_head *q = &sk->sk_error_queue;
++ struct sk_buff *skb, *skb_next;
++ unsigned long flags;
++ int err = 0;
+
-+ /*
-+ * If cooked monitor has been processed already, then
-+ * don't do it again. If not, set the flag.
-+ */
-+ if (rx->flags & IEEE80211_RX_CMNTR)
-+ goto out_free_skb;
-+ rx->flags |= IEEE80211_RX_CMNTR;
++ spin_lock_irqsave(&q->lock, flags);
++ skb = __skb_dequeue(q);
++ if (skb && (skb_next = skb_peek(q)))
++ err = SKB_EXT_ERR(skb_next)->ee.ee_errno;
++ spin_unlock_irqrestore(&q->lock, flags);
+
-+ /* If there are no cooked monitor interfaces, just free the SKB */
-+ if (!local->cooked_mntrs)
-+ goto out_free_skb;
++ sk->sk_err = err;
++ if (err)
++ sk->sk_error_report(sk);
+
-+ /* room for the radiotap header based on driver features */
-+ needed_headroom = ieee80211_rx_radiotap_space(local, status);
++ return skb;
++}
++EXPORT_SYMBOL(sock_dequeue_err_skb);
+
-+ if (skb_headroom(skb) < needed_headroom &&
-+ pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
-+ goto out_free_skb;
++/**
++ * skb_clone_sk - create clone of skb, and take reference to socket
++ * @skb: the skb to clone
++ *
++ * This function creates a clone of a buffer that holds a reference on
++ * sk_refcnt. Buffers created via this function are meant to be
++ * returned using sock_queue_err_skb, or free via kfree_skb.
++ *
++ * When passing buffers allocated with this function to sock_queue_err_skb
++ * it is necessary to wrap the call with sock_hold/sock_put in order to
++ * prevent the socket from being released prior to being enqueued on
++ * the sk_error_queue.
++ */
++struct sk_buff *skb_clone_sk(struct sk_buff *skb)
++{
++ struct sock *sk = skb->sk;
++ struct sk_buff *clone;
+
-+ /* prepend radiotap information */
-+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
-+ false);
++ if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt))
++ return NULL;
+
-+ skb_set_mac_header(skb, 0);
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ skb->protocol = htons(ETH_P_802_2);
++ clone = skb_clone(skb, GFP_ATOMIC);
++ if (!clone) {
++ sock_put(sk);
++ return NULL;
++ }
+
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+ if (!ieee80211_sdata_running(sdata))
-+ continue;
++ clone->sk = sk;
++ clone->destructor = sock_efree;
+
-+ if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
-+ !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
-+ continue;
++ return clone;
++}
++EXPORT_SYMBOL(skb_clone_sk);
+
-+ if (prev_dev) {
-+ skb2 = skb_clone(skb, GFP_ATOMIC);
-+ if (skb2) {
-+ skb2->dev = prev_dev;
-+ netif_receive_skb(skb2);
-+ }
-+ }
++static void __skb_complete_tx_timestamp(struct sk_buff *skb,
++ struct sock *sk,
++ int tstype)
++{
++ struct sock_exterr_skb *serr;
++ int err;
+
-+ prev_dev = sdata->dev;
-+ sdata->dev->stats.rx_packets++;
-+ sdata->dev->stats.rx_bytes += skb->len;
++ serr = SKB_EXT_ERR(skb);
++ memset(serr, 0, sizeof(*serr));
++ serr->ee.ee_errno = ENOMSG;
++ serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
++ serr->ee.ee_info = tstype;
++ if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
++ serr->ee.ee_data = skb_shinfo(skb)->tskey;
++ if (sk->sk_protocol == IPPROTO_TCP)
++ serr->ee.ee_data -= sk->sk_tskey;
+ }
+
-+ if (prev_dev) {
-+ skb->dev = prev_dev;
-+ netif_receive_skb(skb);
-+ return;
-+ }
++ err = sock_queue_err_skb(sk, skb);
+
-+ out_free_skb:
-+ dev_kfree_skb(skb);
++ if (err)
++ kfree_skb(skb);
+}
+
-+static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
-+ ieee80211_rx_result res)
++void skb_complete_tx_timestamp(struct sk_buff *skb,
++ struct skb_shared_hwtstamps *hwtstamps)
+{
-+ switch (res) {
-+ case RX_DROP_MONITOR:
-+ I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
-+ if (rx->sta)
-+ rx->sta->rx_dropped++;
-+ /* fall through */
-+ case RX_CONTINUE: {
-+ struct ieee80211_rate *rate = NULL;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_rx_status *status;
++ struct sock *sk = skb->sk;
+
-+ status = IEEE80211_SKB_RXCB((rx->skb));
++ /* take a reference to prevent skb_orphan() from freeing the socket */
++ sock_hold(sk);
+
-+ sband = rx->local->hw.wiphy->bands[status->band];
-+ if (!(status->flag & RX_FLAG_HT) &&
-+ !(status->flag & RX_FLAG_VHT))
-+ rate = &sband->bitrates[status->rate_idx];
++ *skb_hwtstamps(skb) = *hwtstamps;
++ __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND);
+
-+ ieee80211_rx_cooked_monitor(rx, rate);
-+ break;
-+ }
-+ case RX_DROP_UNUSABLE:
-+ I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
-+ if (rx->sta)
-+ rx->sta->rx_dropped++;
-+ dev_kfree_skb(rx->skb);
-+ break;
-+ case RX_QUEUED:
-+ I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued);
-+ break;
-+ }
++ sock_put(sk);
+}
++EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
+
-+static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
-+ struct sk_buff_head *frames)
++void __skb_tstamp_tx(struct sk_buff *orig_skb,
++ struct skb_shared_hwtstamps *hwtstamps,
++ struct sock *sk, int tstype)
+{
-+ ieee80211_rx_result res = RX_DROP_MONITOR;
+ struct sk_buff *skb;
+
-+#define CALL_RXH(rxh) \
-+ do { \
-+ res = rxh(rx); \
-+ if (res != RX_CONTINUE) \
-+ goto rxh_next; \
-+ } while (0);
++ if (!sk)
++ return;
+
-+ spin_lock_bh(&rx->local->rx_path_lock);
++ if (hwtstamps)
++ *skb_hwtstamps(orig_skb) = *hwtstamps;
++ else
++ orig_skb->tstamp = ktime_get_real();
+
-+ while ((skb = __skb_dequeue(frames))) {
-+ /*
-+ * all the other fields are valid across frames
-+ * that belong to an aMPDU since they are on the
-+ * same TID from the same station
-+ */
-+ rx->skb = skb;
++ skb = skb_clone(orig_skb, GFP_ATOMIC);
++ if (!skb)
++ return;
+
-+ CALL_RXH(ieee80211_rx_h_check_more_data)
-+ CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll)
-+ CALL_RXH(ieee80211_rx_h_sta_process)
-+ CALL_RXH(ieee80211_rx_h_decrypt)
-+ CALL_RXH(ieee80211_rx_h_defragment)
-+ CALL_RXH(ieee80211_rx_h_michael_mic_verify)
-+ /* must be after MMIC verify so header is counted in MPDU mic */
-+#ifdef CONFIG_MAC80211_MESH
-+ if (ieee80211_vif_is_mesh(&rx->sdata->vif))
-+ CALL_RXH(ieee80211_rx_h_mesh_fwding);
-+#endif
-+ CALL_RXH(ieee80211_rx_h_amsdu)
-+ CALL_RXH(ieee80211_rx_h_data)
++ __skb_complete_tx_timestamp(skb, sk, tstype);
++}
++EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
++
++void skb_tstamp_tx(struct sk_buff *orig_skb,
++ struct skb_shared_hwtstamps *hwtstamps)
++{
++ return __skb_tstamp_tx(orig_skb, hwtstamps, orig_skb->sk,
++ SCM_TSTAMP_SND);
++}
++EXPORT_SYMBOL_GPL(skb_tstamp_tx);
++
++void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
++{
++ struct sock *sk = skb->sk;
++ struct sock_exterr_skb *serr;
++ int err;
+
-+ /* special treatment -- needs the queue */
-+ res = ieee80211_rx_h_ctrl(rx, frames);
-+ if (res != RX_CONTINUE)
-+ goto rxh_next;
++ skb->wifi_acked_valid = 1;
++ skb->wifi_acked = acked;
+
-+ CALL_RXH(ieee80211_rx_h_mgmt_check)
-+ CALL_RXH(ieee80211_rx_h_action)
-+ CALL_RXH(ieee80211_rx_h_userspace_mgmt)
-+ CALL_RXH(ieee80211_rx_h_action_return)
-+ CALL_RXH(ieee80211_rx_h_mgmt)
++ serr = SKB_EXT_ERR(skb);
++ memset(serr, 0, sizeof(*serr));
++ serr->ee.ee_errno = ENOMSG;
++ serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
+
-+ rxh_next:
-+ ieee80211_rx_handlers_result(rx, res);
++ /* take a reference to prevent skb_orphan() from freeing the socket */
++ sock_hold(sk);
++
++ err = sock_queue_err_skb(sk, skb);
++ if (err)
++ kfree_skb(skb);
++
++ sock_put(sk);
++}
++EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
+
-+#undef CALL_RXH
-+ }
+
-+ spin_unlock_bh(&rx->local->rx_path_lock);
++/**
++ * skb_partial_csum_set - set up and verify partial csum values for packet
++ * @skb: the skb to set
++ * @start: the number of bytes after skb->data to start checksumming.
++ * @off: the offset from start to place the checksum.
++ *
++ * For untrusted partially-checksummed packets, we need to make sure the values
++ * for skb->csum_start and skb->csum_offset are valid so we don't oops.
++ *
++ * This function checks and sets those values and skb->ip_summed: if this
++ * returns false you should drop the packet.
++ */
++bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
++{
++ if (unlikely(start > skb_headlen(skb)) ||
++ unlikely((int)start + off > skb_headlen(skb) - 2)) {
++ net_warn_ratelimited("bad partial csum: csum=%u/%u len=%u\n",
++ start, off, skb_headlen(skb));
++ return false;
++ }
++ skb->ip_summed = CHECKSUM_PARTIAL;
++ skb->csum_start = skb_headroom(skb) + start;
++ skb->csum_offset = off;
++ skb_set_transport_header(skb, start);
++ return true;
+}
++EXPORT_SYMBOL_GPL(skb_partial_csum_set);
+
-+static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
++static int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len,
++ unsigned int max)
+{
-+ struct sk_buff_head reorder_release;
-+ ieee80211_rx_result res = RX_DROP_MONITOR;
++ if (skb_headlen(skb) >= len)
++ return 0;
++
++ /* If we need to pullup then pullup to the max, so we
++ * won't need to do it again.
++ */
++ if (max > skb->len)
++ max = skb->len;
+
-+ __skb_queue_head_init(&reorder_release);
++ if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
++ return -ENOMEM;
+
-+#define CALL_RXH(rxh) \
-+ do { \
-+ res = rxh(rx); \
-+ if (res != RX_CONTINUE) \
-+ goto rxh_next; \
-+ } while (0);
++ if (skb_headlen(skb) < len)
++ return -EPROTO;
+
-+ CALL_RXH(ieee80211_rx_h_check)
++ return 0;
++}
+
-+ ieee80211_rx_reorder_ampdu(rx, &reorder_release);
++#define MAX_TCP_HDR_LEN (15 * 4)
+
-+ ieee80211_rx_handlers(rx, &reorder_release);
-+ return;
++static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb,
++ typeof(IPPROTO_IP) proto,
++ unsigned int off)
++{
++ switch (proto) {
++ int err;
++
++ case IPPROTO_TCP:
++ err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr),
++ off + MAX_TCP_HDR_LEN);
++ if (!err && !skb_partial_csum_set(skb, off,
++ offsetof(struct tcphdr,
++ check)))
++ err = -EPROTO;
++ return err ? ERR_PTR(err) : &tcp_hdr(skb)->check;
+
-+ rxh_next:
-+ ieee80211_rx_handlers_result(rx, res);
++ case IPPROTO_UDP:
++ err = skb_maybe_pull_tail(skb, off + sizeof(struct udphdr),
++ off + sizeof(struct udphdr));
++ if (!err && !skb_partial_csum_set(skb, off,
++ offsetof(struct udphdr,
++ check)))
++ err = -EPROTO;
++ return err ? ERR_PTR(err) : &udp_hdr(skb)->check;
++ }
+
-+#undef CALL_RXH
++ return ERR_PTR(-EPROTO);
+}
+
-+/*
-+ * This function makes calls into the RX path, therefore
-+ * it has to be invoked under RCU read lock.
-+ */
-+void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
-+{
-+ struct sk_buff_head frames;
-+ struct ieee80211_rx_data rx = {
-+ .sta = sta,
-+ .sdata = sta->sdata,
-+ .local = sta->local,
-+ /* This is OK -- must be QoS data frame */
-+ .security_idx = tid,
-+ .seqno_idx = tid,
-+ .flags = 0,
-+ };
-+ struct tid_ampdu_rx *tid_agg_rx;
++/* This value should be large enough to cover a tagged ethernet header plus
++ * maximally sized IP and TCP or UDP headers.
++ */
++#define MAX_IP_HDR_LEN 128
+
-+ tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
-+ if (!tid_agg_rx)
-+ return;
++static int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate)
++{
++ unsigned int off;
++ bool fragment;
++ __sum16 *csum;
++ int err;
++
++ fragment = false;
++
++ err = skb_maybe_pull_tail(skb,
++ sizeof(struct iphdr),
++ MAX_IP_HDR_LEN);
++ if (err < 0)
++ goto out;
++
++ if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
++ fragment = true;
+
-+ __skb_queue_head_init(&frames);
++ off = ip_hdrlen(skb);
+
-+ spin_lock(&tid_agg_rx->reorder_lock);
-+ ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
-+ spin_unlock(&tid_agg_rx->reorder_lock);
++ err = -EPROTO;
++
++ if (fragment)
++ goto out;
+
-+ ieee80211_rx_handlers(&rx, &frames);
++ csum = skb_checksum_setup_ip(skb, ip_hdr(skb)->protocol, off);
++ if (IS_ERR(csum))
++ return PTR_ERR(csum);
++
++ if (recalculate)
++ *csum = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
++ ip_hdr(skb)->daddr,
++ skb->len - off,
++ ip_hdr(skb)->protocol, 0);
++ err = 0;
++
++out:
++ return err;
+}
+
-+/* main receive path */
++/* This value should be large enough to cover a tagged ethernet header plus
++ * an IPv6 header, all options, and a maximal TCP or UDP header.
++ */
++#define MAX_IPV6_HDR_LEN 256
+
-+static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
-+ struct ieee80211_hdr *hdr)
++#define OPT_HDR(type, skb, off) \
++ (type *)(skb_network_header(skb) + (off))
++
++static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate)
+{
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
-+ int multicast = is_multicast_ether_addr(hdr->addr1);
++ int err;
++ u8 nexthdr;
++ unsigned int off;
++ unsigned int len;
++ bool fragment;
++ bool done;
++ __sum16 *csum;
+
-+ switch (sdata->vif.type) {
-+ case NL80211_IFTYPE_STATION:
-+ if (!bssid && !sdata->u.mgd.use_4addr)
-+ return false;
-+ if (!multicast &&
-+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
-+ if (!(sdata->dev->flags & IFF_PROMISC) ||
-+ sdata->u.mgd.use_4addr)
-+ return false;
-+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
++ fragment = false;
++ done = false;
++
++ off = sizeof(struct ipv6hdr);
++
++ err = skb_maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
++ if (err < 0)
++ goto out;
++
++ nexthdr = ipv6_hdr(skb)->nexthdr;
++
++ len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
++ while (off <= len && !done) {
++ switch (nexthdr) {
++ case IPPROTO_DSTOPTS:
++ case IPPROTO_HOPOPTS:
++ case IPPROTO_ROUTING: {
++ struct ipv6_opt_hdr *hp;
++
++ err = skb_maybe_pull_tail(skb,
++ off +
++ sizeof(struct ipv6_opt_hdr),
++ MAX_IPV6_HDR_LEN);
++ if (err < 0)
++ goto out;
++
++ hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
++ nexthdr = hp->nexthdr;
++ off += ipv6_optlen(hp);
++ break;
+ }
-+ break;
-+ case NL80211_IFTYPE_ADHOC:
-+ if (!bssid)
-+ return false;
-+ if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
-+ ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
-+ return false;
-+ if (ieee80211_is_beacon(hdr->frame_control)) {
-+ return true;
-+ } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
-+ return false;
-+ } else if (!multicast &&
-+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
-+ if (!(sdata->dev->flags & IFF_PROMISC))
-+ return false;
-+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-+ } else if (!rx->sta) {
-+ int rate_idx;
-+ if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
-+ rate_idx = 0; /* TODO: HT/VHT rates */
-+ else
-+ rate_idx = status->rate_idx;
-+ ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
-+ BIT(rate_idx));
++ case IPPROTO_AH: {
++ struct ip_auth_hdr *hp;
++
++ err = skb_maybe_pull_tail(skb,
++ off +
++ sizeof(struct ip_auth_hdr),
++ MAX_IPV6_HDR_LEN);
++ if (err < 0)
++ goto out;
++
++ hp = OPT_HDR(struct ip_auth_hdr, skb, off);
++ nexthdr = hp->nexthdr;
++ off += ipv6_authlen(hp);
++ break;
+ }
-+ break;
-+ case NL80211_IFTYPE_MESH_POINT:
-+ if (!multicast &&
-+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
-+ if (!(sdata->dev->flags & IFF_PROMISC))
-+ return false;
++ case IPPROTO_FRAGMENT: {
++ struct frag_hdr *hp;
++
++ err = skb_maybe_pull_tail(skb,
++ off +
++ sizeof(struct frag_hdr),
++ MAX_IPV6_HDR_LEN);
++ if (err < 0)
++ goto out;
++
++ hp = OPT_HDR(struct frag_hdr, skb, off);
++
++ if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
++ fragment = true;
+
-+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
++ nexthdr = hp->nexthdr;
++ off += sizeof(struct frag_hdr);
++ break;
+ }
-+ break;
-+ case NL80211_IFTYPE_AP_VLAN:
-+ case NL80211_IFTYPE_AP:
-+ if (!bssid) {
-+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
-+ return false;
-+ } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
-+ /*
-+ * Accept public action frames even when the
-+ * BSSID doesn't match, this is used for P2P
-+ * and location updates. Note that mac80211
-+ * itself never looks at these frames.
-+ */
-+ if (!multicast &&
-+ !ether_addr_equal(sdata->vif.addr, hdr->addr1))
-+ return false;
-+ if (ieee80211_is_public_action(hdr, skb->len))
-+ return true;
-+ if (!ieee80211_is_beacon(hdr->frame_control))
-+ return false;
-+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-+ } else if (!ieee80211_has_tods(hdr->frame_control)) {
-+ /* ignore data frames to TDLS-peers */
-+ if (ieee80211_is_data(hdr->frame_control))
-+ return false;
-+ /* ignore action frames to TDLS-peers */
-+ if (ieee80211_is_action(hdr->frame_control) &&
-+ !ether_addr_equal(bssid, hdr->addr1))
-+ return false;
++ default:
++ done = true;
++ break;
+ }
-+ break;
-+ case NL80211_IFTYPE_WDS:
-+ if (bssid || !ieee80211_is_data(hdr->frame_control))
-+ return false;
-+ if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
-+ return false;
-+ break;
-+ case NL80211_IFTYPE_P2P_DEVICE:
-+ if (!ieee80211_is_public_action(hdr, skb->len) &&
-+ !ieee80211_is_probe_req(hdr->frame_control) &&
-+ !ieee80211_is_probe_resp(hdr->frame_control) &&
-+ !ieee80211_is_beacon(hdr->frame_control))
-+ return false;
-+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
-+ !multicast)
-+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-+ break;
-+ default:
-+ /* should never get here */
-+ WARN_ON_ONCE(1);
-+ break;
+ }
+
-+ return true;
++ err = -EPROTO;
++
++ if (!done || fragment)
++ goto out;
++
++ csum = skb_checksum_setup_ip(skb, nexthdr, off);
++ if (IS_ERR(csum))
++ return PTR_ERR(csum);
++
++ if (recalculate)
++ *csum = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
++ &ipv6_hdr(skb)->daddr,
++ skb->len - off, nexthdr, 0);
++ err = 0;
++
++out:
++ return err;
+}
+
-+/*
-+ * This function returns whether or not the SKB
-+ * was destined for RX processing or not, which,
-+ * if consume is true, is equivalent to whether
-+ * or not the skb was consumed.
++/**
++ * skb_checksum_setup - set up partial checksum offset
++ * @skb: the skb to set up
++ * @recalculate: if true the pseudo-header checksum will be recalculated
+ */
-+static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
-+ struct sk_buff *skb, bool consume)
++int skb_checksum_setup(struct sk_buff *skb, bool recalculate)
+{
-+ struct ieee80211_local *local = rx->local;
-+ struct ieee80211_sub_if_data *sdata = rx->sdata;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *hdr = (void *)skb->data;
-+
-+ rx->skb = skb;
-+ status->rx_flags |= IEEE80211_RX_RA_MATCH;
++ int err;
+
-+ if (!prepare_for_handlers(rx, hdr))
-+ return false;
++ switch (skb->protocol) {
++ case htons(ETH_P_IP):
++ err = skb_checksum_setup_ipv4(skb, recalculate);
++ break;
+
-+ if (!consume) {
-+ skb = skb_copy(skb, GFP_ATOMIC);
-+ if (!skb) {
-+ if (net_ratelimit())
-+ wiphy_debug(local->hw.wiphy,
-+ "failed to copy skb for %s\n",
-+ sdata->name);
-+ return true;
-+ }
++ case htons(ETH_P_IPV6):
++ err = skb_checksum_setup_ipv6(skb, recalculate);
++ break;
+
-+ rx->skb = skb;
++ default:
++ err = -EPROTO;
++ break;
+ }
+
-+ ieee80211_invoke_rx_handlers(rx);
-+ return true;
++ return err;
+}
++EXPORT_SYMBOL(skb_checksum_setup);
+
-+/*
-+ * This is the actual Rx frames handler. as it belongs to Rx path it must
-+ * be called with rcu_read_lock protection.
-+ */
-+static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
-+ struct sk_buff *skb)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_hdr *hdr;
-+ __le16 fc;
-+ struct ieee80211_rx_data rx;
-+ struct ieee80211_sub_if_data *prev;
-+ struct sta_info *sta, *tmp, *prev_sta;
-+ int err = 0;
-+
-+ fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
-+ memset(&rx, 0, sizeof(rx));
-+ rx.skb = skb;
-+ rx.local = local;
-+
-+ if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
-+ local->dot11ReceivedFragmentCount++;
++void __skb_warn_lro_forwarding(const struct sk_buff *skb)
++{
++ net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n",
++ skb->dev->name);
++}
++EXPORT_SYMBOL(__skb_warn_lro_forwarding);
+
-+ if (ieee80211_is_mgmt(fc)) {
-+ /* drop frame if too short for header */
-+ if (skb->len < ieee80211_hdrlen(fc))
-+ err = -ENOBUFS;
-+ else
-+ err = skb_linearize(skb);
++void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
++{
++ if (head_stolen) {
++ skb_release_head_state(skb);
++ kmem_cache_free(skbuff_head_cache, skb);
+ } else {
-+ err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
++ __kfree_skb(skb);
+ }
++}
++EXPORT_SYMBOL(kfree_skb_partial);
+
-+ if (err) {
-+ dev_kfree_skb(skb);
-+ return;
++/**
++ * skb_try_coalesce - try to merge skb to prior one
++ * @to: prior buffer
++ * @from: buffer to add
++ * @fragstolen: pointer to boolean
++ * @delta_truesize: how much more was allocated than was requested
++ */
++bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
++ bool *fragstolen, int *delta_truesize)
++{
++ int i, delta, len = from->len;
++
++ *fragstolen = false;
++
++ if (skb_cloned(to))
++ return false;
++
++ if (len <= skb_tailroom(to)) {
++ if (len)
++ BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len));
++ *delta_truesize = 0;
++ return true;
+ }
+
-+ hdr = (struct ieee80211_hdr *)skb->data;
-+ ieee80211_parse_qos(&rx);
-+ ieee80211_verify_alignment(&rx);
++ if (skb_has_frag_list(to) || skb_has_frag_list(from))
++ return false;
+
-+ if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
-+ ieee80211_is_beacon(hdr->frame_control)))
-+ ieee80211_scan_rx(local, skb);
++ if (skb_headlen(from) != 0) {
++ struct page *page;
++ unsigned int offset;
+
-+ if (ieee80211_is_data(fc)) {
-+ prev_sta = NULL;
++ if (skb_shinfo(to)->nr_frags +
++ skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
++ return false;
+
-+ for_each_sta_info(local, hdr->addr2, sta, tmp) {
-+ if (!prev_sta) {
-+ prev_sta = sta;
-+ continue;
-+ }
++ if (skb_head_is_locked(from))
++ return false;
+
-+ rx.sta = prev_sta;
-+ rx.sdata = prev_sta->sdata;
-+ ieee80211_prepare_and_rx_handle(&rx, skb, false);
++ delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));
+
-+ prev_sta = sta;
-+ }
++ page = virt_to_head_page(from->head);
++ offset = from->data - (unsigned char *)page_address(page);
+
-+ if (prev_sta) {
-+ rx.sta = prev_sta;
-+ rx.sdata = prev_sta->sdata;
++ skb_fill_page_desc(to, skb_shinfo(to)->nr_frags,
++ page, offset, skb_headlen(from));
++ *fragstolen = true;
++ } else {
++ if (skb_shinfo(to)->nr_frags +
++ skb_shinfo(from)->nr_frags > MAX_SKB_FRAGS)
++ return false;
+
-+ if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
-+ return;
-+ goto out;
-+ }
++ delta = from->truesize - SKB_TRUESIZE(skb_end_offset(from));
+ }
+
-+ prev = NULL;
++ WARN_ON_ONCE(delta < len);
+
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+ if (!ieee80211_sdata_running(sdata))
-+ continue;
++ memcpy(skb_shinfo(to)->frags + skb_shinfo(to)->nr_frags,
++ skb_shinfo(from)->frags,
++ skb_shinfo(from)->nr_frags * sizeof(skb_frag_t));
++ skb_shinfo(to)->nr_frags += skb_shinfo(from)->nr_frags;
+
-+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+ continue;
++ if (!skb_cloned(from))
++ skb_shinfo(from)->nr_frags = 0;
+
-+ /*
-+ * frame is destined for this interface, but if it's
-+ * not also for the previous one we handle that after
-+ * the loop to avoid copying the SKB once too much
-+ */
++ /* if the skb is not cloned this does nothing
++ * since we set nr_frags to 0.
++ */
++ for (i = 0; i < skb_shinfo(from)->nr_frags; i++)
++ skb_frag_ref(from, i);
+
-+ if (!prev) {
-+ prev = sdata;
-+ continue;
-+ }
++ to->truesize += delta;
++ to->len += len;
++ to->data_len += len;
+
-+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
-+ rx.sdata = prev;
-+ ieee80211_prepare_and_rx_handle(&rx, skb, false);
++ *delta_truesize = delta;
++ return true;
++}
++EXPORT_SYMBOL(skb_try_coalesce);
+
-+ prev = sdata;
-+ }
++/**
++ * skb_scrub_packet - scrub an skb
++ *
++ * @skb: buffer to clean
++ * @xnet: packet is crossing netns
++ *
++ * skb_scrub_packet can be used after encapsulating or decapsulting a packet
++ * into/from a tunnel. Some information have to be cleared during these
++ * operations.
++ * skb_scrub_packet can also be used to clean a skb before injecting it in
++ * another namespace (@xnet == true). We have to clear all information in the
++ * skb that could impact namespace isolation.
++ */
++void skb_scrub_packet(struct sk_buff *skb, bool xnet)
++{
++ skb->tstamp.tv64 = 0;
++ skb->pkt_type = PACKET_HOST;
++ skb->skb_iif = 0;
++ skb->ignore_df = 0;
++ skb_dst_drop(skb);
++ secpath_reset(skb);
++ nf_reset(skb);
++ nf_reset_trace(skb);
++
++ if (!xnet)
++ return;
+
-+ if (prev) {
-+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
-+ rx.sdata = prev;
++ skb_orphan(skb);
++ skb->mark = 0;
++}
++EXPORT_SYMBOL_GPL(skb_scrub_packet);
+
-+ if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
-+ return;
++/**
++ * skb_gso_transport_seglen - Return length of individual segments of a gso packet
++ *
++ * @skb: GSO skb
++ *
++ * skb_gso_transport_seglen is used to determine the real size of the
++ * individual segments, including Layer4 headers (TCP/UDP).
++ *
++ * The MAC/L2 or network (IP, IPv6) headers are not accounted for.
++ */
++unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
++{
++ const struct skb_shared_info *shinfo = skb_shinfo(skb);
++ unsigned int thlen = 0;
++
++ if (skb->encapsulation) {
++ thlen = skb_inner_transport_header(skb) -
++ skb_transport_header(skb);
++
++ if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
++ thlen += inner_tcp_hdrlen(skb);
++ } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
++ thlen = tcp_hdrlen(skb);
++ }
++ /* UFO sets gso_size to the size of the fragmentation
++ * payload, i.e. the size of the L4 (UDP) header is already
++ * accounted for.
++ */
++ return thlen + shinfo->gso_size;
++}
++EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
++
++static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
++{
++ if (skb_cow(skb, skb_headroom(skb)) < 0) {
++ kfree_skb(skb);
++ return NULL;
+ }
+
-+ out:
-+ dev_kfree_skb(skb);
++ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
++ skb->mac_header += VLAN_HLEN;
++ return skb;
+}
+
-+/*
-+ * This is the receive path handler. It is called by a low level driver when an
-+ * 802.11 MPDU is received from the hardware.
-+ */
-+void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
++struct sk_buff *skb_vlan_untag(struct sk_buff *skb)
+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_rate *rate = NULL;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
++ struct vlan_hdr *vhdr;
++ u16 vlan_tci;
+
-+ WARN_ON_ONCE(softirq_count() == 0);
++ if (unlikely(vlan_tx_tag_present(skb))) {
++ /* vlan_tci is already set-up so leave this for another time */
++ return skb;
++ }
+
-+ if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
-+ goto drop;
++ skb = skb_share_check(skb, GFP_ATOMIC);
++ if (unlikely(!skb))
++ goto err_free;
+
-+ sband = local->hw.wiphy->bands[status->band];
-+ if (WARN_ON(!sband))
-+ goto drop;
++ if (unlikely(!pskb_may_pull(skb, VLAN_HLEN)))
++ goto err_free;
+
-+ /*
-+ * If we're suspending, it is possible although not too likely
-+ * that we'd be receiving frames after having already partially
-+ * quiesced the stack. We can't process such frames then since
-+ * that might, for example, cause stations to be added or other
-+ * driver callbacks be invoked.
-+ */
-+ if (unlikely(local->quiescing || local->suspended))
-+ goto drop;
++ vhdr = (struct vlan_hdr *)skb->data;
++ vlan_tci = ntohs(vhdr->h_vlan_TCI);
++ __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci);
+
-+ /* We might be during a HW reconfig, prevent Rx for the same reason */
-+ if (unlikely(local->in_reconfig))
-+ goto drop;
++ skb_pull_rcsum(skb, VLAN_HLEN);
++ vlan_set_encap_proto(skb, vhdr);
+
-+ /*
-+ * The same happens when we're not even started,
-+ * but that's worth a warning.
-+ */
-+ if (WARN_ON(!local->started))
-+ goto drop;
++ skb = skb_reorder_vlan_header(skb);
++ if (unlikely(!skb))
++ goto err_free;
+
-+ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) {
-+ /*
-+ * Validate the rate, unless a PLCP error means that
-+ * we probably can't have a valid rate here anyway.
-+ */
++ skb_reset_network_header(skb);
++ skb_reset_transport_header(skb);
++ skb_reset_mac_len(skb);
+
-+ if (status->flag & RX_FLAG_HT) {
-+ /*
-+ * rate_idx is MCS index, which can be [0-76]
-+ * as documented on:
-+ *
-+ * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
-+ *
-+ * Anything else would be some sort of driver or
-+ * hardware error. The driver should catch hardware
-+ * errors.
-+ */
-+ if (WARN(status->rate_idx > 76,
-+ "Rate marked as an HT rate but passed "
-+ "status->rate_idx is not "
-+ "an MCS index [0-76]: %d (0x%02x)\n",
-+ status->rate_idx,
-+ status->rate_idx))
-+ goto drop;
-+ } else if (status->flag & RX_FLAG_VHT) {
-+ if (WARN_ONCE(status->rate_idx > 9 ||
-+ !status->vht_nss ||
-+ status->vht_nss > 8,
-+ "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
-+ status->rate_idx, status->vht_nss))
-+ goto drop;
-+ } else {
-+ if (WARN_ON(status->rate_idx >= sband->n_bitrates))
-+ goto drop;
-+ rate = &sband->bitrates[status->rate_idx];
-+ }
-+ }
++ return skb;
+
-+ status->rx_flags = 0;
++err_free:
++ kfree_skb(skb);
++ return NULL;
++}
++EXPORT_SYMBOL(skb_vlan_untag);
+
-+ /*
-+ * key references and virtual interfaces are protected using RCU
-+ * and this requires that we are in a read-side RCU section during
-+ * receive processing
-+ */
-+ rcu_read_lock();
++/**
++ * alloc_skb_with_frags - allocate skb with page frags
++ *
++ * @header_len: size of linear part
++ * @data_len: needed length in frags
++ * @max_page_order: max page order desired.
++ * @errcode: pointer to error code if any
++ * @gfp_mask: allocation mask
++ *
++ * This can be used to allocate a paged skb, given a maximal order for frags.
++ */
++struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
++ unsigned long data_len,
++ int max_page_order,
++ int *errcode,
++ gfp_t gfp_mask)
++{
++ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
++ unsigned long chunk;
++ struct sk_buff *skb;
++ struct page *page;
++ gfp_t gfp_head;
++ int i;
+
-+ /*
-+ * Frames with failed FCS/PLCP checksum are not returned,
-+ * all other frames are returned without radiotap header
-+ * if it was previously present.
-+ * Also, frames with less than 16 bytes are dropped.
++ *errcode = -EMSGSIZE;
++ /* Note this test could be relaxed, if we succeed to allocate
++ * high order pages...
+ */
-+ skb = ieee80211_rx_monitor(local, skb, rate);
-+ if (!skb) {
-+ rcu_read_unlock();
-+ return;
-+ }
++ if (npages > MAX_SKB_FRAGS)
++ return NULL;
+
-+ ieee80211_tpt_led_trig_rx(local,
-+ ((struct ieee80211_hdr *)skb->data)->frame_control,
-+ skb->len);
-+ __ieee80211_rx_handle_packet(hw, skb);
++ gfp_head = gfp_mask;
++ if (gfp_head & __GFP_WAIT)
++ gfp_head |= __GFP_REPEAT;
+
-+ rcu_read_unlock();
++ *errcode = -ENOBUFS;
++ skb = alloc_skb(header_len, gfp_head);
++ if (!skb)
++ return NULL;
+
-+ return;
-+ drop:
++ skb->truesize += npages << PAGE_SHIFT;
++
++ for (i = 0; npages > 0; i++) {
++ int order = max_page_order;
++
++ while (order) {
++ if (npages >= 1 << order) {
++ page = alloc_pages(gfp_mask |
++ __GFP_COMP |
++ __GFP_NOWARN |
++ __GFP_NORETRY,
++ order);
++ if (page)
++ goto fill_page;
++ /* Do not retry other high order allocations */
++ order = 1;
++ max_page_order = 0;
++ }
++ order--;
++ }
++ page = alloc_page(gfp_mask);
++ if (!page)
++ goto failure;
++fill_page:
++ chunk = min_t(unsigned long, data_len,
++ PAGE_SIZE << order);
++ skb_fill_page_desc(skb, i, page, 0, chunk);
++ data_len -= chunk;
++ npages -= 1 << order;
++ }
++ return skb;
++
++failure:
+ kfree_skb(skb);
++ return NULL;
+}
-+EXPORT_SYMBOL(ieee80211_rx);
++EXPORT_SYMBOL(alloc_skb_with_frags);
+diff -Nur linux-3.18.14.orig/net/core/sock.c linux-3.18.14-rt/net/core/sock.c
+--- linux-3.18.14.orig/net/core/sock.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/core/sock.c 2015-05-31 15:32:49.433635358 -0500
+@@ -2345,12 +2345,11 @@
+ if (sk->sk_lock.owned)
+ __lock_sock(sk);
+ sk->sk_lock.owned = 1;
+- spin_unlock(&sk->sk_lock.slock);
++ spin_unlock_bh(&sk->sk_lock.slock);
+ /*
+ * The sk_lock has mutex_lock() semantics here:
+ */
+ mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
+- local_bh_enable();
+ }
+ EXPORT_SYMBOL(lock_sock_nested);
+
+diff -Nur linux-3.18.14.orig/net/ipv4/icmp.c linux-3.18.14-rt/net/ipv4/icmp.c
+--- linux-3.18.14.orig/net/ipv4/icmp.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/ipv4/icmp.c 2015-05-31 15:32:49.457635357 -0500
+@@ -69,6 +69,7 @@
+ #include <linux/jiffies.h>
+ #include <linux/kernel.h>
+ #include <linux/fcntl.h>
++#include <linux/sysrq.h>
+ #include <linux/socket.h>
+ #include <linux/in.h>
+ #include <linux/inet.h>
+@@ -864,6 +865,30 @@
+ }
+
+ /*
++ * 32bit and 64bit have different timestamp length, so we check for
++ * the cookie at offset 20 and verify it is repeated at offset 50
++ */
++#define CO_POS0 20
++#define CO_POS1 50
++#define CO_SIZE sizeof(int)
++#define ICMP_SYSRQ_SIZE 57
+
-+/* This is a version of the rx handler that can be called from hard irq
-+ * context. Post the skb on the queue and schedule the tasklet */
-+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)
++/*
++ * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie
++ * pattern and if it matches send the next byte as a trigger to sysrq.
++ */
++static void icmp_check_sysrq(struct net *net, struct sk_buff *skb)
+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+
-+ BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
++ int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq);
++ char *p = skb->data;
+
-+ skb->pkt_type = IEEE80211_RX_MSG;
-+ skb_queue_tail(&local->skb_queue, skb);
-+ tasklet_schedule(&local->tasklet);
++ if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) &&
++ !memcmp(&cookie, p + CO_POS1, CO_SIZE) &&
++ p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE])
++ handle_sysrq(p[CO_POS0 + CO_SIZE]);
+}
-+EXPORT_SYMBOL(ieee80211_rx_irqsafe);
-diff -Nur linux-3.18.12.orig/net/netfilter/core.c linux-3.18.12/net/netfilter/core.c
---- linux-3.18.12.orig/net/netfilter/core.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/netfilter/core.c 2015-04-26 13:32:22.471684003 -0500
++
++/*
+ * Handle ICMP_ECHO ("ping") requests.
+ *
+ * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo
+@@ -890,6 +915,11 @@
+ icmp_param.data_len = skb->len;
+ icmp_param.head_len = sizeof(struct icmphdr);
+ icmp_reply(&icmp_param, skb);
++
++ if (skb->len == ICMP_SYSRQ_SIZE &&
++ net->ipv4.sysctl_icmp_echo_sysrq) {
++ icmp_check_sysrq(net, skb);
++ }
+ }
+ }
+
+diff -Nur linux-3.18.14.orig/net/ipv4/sysctl_net_ipv4.c linux-3.18.14-rt/net/ipv4/sysctl_net_ipv4.c
+--- linux-3.18.14.orig/net/ipv4/sysctl_net_ipv4.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/ipv4/sysctl_net_ipv4.c 2015-05-31 15:32:49.485635357 -0500
+@@ -779,6 +779,13 @@
+ .proc_handler = proc_dointvec
+ },
+ {
++ .procname = "icmp_echo_sysrq",
++ .data = &init_net.ipv4.sysctl_icmp_echo_sysrq,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec
++ },
++ {
+ .procname = "icmp_ignore_bogus_error_responses",
+ .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
+ .maxlen = sizeof(int),
+diff -Nur linux-3.18.14.orig/net/mac80211/rx.c linux-3.18.14-rt/net/mac80211/rx.c
+--- linux-3.18.14.orig/net/mac80211/rx.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/mac80211/rx.c 2015-05-31 15:32:49.501635357 -0500
+@@ -3360,7 +3360,7 @@
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+
+- WARN_ON_ONCE(softirq_count() == 0);
++ WARN_ON_ONCE_NONRT(softirq_count() == 0);
+
+ if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
+ goto drop;
+diff -Nur linux-3.18.14.orig/net/netfilter/core.c linux-3.18.14-rt/net/netfilter/core.c
+--- linux-3.18.14.orig/net/netfilter/core.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/netfilter/core.c 2015-05-31 15:32:49.549635357 -0500
@@ -21,11 +21,17 @@
#include <linux/proc_fs.h>
#include <linux/mutex.h>
@@ -36114,9 +36630,9 @@ diff -Nur linux-3.18.12.orig/net/netfilter/core.c linux-3.18.12/net/netfilter/co
static DEFINE_MUTEX(afinfo_mutex);
const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
-diff -Nur linux-3.18.12.orig/net/packet/af_packet.c linux-3.18.12/net/packet/af_packet.c
---- linux-3.18.12.orig/net/packet/af_packet.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/packet/af_packet.c 2015-04-26 13:32:22.471684003 -0500
+diff -Nur linux-3.18.14.orig/net/packet/af_packet.c linux-3.18.14-rt/net/packet/af_packet.c
+--- linux-3.18.14.orig/net/packet/af_packet.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/packet/af_packet.c 2015-05-31 15:32:49.557635357 -0500
@@ -63,6 +63,7 @@
#include <linux/if_packet.h>
#include <linux/wireless.h>
@@ -36143,9 +36659,9 @@ diff -Nur linux-3.18.12.orig/net/packet/af_packet.c linux-3.18.12/net/packet/af_
}
}
prb_close_block(pkc, pbd, po, status);
-diff -Nur linux-3.18.12.orig/net/rds/ib_rdma.c linux-3.18.12/net/rds/ib_rdma.c
---- linux-3.18.12.orig/net/rds/ib_rdma.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/rds/ib_rdma.c 2015-04-26 13:32:22.471684003 -0500
+diff -Nur linux-3.18.14.orig/net/rds/ib_rdma.c linux-3.18.14-rt/net/rds/ib_rdma.c
+--- linux-3.18.14.orig/net/rds/ib_rdma.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/rds/ib_rdma.c 2015-05-31 15:32:49.573635357 -0500
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/rculist.h>
@@ -36163,9 +36679,9 @@ diff -Nur linux-3.18.12.orig/net/rds/ib_rdma.c linux-3.18.12/net/rds/ib_rdma.c
}
}
-diff -Nur linux-3.18.12.orig/net/sched/sch_generic.c linux-3.18.12/net/sched/sch_generic.c
---- linux-3.18.12.orig/net/sched/sch_generic.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/sched/sch_generic.c 2015-04-26 13:32:22.471684003 -0500
+diff -Nur linux-3.18.14.orig/net/sched/sch_generic.c linux-3.18.14-rt/net/sched/sch_generic.c
+--- linux-3.18.14.orig/net/sched/sch_generic.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/sched/sch_generic.c 2015-05-31 15:32:49.593635356 -0500
@@ -894,7 +894,7 @@
/* Wait for outstanding qdisc_run calls. */
list_for_each_entry(dev, head, close_list)
@@ -36175,9 +36691,9 @@ diff -Nur linux-3.18.12.orig/net/sched/sch_generic.c linux-3.18.12/net/sched/sch
}
void dev_deactivate(struct net_device *dev)
-diff -Nur linux-3.18.12.orig/net/sunrpc/svc_xprt.c linux-3.18.12/net/sunrpc/svc_xprt.c
---- linux-3.18.12.orig/net/sunrpc/svc_xprt.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/net/sunrpc/svc_xprt.c 2015-04-26 13:32:22.475684003 -0500
+diff -Nur linux-3.18.14.orig/net/sunrpc/svc_xprt.c linux-3.18.14-rt/net/sunrpc/svc_xprt.c
+--- linux-3.18.14.orig/net/sunrpc/svc_xprt.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/net/sunrpc/svc_xprt.c 2015-05-31 15:32:49.617635356 -0500
@@ -357,7 +357,7 @@
return;
}
@@ -36196,9 +36712,9 @@ diff -Nur linux-3.18.12.orig/net/sunrpc/svc_xprt.c linux-3.18.12/net/sunrpc/svc_
}
/*
-diff -Nur linux-3.18.12.orig/scripts/mkcompile_h linux-3.18.12/scripts/mkcompile_h
---- linux-3.18.12.orig/scripts/mkcompile_h 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/scripts/mkcompile_h 2015-04-26 13:32:22.475684003 -0500
+diff -Nur linux-3.18.14.orig/scripts/mkcompile_h linux-3.18.14-rt/scripts/mkcompile_h
+--- linux-3.18.14.orig/scripts/mkcompile_h 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/scripts/mkcompile_h 2015-05-31 15:32:49.641635356 -0500
@@ -4,7 +4,8 @@
ARCH=$2
SMP=$3
@@ -36217,9 +36733,9 @@ diff -Nur linux-3.18.12.orig/scripts/mkcompile_h linux-3.18.12/scripts/mkcompile
UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
# Truncate to maximum length
-diff -Nur linux-3.18.12.orig/sound/core/pcm_native.c linux-3.18.12/sound/core/pcm_native.c
---- linux-3.18.12.orig/sound/core/pcm_native.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/sound/core/pcm_native.c 2015-04-26 13:32:22.475684003 -0500
+diff -Nur linux-3.18.14.orig/sound/core/pcm_native.c linux-3.18.14-rt/sound/core/pcm_native.c
+--- linux-3.18.14.orig/sound/core/pcm_native.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/sound/core/pcm_native.c 2015-05-31 15:32:49.661635356 -0500
@@ -104,7 +104,7 @@
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
@@ -36256,9 +36772,9 @@ diff -Nur linux-3.18.12.orig/sound/core/pcm_native.c linux-3.18.12/sound/core/pc
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
-diff -Nur linux-3.18.12.orig/virt/kvm/async_pf.c linux-3.18.12/virt/kvm/async_pf.c
---- linux-3.18.12.orig/virt/kvm/async_pf.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/virt/kvm/async_pf.c 2015-04-26 13:32:22.475684003 -0500
+diff -Nur linux-3.18.14.orig/virt/kvm/async_pf.c linux-3.18.14-rt/virt/kvm/async_pf.c
+--- linux-3.18.14.orig/virt/kvm/async_pf.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/virt/kvm/async_pf.c 2015-05-31 15:32:49.661635356 -0500
@@ -94,8 +94,8 @@
trace_kvm_async_pf_completed(addr, gva);
@@ -36270,9 +36786,9 @@ diff -Nur linux-3.18.12.orig/virt/kvm/async_pf.c linux-3.18.12/virt/kvm/async_pf
mmput(mm);
kvm_put_kvm(vcpu->kvm);
-diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main.c
---- linux-3.18.12.orig/virt/kvm/kvm_main.c 2015-04-20 14:48:02.000000000 -0500
-+++ linux-3.18.12/virt/kvm/kvm_main.c 2015-04-26 13:32:22.475684003 -0500
+diff -Nur linux-3.18.14.orig/virt/kvm/kvm_main.c linux-3.18.14-rt/virt/kvm/kvm_main.c
+--- linux-3.18.14.orig/virt/kvm/kvm_main.c 2015-05-20 10:04:50.000000000 -0500
++++ linux-3.18.14-rt/virt/kvm/kvm_main.c 2015-05-31 15:32:49.697635356 -0500
@@ -221,7 +221,7 @@
vcpu->kvm = kvm;
vcpu->vcpu_id = id;
@@ -36282,7 +36798,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main
kvm_async_pf_vcpu_init(vcpu);
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-@@ -1740,10 +1740,10 @@
+@@ -1741,10 +1741,10 @@
*/
void kvm_vcpu_block(struct kvm_vcpu *vcpu)
{
@@ -36295,7 +36811,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main
if (kvm_arch_vcpu_runnable(vcpu)) {
kvm_make_request(KVM_REQ_UNHALT, vcpu);
-@@ -1757,7 +1757,7 @@
+@@ -1758,7 +1758,7 @@
schedule();
}
@@ -36304,7 +36820,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main
}
EXPORT_SYMBOL_GPL(kvm_vcpu_block);
-@@ -1769,11 +1769,11 @@
+@@ -1770,11 +1770,11 @@
{
int me;
int cpu = vcpu->cpu;
@@ -36319,7 +36835,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main
++vcpu->stat.halt_wakeup;
}
-@@ -1878,7 +1878,7 @@
+@@ -1879,7 +1879,7 @@
continue;
if (vcpu == me)
continue;
diff --git a/target/linux/patches/3.18.12/regmap-bool.patch b/target/linux/patches/3.18.14/regmap-bool.patch
index 5c0ff5e2c..5c0ff5e2c 100644
--- a/target/linux/patches/3.18.12/regmap-bool.patch
+++ b/target/linux/patches/3.18.14/regmap-bool.patch
diff --git a/target/linux/patches/3.18.12/relocs.patch b/target/linux/patches/3.18.14/relocs.patch
index 69a7c88a9..69a7c88a9 100644
--- a/target/linux/patches/3.18.12/relocs.patch
+++ b/target/linux/patches/3.18.14/relocs.patch
diff --git a/target/linux/patches/3.18.12/sgidefs.patch b/target/linux/patches/3.18.14/sgidefs.patch
index f00a284d9..f00a284d9 100644
--- a/target/linux/patches/3.18.12/sgidefs.patch
+++ b/target/linux/patches/3.18.14/sgidefs.patch
diff --git a/target/linux/patches/3.18.12/sortext.patch b/target/linux/patches/3.18.14/sortext.patch
index 8fd4e1d6b..8fd4e1d6b 100644
--- a/target/linux/patches/3.18.12/sortext.patch
+++ b/target/linux/patches/3.18.14/sortext.patch
diff --git a/target/linux/patches/3.18.12/startup.patch b/target/linux/patches/3.18.14/startup.patch
index d396b75e4..d396b75e4 100644
--- a/target/linux/patches/3.18.12/startup.patch
+++ b/target/linux/patches/3.18.14/startup.patch
diff --git a/target/linux/patches/3.18.12/wlan-cf.patch b/target/linux/patches/3.18.14/wlan-cf.patch
index fc20759e2..fc20759e2 100644
--- a/target/linux/patches/3.18.12/wlan-cf.patch
+++ b/target/linux/patches/3.18.14/wlan-cf.patch
diff --git a/target/linux/patches/3.18.12/xargs.patch b/target/linux/patches/3.18.14/xargs.patch
index 2c7b3df59..2c7b3df59 100644
--- a/target/linux/patches/3.18.12/xargs.patch
+++ b/target/linux/patches/3.18.14/xargs.patch
diff --git a/target/linux/patches/3.18.12/yaffs2.patch b/target/linux/patches/3.18.14/yaffs2.patch
index bb244c7ca..bb244c7ca 100644
--- a/target/linux/patches/3.18.12/yaffs2.patch
+++ b/target/linux/patches/3.18.14/yaffs2.patch