diff --git a/compile.sh b/compile.sh
index a2eded7dd..9f25c0f72 100755
--- a/compile.sh
+++ b/compile.sh
@@ -93,8 +93,8 @@ if [[ ! -f $SRC/.ignore_changes ]]; then
fi
if [[ $BUILD_ALL == yes || $BUILD_ALL == demo ]]; then
- # shellcheck source=lib/build-all.sh
- source "${SRC}"/lib/build-all.sh
+ # shellcheck source=lib/build-all-ng.sh
+ source "${SRC}"/lib/build-all-ng.sh
else
# shellcheck source=lib/main.sh
source "${SRC}"/lib/main.sh
diff --git a/config/aptly-beta.conf b/config/aptly-beta.conf
new file mode 100644
index 000000000..5829e41ea
--- /dev/null
+++ b/config/aptly-beta.conf
@@ -0,0 +1,18 @@
+{
+ "rootDir": "output/repository-beta",
+ "downloadConcurrency": 4,
+ "downloadSpeedLimit": 0,
+ "architectures": [],
+ "dependencyFollowSuggests": false,
+ "dependencyFollowRecommends": false,
+ "dependencyFollowAllVariants": false,
+ "dependencyFollowSource": false,
+ "gpgDisableSign": false,
+ "gpgDisableVerify": false,
+ "gpgProvider": "gpg2",
+ "downloadSourcePackages": false,
+ "ppaDistributorID": "ubuntu",
+ "ppaCodename": "",
+ "S3PublishEndpoints": {},
+ "SwiftPublishEndpoints": {}
+}
diff --git a/config/aptly.conf b/config/aptly.conf
index 1dc74592f..b01f2e768 100644
--- a/config/aptly.conf
+++ b/config/aptly.conf
@@ -9,6 +9,7 @@
"dependencyFollowSource": false,
"gpgDisableSign": false,
"gpgDisableVerify": false,
+ "gpgProvider": "gpg2",
"downloadSourcePackages": false,
"ppaDistributorID": "ubuntu",
"ppaCodename": "",
diff --git a/config/boards/bananapi.conf b/config/boards/bananapi.conf
index 81e0f3834..504b31ade 100644
--- a/config/boards/bananapi.conf
+++ b/config/boards/bananapi.conf
@@ -6,8 +6,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp
MODULES_NEXT="brcmfmac bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default,next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/bananapim1plus.csc b/config/boards/bananapim1plus.csc
index 4a3b8c9aa..090224d2c 100644
--- a/config/boards/bananapim1plus.csc
+++ b/config/boards/bananapim1plus.csc
@@ -6,11 +6,7 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp
MODULES_NEXT="brcmfmac bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
#
#
diff --git a/config/boards/bananapim2.eos b/config/boards/bananapim2.eos
index 68cf5fa9b..51590529d 100644
--- a/config/boards/bananapim2.eos
+++ b/config/boards/bananapim2.eos
@@ -7,5 +7,3 @@ OVERLAY_PREFIX="sun6i-a31s"
MODULES_NEXT="brcmfmac bonding"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
diff --git a/config/boards/bananapim2plus.conf b/config/boards/bananapim2plus.conf
index c8c3f88f3..e36bad4a7 100644
--- a/config/boards/bananapim2plus.conf
+++ b/config/boards/bananapim2plus.conf
@@ -7,8 +7,4 @@ MODULES="#w1-sunxi #w1-gpio #w1-therm #sunxi-cir dhd hci_uart rfcomm hidp"
MODULES_NEXT="brcmfmac g_serial"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/bananapim2ultra.csc b/config/boards/bananapim2ultra.csc
index 77a44ab85..73df52d66 100644
--- a/config/boards/bananapim2ultra.csc
+++ b/config/boards/bananapim2ultra.csc
@@ -7,5 +7,3 @@ MODULES_NEXT=""
OVERLAY_PREFIX=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster:dev"
-DESKTOP_TARGET="bionic:dev"
diff --git a/config/boards/bananapim2zero.csc b/config/boards/bananapim2zero.csc
index 0897f0ab1..8e8e227c6 100644
--- a/config/boards/bananapim2zero.csc
+++ b/config/boards/bananapim2zero.csc
@@ -7,8 +7,4 @@ MODULES="#w1-sunxi #w1-gpio #w1-therm #sunxi-cir dhd hci_uart rfcomm hidp"
MODULES_NEXT="brcmfmac g_serial"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/bananapim3.csc b/config/boards/bananapim3.csc
index a5332962e..3a4c2a97f 100644
--- a/config/boards/bananapim3.csc
+++ b/config/boards/bananapim3.csc
@@ -8,7 +8,4 @@ MODULES_NEXT=""
OVERLAY_PREFIX="sun8i-a83t"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/bananapim64.conf b/config/boards/bananapim64.conf
index 27818e188..c62fe5af0 100644
--- a/config/boards/bananapim64.conf
+++ b/config/boards/bananapim64.conf
@@ -10,8 +10,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="bionic:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/bananapipro.eos b/config/boards/bananapipro.eos
index 70e977b24..778dd7fae 100644
--- a/config/boards/bananapipro.eos
+++ b/config/boards/bananapipro.eos
@@ -6,8 +6,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp
MODULES_NEXT="brcmfmac bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default,next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/bananapir2.csc b/config/boards/bananapir2.csc
index ce7dd3458..cb6b914ce 100644
--- a/config/boards/bananapir2.csc
+++ b/config/boards/bananapir2.csc
@@ -8,5 +8,3 @@ MODULES_NEXT="#"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default"
-CLI_TARGET="buster,bionic:default"
-CLI_BETA_TARGET=""
diff --git a/config/boards/beelinkx2.tvb b/config/boards/beelinkx2.tvb
index 73f91f769..e761d9f35 100644
--- a/config/boards/beelinkx2.tvb
+++ b/config/boards/beelinkx2.tvb
@@ -7,8 +7,4 @@ MODULES="sndspdif sunxi_sndspdif sunxi_spdif sunxi_spdma sunxi-cir"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/clearfogbase.conf b/config/boards/clearfogbase.conf
index 1689f24e2..3a7eafc82 100644
--- a/config/boards/clearfogbase.conf
+++ b/config/boards/clearfogbase.conf
@@ -8,6 +8,4 @@ MODULES_NEXT=""
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="stretch,buster,bionic:default,next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/clearfogpro.conf b/config/boards/clearfogpro.conf
index ca7f2f364..43f4947dc 100644
--- a/config/boards/clearfogpro.conf
+++ b/config/boards/clearfogpro.conf
@@ -7,6 +7,4 @@ MODULES_NEXT=""
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="stretch,buster,bionic:default,next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/cubieboard.eos b/config/boards/cubieboard.eos
index 148c9bb8c..1d943089b 100644
--- a/config/boards/cubieboard.eos
+++ b/config/boards/cubieboard.eos
@@ -7,5 +7,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sunxi"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,xenial:next"
-DESKTOP_TARGET="xenial:default,next"
diff --git a/config/boards/cubieboard2.eos b/config/boards/cubieboard2.eos
index 0b5314970..12da9528f 100644
--- a/config/boards/cubieboard2.eos
+++ b/config/boards/cubieboard2.eos
@@ -6,5 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,xenial:next"
-DESKTOP_TARGET="xenial:default,next"
diff --git a/config/boards/cubieboard4.csc b/config/boards/cubieboard4.csc
index a952e133a..7cee2c7ae 100644
--- a/config/boards/cubieboard4.csc
+++ b/config/boards/cubieboard4.csc
@@ -8,5 +8,3 @@ MODULES_NEXT=""
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
diff --git a/config/boards/cubietruck.conf b/config/boards/cubietruck.conf
index a98988d9f..c7e205142 100644
--- a/config/boards/cubietruck.conf
+++ b/config/boards/cubietruck.conf
@@ -6,7 +6,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i ap6210"
MODULES_NEXT="brcmfmac rfcomm hidp bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="bionic,buster:next"
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/cubietruckplus.csc b/config/boards/cubietruckplus.csc
index aab2688fc..20cc1619b 100644
--- a/config/boards/cubietruckplus.csc
+++ b/config/boards/cubietruckplus.csc
@@ -7,5 +7,3 @@ MODULES_NEXT=""
OVERLAY_PREFIX="sun8i-a83t"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
\ No newline at end of file
diff --git a/config/boards/espressobin.conf b/config/boards/espressobin.conf
index d217f028c..e455b87e9 100644
--- a/config/boards/espressobin.conf
+++ b/config/boards/espressobin.conf
@@ -7,6 +7,4 @@ MODULES_NEXT=""
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/firefly-rk3399.csc b/config/boards/firefly-rk3399.csc
index 4742015e4..ea081ba26 100644
--- a/config/boards/firefly-rk3399.csc
+++ b/config/boards/firefly-rk3399.csc
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/helios4.conf b/config/boards/helios4.conf
index 24b7bfce0..30957de8e 100644
--- a/config/boards/helios4.conf
+++ b/config/boards/helios4.conf
@@ -9,6 +9,4 @@ BUILD_DESKTOP="no"
FORCE_BOOTSCRIPT_UPDATE="yes"
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="stretch,buster,bionic:default,next"
-CLI_BETA_TARGET=""
diff --git a/config/boards/hummingbird.csc b/config/boards/hummingbird.csc
index 1f59356af..7fb9e1eca 100644
--- a/config/boards/hummingbird.csc
+++ b/config/boards/hummingbird.csc
@@ -6,11 +6,7 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i ap6210"
MODULES_NEXT="brcmfmac rfcomm hidp bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
#
BOARDRATING=""
CHIP="http://docs.armbian.com/Hardware_Allwinner-A20/"
diff --git a/config/boards/kvim1.csc b/config/boards/kvim1.csc
index f20d05751..1bce8700f 100644
--- a/config/boards/kvim1.csc
+++ b/config/boards/kvim1.csc
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="dev"
-CLI_TARGET="buster:dev"
-DESKTOP_TARGET="buster:dev"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/lamobo-r1.eos b/config/boards/lamobo-r1.eos
index 898c6907d..35e15f6c2 100644
--- a/config/boards/lamobo-r1.eos
+++ b/config/boards/lamobo-r1.eos
@@ -5,5 +5,3 @@ BOOTCONFIG="Lamobo_R1_defconfig"
MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,xenial:next,default"
-CLI_BETA_TARGET=""
diff --git a/config/boards/lepotato.conf b/config/boards/lepotato.conf
index 52ce3131e..d30c453cb 100644
--- a/config/boards/lepotato.conf
+++ b/config/boards/lepotato.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/lime-a10.eos b/config/boards/lime-a10.eos
index 0f69c7c67..67169e7a3 100644
--- a/config/boards/lime-a10.eos
+++ b/config/boards/lime-a10.eos
@@ -6,5 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="xenial:default,next"
diff --git a/config/boards/lime-a33.csc b/config/boards/lime-a33.csc
index 024055de5..b7c91fad5 100644
--- a/config/boards/lime-a33.csc
+++ b/config/boards/lime-a33.csc
@@ -7,7 +7,4 @@ MODULES_NEXT=""
OVERLAY_PREFIX="sun8i-a33"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/lime-a64.conf b/config/boards/lime-a64.conf
index b96e0cdec..5ecf3c9f2 100644
--- a/config/boards/lime-a64.conf
+++ b/config/boards/lime-a64.conf
@@ -10,8 +10,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="bionic:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/lime.eos b/config/boards/lime.eos
index 69e894335..5a115e1c1 100644
--- a/config/boards/lime.eos
+++ b/config/boards/lime.eos
@@ -7,7 +7,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/lime2.conf b/config/boards/lime2.conf
index ebbd564e3..8ec688c89 100644
--- a/config/boards/lime2.conf
+++ b/config/boards/lime2.conf
@@ -6,7 +6,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/macchiatobin-doubleshot.csc b/config/boards/macchiatobin-doubleshot.csc
index f6df36182..35f3558e5 100644
--- a/config/boards/macchiatobin-doubleshot.csc
+++ b/config/boards/macchiatobin-doubleshot.csc
@@ -7,6 +7,4 @@ MODULES_NEXT=""
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default"
-CLI_TARGET="buster,bionic:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/melea1000.csc b/config/boards/melea1000.csc
index 403855802..50ce87b73 100644
--- a/config/boards/melea1000.csc
+++ b/config/boards/melea1000.csc
@@ -7,7 +7,5 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sunxi"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="next"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
RECOMMENDED=""
diff --git a/config/boards/micro.eos b/config/boards/micro.eos
index e9317df61..518600b71 100644
--- a/config/boards/micro.eos
+++ b/config/boards/micro.eos
@@ -6,7 +6,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/miqi.eos b/config/boards/miqi.eos
index d40be2695..e90ee36c2 100644
--- a/config/boards/miqi.eos
+++ b/config/boards/miqi.eos
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:default,next"
-DESKTOP_TARGET="buster,bionic:default,next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/mk808c.csc b/config/boards/mk808c.csc
index a3fe2c138..1fee42925 100644
--- a/config/boards/mk808c.csc
+++ b/config/boards/mk808c.csc
@@ -6,5 +6,3 @@ MODULES="hci_uart rfcomm hidp sunxi-ir"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next"
-CLI_TARGET=""
-DESKTOP_TARGET=""
diff --git a/config/boards/nanopct3.conf b/config/boards/nanopct3.conf
index 382c913c2..316264617 100644
--- a/config/boards/nanopct3.conf
+++ b/config/boards/nanopct3.conf
@@ -8,7 +8,4 @@ CPUMIN="400000"
CPUMAX="1400000"
#
KERNEL_TARGET="next"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopct3plus.conf b/config/boards/nanopct3plus.conf
index 327662784..25de55ec2 100644
--- a/config/boards/nanopct3plus.conf
+++ b/config/boards/nanopct3plus.conf
@@ -8,7 +8,4 @@ CPUMIN="400000"
CPUMAX="1400000"
#
KERNEL_TARGET="next"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopct4.conf b/config/boards/nanopct4.conf
index c12882c5f..65577b0b5 100644
--- a/config/boards/nanopct4.conf
+++ b/config/boards/nanopct4.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/nanopi-r1.conf b/config/boards/nanopi-r1.conf
index ae45bd632..2c3ba8805 100644
--- a/config/boards/nanopi-r1.conf
+++ b/config/boards/nanopi-r1.conf
@@ -11,5 +11,3 @@ DEFAULT_CONSOLE="serial"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopiair.conf b/config/boards/nanopiair.conf
index a7251c868..5e363ff76 100644
--- a/config/boards/nanopiair.conf
+++ b/config/boards/nanopiair.conf
@@ -11,6 +11,4 @@ DEFAULT_CONSOLE="serial"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopiduo.conf b/config/boards/nanopiduo.conf
index 5b7db4ed5..c296b15d6 100644
--- a/config/boards/nanopiduo.conf
+++ b/config/boards/nanopiduo.conf
@@ -10,6 +10,4 @@ DEFAULT_CONSOLE="serial"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopiduo2.conf b/config/boards/nanopiduo2.conf
index 2000ae54d..605a3566e 100644
--- a/config/boards/nanopiduo2.conf
+++ b/config/boards/nanopiduo2.conf
@@ -10,6 +10,4 @@ DEFAULT_CONSOLE="serial"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopifire3.conf b/config/boards/nanopifire3.conf
index f5b3cef64..3fd0a8fb3 100644
--- a/config/boards/nanopifire3.conf
+++ b/config/boards/nanopifire3.conf
@@ -9,8 +9,5 @@ CPUMIN="400000"
CPUMAX="1400000"
#
KERNEL_TARGET="next"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopik1plus.conf b/config/boards/nanopik1plus.conf
index a55123bab..7015c820f 100644
--- a/config/boards/nanopik1plus.conf
+++ b/config/boards/nanopik1plus.conf
@@ -8,8 +8,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/nanopik2-s905.conf b/config/boards/nanopik2-s905.conf
index 372de847e..1fcfabca2 100644
--- a/config/boards/nanopik2-s905.conf
+++ b/config/boards/nanopik2-s905.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/nanopim1.eos b/config/boards/nanopim1.eos
index 330babac9..73b7844e6 100644
--- a/config/boards/nanopim1.eos
+++ b/config/boards/nanopim1.eos
@@ -7,8 +7,4 @@ MODULES="#w1-sunxi #w1-gpio #w1-therm #sunxi-cir"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/nanopim1plus.eos b/config/boards/nanopim1plus.eos
index c3f8a60d4..65a11222c 100644
--- a/config/boards/nanopim1plus.eos
+++ b/config/boards/nanopim1plus.eos
@@ -7,7 +7,4 @@ MODULES="#w1-sunxi #w1-gpio #w1-therm #sunxi-cir hci_uart rfcomm hidp dhd"
MODULES_NEXT="brcmfmac"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopim1plus2.eos b/config/boards/nanopim1plus2.eos
index 12db24fac..20fdb0665 100644
--- a/config/boards/nanopim1plus2.eos
+++ b/config/boards/nanopim1plus2.eos
@@ -8,8 +8,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET="bionic:dev"
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/nanopim3.eos b/config/boards/nanopim3.eos
index 408285f43..b6a475e51 100644
--- a/config/boards/nanopim3.eos
+++ b/config/boards/nanopim3.eos
@@ -9,7 +9,4 @@ CPUMIN="400000"
CPUMAX="1400000"
#
KERNEL_TARGET="next"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopim4.conf b/config/boards/nanopim4.conf
index cef400e70..64b552862 100644
--- a/config/boards/nanopim4.conf
+++ b/config/boards/nanopim4.conf
@@ -9,8 +9,4 @@ MODULES_NEXT=""
CPUMAX=1800000
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/nanopineo.conf b/config/boards/nanopineo.conf
index 6c52c8d9c..27c85847a 100644
--- a/config/boards/nanopineo.conf
+++ b/config/boards/nanopineo.conf
@@ -11,5 +11,3 @@ DEFAULT_CONSOLE="serial"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopineo2.conf b/config/boards/nanopineo2.conf
index a3ab93bda..2f62d0895 100644
--- a/config/boards/nanopineo2.conf
+++ b/config/boards/nanopineo2.conf
@@ -13,6 +13,4 @@ CPUMAX="816000"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopineo4.conf b/config/boards/nanopineo4.conf
index 0ee57fe66..52f826b3a 100644
--- a/config/boards/nanopineo4.conf
+++ b/config/boards/nanopineo4.conf
@@ -9,8 +9,4 @@ MODULES_NEXT=""
CPUMAX=1800000
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/nanopineocore2.conf b/config/boards/nanopineocore2.conf
index ecc2ad664..384419f3b 100644
--- a/config/boards/nanopineocore2.conf
+++ b/config/boards/nanopineocore2.conf
@@ -13,6 +13,4 @@ CPUMAX="1392000"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/nanopineoplus2.conf b/config/boards/nanopineoplus2.conf
index 099dbbe3d..7a5da135e 100644
--- a/config/boards/nanopineoplus2.conf
+++ b/config/boards/nanopineoplus2.conf
@@ -13,6 +13,4 @@ CPUMAX="816000"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/odroidc1.eos b/config/boards/odroidc1.eos
index 69c883a29..18f6c528e 100644
--- a/config/boards/odroidc1.eos
+++ b/config/boards/odroidc1.eos
@@ -7,8 +7,4 @@ MODULES="bonding"
MODULES_NEXT=""
#
KERNEL_TARGET="next"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/odroidc2.conf b/config/boards/odroidc2.conf
index 836512556..9674b4cc8 100644
--- a/config/boards/odroidc2.conf
+++ b/config/boards/odroidc2.conf
@@ -7,8 +7,4 @@ MODULES="bonding"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/odroidn2.csc b/config/boards/odroidn2.csc
index 49c1fa15e..8e88f05f1 100644
--- a/config/boards/odroidn2.csc
+++ b/config/boards/odroidn2.csc
@@ -3,16 +3,7 @@ BOARD_NAME="Odroid N2"
BOARDFAMILY="odroidn2"
BOOTCONFIG="odroidn2_config"
#
-MODULES="media_clock firmware"
-if [[ $BUILD_DESKTOP == 'yes' ]]; then
- MODULES+=" decoder_common stream_input amvdec_avs amvdec_h264 amvdec_h264_4k2k amvdec_mh264 amvdec_h264mvc amvdec_h265 amvdec_mjpeg amvdec_mmjpeg amvdec_mpeg12 amvdec_mpeg4 amvdec_mmpeg4 amvdec_real amvdec_vc1 amvdec_vp9"
-fi
-
+MODULES="media_clock firmware #decoder_common #stream_input #amvdec_mh264 #amvdec_h264 #amvdec_h264mvc #amvdec_h265 #amvdec_mmjpeg #amvdec_mpeg12 #amvdec_mmpeg4 #amvdec_mpeg4 #amvdec_vc1 #amvdec_vp9"
MODULES_NEXT=""
-#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/odroidxu4.conf b/config/boards/odroidxu4.conf
index 028cd2057..f3c39a96f 100644
--- a/config/boards/odroidxu4.conf
+++ b/config/boards/odroidxu4.conf
@@ -9,8 +9,4 @@ MODULES="bonding"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:default,next"
-DESKTOP_TARGET="buster,bionic:default,next"
-#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/olimex-som-a20.csc b/config/boards/olimex-som-a20.csc
index 89e193158..4711d634d 100644
--- a/config/boards/olimex-som-a20.csc
+++ b/config/boards/olimex-som-a20.csc
@@ -6,7 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp sun4i_cs
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,xenial:next"
-DESKTOP_TARGET="xenial:default,next"
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/olimex-som204-a20.csc b/config/boards/olimex-som204-a20.csc
index 833956602..f7ac0c04d 100644
--- a/config/boards/olimex-som204-a20.csc
+++ b/config/boards/olimex-som204-a20.csc
@@ -7,8 +7,4 @@ MODULES_NEXT="bonding g_serial gpio-ir-tx r8723bs"
MODULES_DEV="bonding g_serial gpio-ir-tx r8723bs "
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,xenial:next"
-DESKTOP_TARGET="xenial:default,next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/olinux-som-a13.csc b/config/boards/olinux-som-a13.csc
index ec122d55e..2082c2a50 100644
--- a/config/boards/olinux-som-a13.csc
+++ b/config/boards/olinux-som-a13.csc
@@ -6,5 +6,3 @@ MODULES="gpio_sunxi spi_sunxi"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
diff --git a/config/boards/olinuxino-a13.csc b/config/boards/olinuxino-a13.csc
index 419263ccd..c43dec567 100644
--- a/config/boards/olinuxino-a13.csc
+++ b/config/boards/olinuxino-a13.csc
@@ -7,5 +7,3 @@ MODULES="gpio_sunxi spi_sunxi 8021q 8192cu 8188eu sun4i_ts"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="xenial:next"
-DESKTOP_TARGET="xenial:next"
diff --git a/config/boards/orangepi-r1.conf b/config/boards/orangepi-r1.conf
index eb1e504d8..7558519a7 100644
--- a/config/boards/orangepi-r1.conf
+++ b/config/boards/orangepi-r1.conf
@@ -11,6 +11,4 @@ BUILD_DESKTOP="no"
DEFAULT_CONSOLE="serial"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepi-rk3399.wip b/config/boards/orangepi-rk3399.wip
index cd7a0d51a..386bfa335 100644
--- a/config/boards/orangepi-rk3399.wip
+++ b/config/boards/orangepi-rk3399.wip
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/orangepi.eos b/config/boards/orangepi.eos
index 9525d3e98..4c2ee7f18 100644
--- a/config/boards/orangepi.eos
+++ b/config/boards/orangepi.eos
@@ -6,5 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
diff --git a/config/boards/orangepi2.conf b/config/boards/orangepi2.conf
index 6dfde4836..acc61c769 100644
--- a/config/boards/orangepi2.conf
+++ b/config/boards/orangepi2.conf
@@ -9,7 +9,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepi3.wip b/config/boards/orangepi3.wip
index c20b40c75..377bc5c0b 100644
--- a/config/boards/orangepi3.wip
+++ b/config/boards/orangepi3.wip
@@ -7,9 +7,5 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/orangepilite.conf b/config/boards/orangepilite.conf
index aa4d5c7da..b527aacf3 100644
--- a/config/boards/orangepilite.conf
+++ b/config/boards/orangepilite.conf
@@ -9,7 +9,4 @@ CPUMIN="408000"
CPUMAX="1200000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepilite2.wip b/config/boards/orangepilite2.wip
index 0887d1e75..3d276b685 100644
--- a/config/boards/orangepilite2.wip
+++ b/config/boards/orangepilite2.wip
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/orangepimini.eos b/config/boards/orangepimini.eos
index b6ecf63ef..53deabfd2 100644
--- a/config/boards/orangepimini.eos
+++ b/config/boards/orangepimini.eos
@@ -6,8 +6,6 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp
MODULES_NEXT="bonding"
#
KERNEL_TARGET=""
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
BOARDRATING=""
CHIP="http://docs.armbian.com/Hardware_Allwinner-A20/"
diff --git a/config/boards/orangepione.conf b/config/boards/orangepione.conf
index 2a8dcbedd..a025cff5f 100644
--- a/config/boards/orangepione.conf
+++ b/config/boards/orangepione.conf
@@ -9,7 +9,4 @@ CPUMIN="408000"
CPUMAX="1200000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepioneplus.wip b/config/boards/orangepioneplus.wip
index 35fccc673..f57172c09 100644
--- a/config/boards/orangepioneplus.wip
+++ b/config/boards/orangepioneplus.wip
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/orangepipc.conf b/config/boards/orangepipc.conf
index f5ac509f9..6b04fb2d7 100644
--- a/config/boards/orangepipc.conf
+++ b/config/boards/orangepipc.conf
@@ -9,7 +9,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepipc2.conf b/config/boards/orangepipc2.conf
index ec15da506..2ec61228a 100644
--- a/config/boards/orangepipc2.conf
+++ b/config/boards/orangepipc2.conf
@@ -6,7 +6,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepipcplus.conf b/config/boards/orangepipcplus.conf
index b5f12d207..87c2d4629 100644
--- a/config/boards/orangepipcplus.conf
+++ b/config/boards/orangepipcplus.conf
@@ -8,7 +8,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepiplus.conf b/config/boards/orangepiplus.conf
index 66c11e7bc..bdd115e3f 100644
--- a/config/boards/orangepiplus.conf
+++ b/config/boards/orangepiplus.conf
@@ -9,7 +9,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepiplus2e.conf b/config/boards/orangepiplus2e.conf
index b9d12d310..50a9d4d6e 100644
--- a/config/boards/orangepiplus2e.conf
+++ b/config/boards/orangepiplus2e.conf
@@ -9,7 +9,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepiprime.conf b/config/boards/orangepiprime.conf
index 5404f73f9..0a03bf85f 100644
--- a/config/boards/orangepiprime.conf
+++ b/config/boards/orangepiprime.conf
@@ -6,8 +6,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/orangepiwin.conf b/config/boards/orangepiwin.conf
index cbdca7dcd..83b111979 100644
--- a/config/boards/orangepiwin.conf
+++ b/config/boards/orangepiwin.conf
@@ -10,8 +10,4 @@ CPUMIN="408000"
CPUMAX="1296000"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="bionic:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/orangepizero.conf b/config/boards/orangepizero.conf
index c702d85f9..244ac4722 100644
--- a/config/boards/orangepizero.conf
+++ b/config/boards/orangepizero.conf
@@ -11,7 +11,4 @@ DEFAULT_CONSOLE="serial"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepizeroplus.conf b/config/boards/orangepizeroplus.conf
index a73c93022..4e8bc9429 100644
--- a/config/boards/orangepizeroplus.conf
+++ b/config/boards/orangepizeroplus.conf
@@ -10,6 +10,4 @@ DEFAULT_OVERLAYS="usbhost2 usbhost3"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepizeroplus2-h3.conf b/config/boards/orangepizeroplus2-h3.conf
index 6bc95c194..8dd6d14d2 100644
--- a/config/boards/orangepizeroplus2-h3.conf
+++ b/config/boards/orangepizeroplus2-h3.conf
@@ -9,7 +9,4 @@ MODULES_BLACKLIST=""
DEFAULT_OVERLAYS="usbhost2 usbhost3"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/orangepizeroplus2-h5.conf b/config/boards/orangepizeroplus2-h5.conf
index ec0896406..47727fe31 100644
--- a/config/boards/orangepizeroplus2-h5.conf
+++ b/config/boards/orangepizeroplus2-h5.conf
@@ -10,6 +10,4 @@ DEFAULT_OVERLAYS="usbhost2 usbhost3"
BUILD_DESKTOP="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
diff --git a/config/boards/pcduino2.eos b/config/boards/pcduino2.eos
index 78ace4590..633b74fb2 100644
--- a/config/boards/pcduino2.eos
+++ b/config/boards/pcduino2.eos
@@ -6,5 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sunxi"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="xenial:default,next"
diff --git a/config/boards/pcduino3.csc b/config/boards/pcduino3.csc
index 2fa6b7ba3..19e89eb92 100644
--- a/config/boards/pcduino3.csc
+++ b/config/boards/pcduino3.csc
@@ -6,8 +6,4 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="next"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/pcduino3nano.eos b/config/boards/pcduino3nano.eos
index bcf109603..5e857cc45 100644
--- a/config/boards/pcduino3nano.eos
+++ b/config/boards/pcduino3nano.eos
@@ -6,5 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i"
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="xenial:default,next"
diff --git a/config/boards/pine64.conf b/config/boards/pine64.conf
index 4b66fba03..04785553f 100644
--- a/config/boards/pine64.conf
+++ b/config/boards/pine64.conf
@@ -8,8 +8,4 @@ MODULES="sunxi_codec sunxi_i2s sunxi_sndcodec 8723bs"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="bionic,buster:next"
-DESKTOP_TARGET="xenial:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/pine64so.conf b/config/boards/pine64so.conf
index d11369063..8040140f3 100644
--- a/config/boards/pine64so.conf
+++ b/config/boards/pine64so.conf
@@ -8,8 +8,4 @@ MODULES="sunxi_codec sunxi_i2s sunxi_sndcodec 8723bs"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="bionic,buster:next"
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/pinebook-a64.conf b/config/boards/pinebook-a64.conf
index bb1eb7cce..29d0307dd 100644
--- a/config/boards/pinebook-a64.conf
+++ b/config/boards/pinebook-a64.conf
@@ -11,8 +11,4 @@ MODULES_NEXT=""
DESKTOP_AUTOLOGIN="no"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:next,dev"
-DESKTOP_TARGET="bionic:next,dev"
-#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/pineh64.wip b/config/boards/pineh64.wip
index 2f255bdfd..b7b102e0f 100644
--- a/config/boards/pineh64.wip
+++ b/config/boards/pineh64.wip
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="next,dev"
-CLI_TARGET=""
-DESKTOP_TARGET=""
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/renegade.conf b/config/boards/renegade.conf
index 8a2fd0228..57abb6ad3 100644
--- a/config/boards/renegade.conf
+++ b/config/boards/renegade.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/rock64.conf b/config/boards/rock64.conf
index bb7f5f4d4..cd5149b2c 100644
--- a/config/boards/rock64.conf
+++ b/config/boards/rock64.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/rockpi-4a.conf b/config/boards/rockpi-4a.conf
new file mode 100644
index 000000000..8a98db8d9
--- /dev/null
+++ b/config/boards/rockpi-4a.conf
@@ -0,0 +1,10 @@
+# RK3399 hexa core 1-4GB SoC GBe eMMC USB3
+BOARD_NAME="RockPi-4A"
+BOARDFAMILY="rockchip64"
+BOOTCONFIG="rockpi4b-rk3399_defconfig"
+#
+MODULES=""
+MODULES_NEXT=""
+#
+KERNEL_TARGET="default,dev"
+FULL_DESKTOP="yes"
diff --git a/config/boards/rockpi-4b.conf b/config/boards/rockpi-4b.conf
index 7433c0176..c908e8e55 100644
--- a/config/boards/rockpi-4b.conf
+++ b/config/boards/rockpi-4b.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/rockpro64.conf b/config/boards/rockpro64.conf
index 0b58efaa5..60bc1bf3f 100644
--- a/config/boards/rockpro64.conf
+++ b/config/boards/rockpro64.conf
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default,dev"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
-
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/sunvell-r69.csc b/config/boards/sunvell-r69.csc
index 66ebda0ff..959d0c2a2 100644
--- a/config/boards/sunvell-r69.csc
+++ b/config/boards/sunvell-r69.csc
@@ -9,8 +9,4 @@ MODULES_BLACKLIST="dhd"
DEFAULT_OVERLAYS="cir analog-codec"
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,xenial:next"
-DESKTOP_TARGET="buster:next"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/teres-a64.conf b/config/boards/teres-a64.conf
index 8bfca34e7..5aefd289c 100644
--- a/config/boards/teres-a64.conf
+++ b/config/boards/teres-a64.conf
@@ -8,8 +8,4 @@ MODULES_NEXT=""
DESKTOP_AUTOLOGIN="no"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="bionic:next"
-#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/tinkerboard.conf b/config/boards/tinkerboard.conf
index ede7c8a2d..1030e6e71 100644
--- a/config/boards/tinkerboard.conf
+++ b/config/boards/tinkerboard.conf
@@ -7,8 +7,4 @@ MODULES="hci_uart rfcomm hidp 8723bs"
MODULES_NEXT=""
DEFAULT_OVERLAYS="i2c1 i2c4 spi2 spidev2 uart1 uart2"
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster,bionic:default,next"
-DESKTOP_TARGET="buster,bionic:default,next"
-#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
+FULL_DESKTOP="yes"
diff --git a/config/boards/topwise-a721.csc b/config/boards/topwise-a721.csc
index 759f59248..7a32f185f 100644
--- a/config/boards/topwise-a721.csc
+++ b/config/boards/topwise-a721.csc
@@ -6,5 +6,3 @@ MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sunxi zet6221 ssd2
MODULES_NEXT="bonding"
#
KERNEL_TARGET="default"
-CLI_TARGET="buster:next"
-DESKTOP_TARGET="xenial:default"
diff --git a/config/boards/tritium-h3.conf b/config/boards/tritium-h3.conf
index dc0361682..f976179f4 100644
--- a/config/boards/tritium-h3.conf
+++ b/config/boards/tritium-h3.conf
@@ -8,5 +8,3 @@ MODULES_NEXT="g_serial"
DEFAULT_OVERLAYS="usbhost1 usbhost2 analog-codec"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
diff --git a/config/boards/tritium-h5.conf b/config/boards/tritium-h5.conf
index 51f4d1db8..45d33691c 100644
--- a/config/boards/tritium-h5.conf
+++ b/config/boards/tritium-h5.conf
@@ -8,9 +8,5 @@ MODULES_NEXT=""
DEFAULT_OVERLAYS="analog-codec"
#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET="buster,bionic:next"
#
-CLI_BETA_TARGET=""
#
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/udoo.eos b/config/boards/udoo.eos
index 9a4522f71..f1a2b0c0b 100644
--- a/config/boards/udoo.eos
+++ b/config/boards/udoo.eos
@@ -4,7 +4,4 @@ BOARDFAMILY="udoo"
BOOTCONFIG="udoo_defconfig"
MODULES=""
MODULES_NEXT=""
-#
KERNEL_TARGET="next,dev"
-CLI_TARGET="buster,bionic:next"
-DESKTOP_TARGET=""
diff --git a/config/boards/xt-q8l-v10.tvb b/config/boards/xt-q8l-v10.tvb
index a010cf16c..700679043 100644
--- a/config/boards/xt-q8l-v10.tvb
+++ b/config/boards/xt-q8l-v10.tvb
@@ -7,8 +7,4 @@ MODULES="hci_uart rfcomm hidp"
MODULES_NEXT=""
#
KERNEL_TARGET="default,next,dev"
-CLI_TARGET="buster:default,next"
-DESKTOP_TARGET="bionic:default,next"
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/boards/z28pro.tvb b/config/boards/z28pro.tvb
index b07d29ba7..13c65b2ef 100644
--- a/config/boards/z28pro.tvb
+++ b/config/boards/z28pro.tvb
@@ -7,8 +7,4 @@ MODULES=""
MODULES_NEXT=""
#
KERNEL_TARGET="default"
-CLI_TARGET="buster,bionic:default"
-DESKTOP_TARGET="buster,bionic:default"
#
-CLI_BETA_TARGET=""
-DESKTOP_BETA_TARGET=""
diff --git a/config/kernel/linux-cubox-default.config b/config/kernel/linux-cubox-default.config
index 5ff275e50..9dfcf8603 100644
--- a/config/kernel/linux-cubox-default.config
+++ b/config/kernel/linux-cubox-default.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm 4.9.166 Kernel Configuration
+# Linux/arm 4.9.179 Kernel Configuration
#
CONFIG_ARM=y
CONFIG_ARM_HAS_SG_CHAIN=y
@@ -3045,6 +3045,7 @@ CONFIG_NOZOMI=m
CONFIG_N_HDLC=m
CONFIG_N_GSM=m
# CONFIG_TRACE_SINK is not set
+CONFIG_LDISC_AUTOLOAD=y
CONFIG_DEVMEM=y
# CONFIG_DEVKMEM is not set
@@ -3126,7 +3127,6 @@ CONFIG_HW_RANDOM_TIMERIOMEM=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_HW_RANDOM_TPM=m
# CONFIG_NVRAM is not set
-CONFIG_R3964=m
# CONFIG_APPLICOM is not set
#
diff --git a/config/kernel/linux-rk3399-default.config b/config/kernel/linux-rk3399-default.config
index d9a9c6f30..1b604f414 100644
--- a/config/kernel/linux-rk3399-default.config
+++ b/config/kernel/linux-rk3399-default.config
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 4.4.188 Kernel Configuration
+# Linux/arm64 4.4.190 Kernel Configuration
#
CONFIG_ARM64=y
CONFIG_64BIT=y
@@ -166,6 +166,7 @@ CONFIG_RD_LZMA=y
CONFIG_RD_XZ=y
CONFIG_RD_LZO=y
CONFIG_RD_LZ4=y
+# CONFIG_INITRD_ASYNC is not set
# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
@@ -492,7 +493,6 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_PAN=y
# CONFIG_ARM64_LSE_ATOMICS is not set
-CONFIG_KEYS_COMPAT=y
CONFIG_ARM64_UAO=y
CONFIG_ARM64_MODULE_CMODEL_LARGE=y
# CONFIG_RANDOMIZE_BASE is not set
@@ -516,6 +516,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_COREDUMP=y
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
+CONFIG_KEYS_COMPAT=y
#
# Power management options
@@ -1906,8 +1907,6 @@ CONFIG_DM_DELAY=m
# CONFIG_DM_UEVENT is not set
CONFIG_DM_FLAKEY=m
CONFIG_DM_VERITY=m
-# CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE_128 is not set
-CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1
# CONFIG_DM_VERITY_FEC is not set
CONFIG_DM_SWITCH=m
CONFIG_DM_LOG_WRITES=m
@@ -1965,10 +1964,6 @@ CONFIG_ATM_DRIVERS=y
#
# CAIF transport drivers
#
-CONFIG_VHOST_NET=m
-CONFIG_VHOST_RING=m
-CONFIG_VHOST=m
-# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
#
# Distributed Switch Architecture drivers
@@ -3725,20 +3720,27 @@ CONFIG_VIDEO_CX25840=m
# Camera sensor devices
#
# CONFIG_VIDEO_IMX219 is not set
+# CONFIG_VIDEO_IMX258 is not set
+# CONFIG_VIDEO_IMX317 is not set
# CONFIG_VIDEO_IMX323 is not set
+# CONFIG_VIDEO_IMX327 is not set
# CONFIG_VIDEO_VIRT_CAMERA is not set
# CONFIG_VIDEO_OV2659 is not set
+# CONFIG_VIDEO_OV2680 is not set
# CONFIG_VIDEO_OV2685 is not set
# CONFIG_VIDEO_OV2718 is not set
# CONFIG_VIDEO_OV2735 is not set
CONFIG_VIDEO_OV4689=y
# CONFIG_VIDEO_OV5647 is not set
+# CONFIG_VIDEO_OV5648 is not set
# CONFIG_VIDEO_OV5695 is not set
# CONFIG_VIDEO_OV7251 is not set
# CONFIG_VIDEO_OV7640 is not set
# CONFIG_VIDEO_OV7670 is not set
# CONFIG_VIDEO_OV7725 is not set
CONFIG_VIDEO_OV7750=y
+CONFIG_VIDEO_OV8858=y
+# CONFIG_VIDEO_OV9281 is not set
# CONFIG_VIDEO_OV9650 is not set
CONFIG_VIDEO_OV13850=y
# CONFIG_VIDEO_VS6624 is not set
@@ -3760,9 +3762,15 @@ CONFIG_VIDEO_OV13850=y
# CONFIG_VIDEO_GC0312 is not set
# CONFIG_VIDEO_GC2145 is not set
CONFIG_VIDEO_GC2355=y
+# CONFIG_VIDEO_GC2385 is not set
+# CONFIG_VIDEO_GC5025 is not set
+# CONFIG_VIDEO_GC8034 is not set
CONFIG_VIDEO_SC031GS=y
CONFIG_VIDEO_GC0329=m
CONFIG_VIDEO_GC2035=m
+# CONFIG_VIDEO_BF3925 is not set
+# CONFIG_VIDEO_JX_H65 is not set
+# CONFIG_VIDEO_PREISP_DUMMY_SENSOR is not set
#
# Flash devices
@@ -3771,6 +3779,7 @@ CONFIG_VIDEO_GC2035=m
# CONFIG_VIDEO_AS3645A is not set
# CONFIG_VIDEO_LM3560 is not set
# CONFIG_VIDEO_LM3646 is not set
+# CONFIG_VIDEO_SGM3784 is not set
#
# Video improvement chips
@@ -3782,6 +3791,8 @@ CONFIG_VIDEO_GC2035=m
# Camera lens devices
#
CONFIG_VIDEO_VM149C=m
+# CONFIG_VIDEO_DW9714 is not set
+# CONFIG_VIDEO_FP5510 is not set
#
# Audio/Video compression chips
@@ -3793,6 +3804,7 @@ CONFIG_VIDEO_VM149C=m
#
# CONFIG_VIDEO_THS7303 is not set
# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_NVP6324 is not set
#
# Sensors used on soc_camera driver
@@ -3815,16 +3827,15 @@ CONFIG_SOC_CAMERA_OV9640=y
CONFIG_SOC_CAMERA_OV9740=y
CONFIG_SOC_CAMERA_RJ54N1=y
CONFIG_SOC_CAMERA_TW9910=y
-CONFIG_VIDEO_OV8858=y
CONFIG_VIDEO_OV2710=y
CONFIG_VIDEO_TC358749XBG=y
CONFIG_VIDEO_ADV7181=y
CONFIG_VIDEO_OV7675=y
CONFIG_VIDEO_NT99230=y
-# CONFIG_VIDEO_OV9281 is not set
CONFIG_VIDEO_OV9750=y
# CONFIG_VIDEO_ov5640 is not set
# CONFIG_VIDEO_SC2232 is not set
+# CONFIG_VIDEO_ISL79987 is not set
#
# SPI helper chips
@@ -4039,6 +4050,7 @@ CONFIG_DRM_KMS_HELPER=y
CONFIG_DRM_KMS_FB_HELPER=y
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+# CONFIG_DRM_DP_CEC is not set
# CONFIG_DRM_SCDC_HELPER is not set
CONFIG_DRM_DMA_SYNC=y
@@ -4927,6 +4939,7 @@ CONFIG_USB_CONFIGFS_F_FS=y
# CONFIG_USB_CONFIGFS_F_ACC is not set
CONFIG_USB_CONFIGFS_UEVENT=y
# CONFIG_USB_CONFIGFS_F_UAC1 is not set
+# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
# CONFIG_USB_CONFIGFS_F_UAC2 is not set
# CONFIG_USB_CONFIGFS_F_MIDI is not set
# CONFIG_USB_CONFIGFS_F_HID is not set
@@ -5465,7 +5478,7 @@ CONFIG_ROCKCHIP_IOMMU=y
#
#
-# CPU selection
+# Rockchip CPU selection
#
CONFIG_CPU_PX30=y
# CONFIG_CPU_RK1808 is not set
@@ -5483,6 +5496,8 @@ CONFIG_ROCKCHIP_OPP=y
CONFIG_ROCKCHIP_GRF=y
CONFIG_ROCKCHIP_PM_DOMAINS=y
# CONFIG_ROCKCHIP_PVTM is not set
+CONFIG_ROCKCHIP_SYSTEM_MONITOR=y
+# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
CONFIG_MACH_NANOPI4=y
@@ -6122,6 +6137,10 @@ CONFIG_VIRTUALIZATION=y
CONFIG_KVM_ARM_VGIC_V3=y
CONFIG_KVM=y
CONFIG_KVM_ARM_HOST=y
+CONFIG_VHOST_NET=m
+# CONFIG_VHOST_VSOCK is not set
+CONFIG_VHOST=m
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
#
# Kernel hacking
@@ -6494,7 +6513,8 @@ CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_CCP is not set
-CONFIG_CRYPTO_DEV_ROCKCHIP=m
+# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set
+# CONFIG_CRYPTO_DEV_ROCKCHIP_V2 is not set
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_PUBLIC_KEY_ALGO_RSA=y
diff --git a/config/sources/cubox.conf b/config/sources/cubox.conf
index 4f816aec6..bdd220839 100644
--- a/config/sources/cubox.conf
+++ b/config/sources/cubox.conf
@@ -18,7 +18,7 @@ KERNELDIR=$MAINLINE_KERNEL_DIR
case $BRANCH in
default)
-
+
KERNELSOURCE='https://github.com/SolidRun/linux-stable'
KERNELBRANCH='branch:linux-4.9.y-imx6'
KERNELDIR='linux-imx6'
diff --git a/config/sources/rk3399.conf b/config/sources/rk3399.conf
index cc404c576..55ce7a8db 100644
--- a/config/sources/rk3399.conf
+++ b/config/sources/rk3399.conf
@@ -92,7 +92,7 @@ family_tweaks()
[[ $BOARD == orangepi-rk3399 ]] && echo "fdtfile=rockchip/rk3399-orangepi.dtb" >> $SDCARD/boot/armbianEnv.txt
[[ $BOARD == firefly-rk3399 ]] && echo "fdtfile=rockchip/rk3399-firefly.dtb" >> $SDCARD/boot/armbianEnv.txt
# install and enable Bluetooth
- chroot $SDCARD /bin/bash -c "apt-get -y -qq install bluetooth bluez bluez-tools"
+ chroot $SDCARD /bin/bash -c "apt-get -y -qq install rfkill bluetooth bluez bluez-tools"
chroot $SDCARD /bin/bash -c "systemctl --no-reload enable rk3399-bluetooth.service >/dev/null 2>&1"
}
diff --git a/config/sources/rockchip.conf b/config/sources/rockchip.conf
index 4ff6d8f33..d5916c11a 100644
--- a/config/sources/rockchip.conf
+++ b/config/sources/rockchip.conf
@@ -79,7 +79,7 @@ uboot_custom_postprocess()
family_tweaks()
{
if [[ $BOARD == tinkerboard ]]; then
- chroot $SDCARD /bin/bash -c "apt-get -y -qq install bluetooth bluez bluez-tools"
+ chroot $SDCARD /bin/bash -c "apt-get -y -qq install rfkill bluetooth bluez bluez-tools"
chroot $SDCARD /bin/bash -c "systemctl --no-reload enable tinker-bluetooth.service >/dev/null 2>&1"
sed -i -e "/#load-module module-alsa-sink/r $SRC/packages/bsp/rockchip/pulseaudio.txt" $SDCARD/etc/pulse/default.pa >/dev/null 2>&1
fi
diff --git a/config/sources/rockchip64.conf b/config/sources/rockchip64.conf
index 432f1cd8c..7a209d2bb 100644
--- a/config/sources/rockchip64.conf
+++ b/config/sources/rockchip64.conf
@@ -125,7 +125,7 @@ family_tweaks()
fi
if [[ $BOARD == rockpi-4b ]]; then
- chroot $SDCARD /bin/bash -c "apt-get -y -qq install bluetooth bluez bluez-tools"
+ chroot $SDCARD /bin/bash -c "apt-get -y -qq install rfkill bluetooth bluez bluez-tools"
chroot $SDCARD /bin/bash -c "systemctl --no-reload enable rk3399-bluetooth.service >/dev/null 2>&1"
fi
}
diff --git a/config/sources/sun7i.conf b/config/sources/sun7i.conf
index 446af16b1..0d95eebf8 100644
--- a/config/sources/sun7i.conf
+++ b/config/sources/sun7i.conf
@@ -33,6 +33,7 @@ family_tweaks_s()
if [[ $BRANCH != default ]]; then
# Enable bluetooth
+ chroot $SDCARD /bin/bash -c "apt-get -y -qq install rfkill bluetooth bluez bluez-tools"
chroot $SDCARD /bin/bash -c "systemctl --no-reload enable olinuxino-bluetooth.service >/dev/null 2>&1"
else
# Install touchscreen calibrator
diff --git a/config/targets.conf b/config/targets.conf
new file mode 100644
index 000000000..5e0b2103c
--- /dev/null
+++ b/config/targets.conf
@@ -0,0 +1,488 @@
+# targets are delimited with :
+# boardname, release, (m)minimal|(c)li|(d)esktop, (d)efault|(n)ext|(d)ev, (s)table|(b)eta, images:yes|no
+#
+# minimal not supported yet
+#
+
+# Bananapi A20
+
+bananapi next buster desktop stable yes
+bananapi next buster cli stable yes
+bananapi next bionic cli stable yes
+bananapi next stretch cli stable yes
+bananapi dev buster minimal beta yes
+
+# Bananapi M2+ H3
+
+bananapim2plus next buster desktop stable yes
+bananapim2plus next bionic cli stable yes
+bananapim2plus next stretch cli stable no
+bananapim2plus dev buster minimal beta yes
+
+# Bananapi M2U R40
+
+bananapim2ultra dev buster minimal beta yes
+
+# Bananapi M3
+
+bananapim3 dev buster minimal beta yes
+
+# Bananapi M64
+
+bananapim64 next bionic minimal stable yes
+bananapim64 next buster minimal stable yes
+bananapim64 dev buster minimal beta yes
+
+# Bananapi pro A20
+
+bananapipro next buster desktop stable yes
+bananapipro next buster cli stable yes
+bananapipro next bionic cli stable yes
+bananapipro next stretch cli stable yes
+bananapipro dev buster minimal beta yes
+
+# Clearfog Base
+clearfogbase default buster cli stable yes
+clearfogbase default stretch cli stable yes
+clearfogbase next buster cli stable yes
+clearfogbase next bionic cli stable yes
+
+# Clearfog Pro
+clearfogpro default buster cli stable yes
+clearfogpro default stretch cli stable yes
+clearfogpro next buster cli stable yes
+clearfogpro next bionic cli stable yes
+
+# Cubietruck
+cubietruck next buster desktop stable yes
+cubietruck next buster cli stable yes
+cubietruck next bionic cli stable yes
+cubietruck next stretch cli stable yes
+cubietruck dev buster minimal beta yes
+
+# Cubox-i
+cubox-i default buster desktop stable yes
+cubox-i default bionic cli stable yes
+cubox-i next buster cli stable yes
+cubox-i next bionic desktop stable yes
+cubox-i next buster minimal stable yes
+
+# Helios4
+helios4 default stretch cli stable yes
+helios4 next buster cli stable yes
+helios4 next bionic cli stable yes
+helios4 next stretch cli stable no
+
+# Khadas Vim1
+kvim1 dev buster desktop beta yes
+kvim1 dev buster minimal beta yes
+
+# La frite
+
+lafrite dev buster minimal beta yes
+lafrite dev bionic minimal beta yes
+
+# Olimex Lime
+
+lime next buster cli stable yes
+lime default xenial desktop stable no
+
+# Olimex Lime2
+lime2 next buster desktop stable yes
+lime2 next buster cli stable yes
+lime2 next bionic cli stable yes
+lime2 next stretch cli stable yes
+lime2 dev buster minimal beta yes
+
+# lime-a64
+
+lime-a64 next bionic minimal stable yes
+lime-a64 next buster minimal stable yes
+lime-a64 dev buster minimal beta yes
+
+# MACCHIATObin Double Shot
+
+macchiatobin-doubleshot default buster cli stable no
+macchiatobin-doubleshot default bionic cli stable no
+
+
+# nanopct3
+
+nanopct3 next buster cli stable yes
+nanopct3 next buster cli stable yes
+nanopct3 next bionic desktop stable yes
+nanopct3 next bionic desktop stable yes
+nanopct3 next buster minimal stable yes
+
+# nanopct3plus
+
+nanopct3plus next buster cli stable yes
+nanopct3plus next buster cli stable yes
+nanopct3plus next bionic desktop stable yes
+nanopct3plus next bionic desktop stable yes
+nanopct3plus next buster minimal stable yes
+
+# nanopct4
+
+nanopct4 default buster cli stable yes
+nanopct4 default buster minimal stable yes
+nanopct4 default buster desktop stable yes
+nanopct4 default bionic desktop stable yes
+nanopct4 dev buster minimal beta yes
+
+# nanopi-r1
+
+nanopi-r1 next buster cli stable yes
+nanopi-r1 next stretch cli stable yes
+nanopi-r1 dev buster minimal beta yes
+
+# nanopiair
+
+nanopiair next buster cli stable yes
+nanopiair next stretch cli stable yes
+nanopiair dev buster minimal beta yes
+
+# nanopiduo
+
+nanopiduo next buster cli stable yes
+nanopiduo next stretch cli stable yes
+nanopiduo dev buster minimal beta yes
+
+# nanopiduo2
+
+nanopiduo2 next buster cli stable yes
+nanopiduo2 next stretch cli stable yes
+nanopiduo2 dev buster minimal beta yes
+
+# nanopifire3
+
+nanopifire3 next buster cli stable yes
+nanopifire3 next buster minimal stable yes
+nanopifire3 next bionic cli stable yes
+
+# nanopik1plus
+
+nanopik1plus next buster desktop stable yes
+nanopik1plus next buster cli stable yes
+nanopik1plus next bionic cli stable yes
+nanopik1plus next stretch cli stable yes
+nanopik1plus dev buster minimal beta yes
+
+# nanopik2-s905
+
+nanopik2-s905 next buster cli stable yes
+nanopik2-s905 next stretch cli stable yes
+nanopik2-s905 next bionic desktop stable yes
+nanopik2-s905 dev buster minimal beta yes
+
+# nanopim1
+
+nanopim1 next buster desktop stable yes
+nanopim1 next buster cli stable yes
+nanopim1 next bionic cli stable yes
+nanopim1 next stretch cli stable yes
+nanopim1 dev buster minimal beta yes
+
+# nanopim3
+
+nanopim3 next buster cli stable yes
+nanopim3 next buster cli stable yes
+nanopim3 next bionic desktop stable yes
+nanopim3 next bionic desktop stable yes
+nanopim3 next buster minimal stable yes
+
+# nanopim4
+
+nanopim4 default buster cli stable yes
+nanopim4 default buster minimal stable yes
+nanopim4 default buster desktop stable yes
+nanopim4 default bionic desktop stable yes
+nanopim4 dev buster minimal beta yes
+
+# nanopineo
+
+nanopineo next buster cli stable yes
+nanopineo next stretch cli stable yes
+nanopineo dev buster minimal beta yes
+
+# nanopineocore2
+
+nanopineo2 next buster cli stable yes
+nanopineo2 next stretch cli stable yes
+nanopineo2 dev buster minimal beta yes
+
+# nanopineo4
+
+nanopineo4 default buster cli stable yes
+nanopineo4 default buster minimal stable yes
+nanopineo4 default buster desktop stable yes
+nanopineo4 default bionic desktop stable yes
+nanopineo4 dev buster minimal beta yes
+
+# nanopineocore2
+
+nanopineocore2 next buster cli stable yes
+nanopineocore2 next stretch cli stable yes
+nanopineocore2 dev buster minimal beta yes
+
+# nanopineoplus2
+
+nanopineoplus2 next buster cli stable yes
+nanopineoplus2 next stretch cli stable yes
+nanopineoplus2 dev buster minimal beta yes
+
+# Odroid C1
+
+odroidc1 next bionic minimal beta yes
+odroidc1 next buster minimal beta yes
+
+# Odroid C2
+
+odroidc2 next buster cli stable yes
+odroidc2 next buster minimal stable yes
+odroidc2 next stretch cli stable yes
+odroidc2 next bionic desktop stable yes
+odroidc2 dev buster minimal beta yes
+
+# Odroid N2
+
+odroidn2 default buster cli stable yes
+odroidn2 default buster desktop stable yes
+odroidn2 default stretch cli stable yes
+odroidn2 default bionic desktop stable yes
+odroidn2 default buster minimal stable yes
+odroidn2 default buster minimal beta no
+
+# Odroid XU4
+
+odroidxu4 default buster cli stable yes
+odroidxu4 default buster desktop stable yes
+odroidxu4 default stretch cli stable yes
+odroidxu4 default bionic desktop stable yes
+odroidxu4 default buster minimal stable yes
+odroidxu4 dev buster minimal beta yes
+
+# orangepi2
+
+orangepi2 next buster desktop stable yes
+orangepi2 next buster cli stable yes
+orangepi2 next bionic cli stable yes
+orangepi2 next stretch cli stable yes
+orangepi2 dev buster minimal beta yes
+
+# orangepi 3
+
+orangepi3 dev buster cli beta yes
+orangepi3 dev stretch cli beta yes
+orangepi3 dev buster minimal beta yes
+
+# orangepi-r1
+
+orangepi-r1 next buster cli stable yes
+orangepi-r1 next stretch cli stable yes
+orangepi-r1 dev buster minimal beta yes
+
+# Orangepi rk3399
+
+orangepi-rk3399 default buster cli stable yes
+orangepi-rk3399 default buster cli stable yes
+orangepi-rk3399 default bionic desktop stable yes
+orangepi-rk3399 default bionic desktop stable yes
+orangepi-rk3399 dev buster minimal beta yes
+
+# orangepilite
+
+orangepilite next buster desktop stable yes
+orangepilite next buster cli stable yes
+orangepilite next bionic cli stable yes
+orangepilite next stretch cli stable yes
+orangepilite dev buster minimal beta yes
+
+# orangepilite2
+
+orangepilite2 dev buster cli beta yes
+orangepilite2 dev stretch cli beta yes
+orangepilite2 dev buster minimal beta yes
+
+# orangepioneplus
+
+orangepioneplus dev buster cli beta yes
+orangepioneplus dev stretch cli beta yes
+orangepioneplus dev buster minimal beta yes
+
+# orangepione
+
+orangepione next buster desktop stable yes
+orangepione next buster cli stable yes
+orangepione next bionic cli stable yes
+orangepione next stretch cli stable yes
+orangepione dev buster minimal beta yes
+
+# orangepipc
+
+orangepipc next buster desktop stable yes
+orangepipc next buster cli stable yes
+orangepipc next bionic cli stable yes
+orangepipc next stretch cli stable yes
+orangepipc dev buster minimal beta yes
+
+# orangepipc2
+
+orangepipc2 next buster desktop stable yes
+orangepipc2 next buster cli stable yes
+orangepipc2 next bionic cli stable yes
+orangepipc2 next stretch cli stable yes
+orangepipc2 dev buster minimal beta yes
+
+# orangepipcplus
+
+orangepipcplus next buster desktop stable yes
+orangepipcplus next buster cli stable yes
+orangepipcplus next bionic cli stable yes
+orangepipcplus next stretch cli stable yes
+orangepipcplus dev buster minimal beta yes
+
+# orangepiplus
+
+orangepiplus next buster desktop stable yes
+orangepiplus next buster cli stable yes
+orangepiplus next bionic cli stable yes
+orangepiplus next stretch cli stable yes
+orangepiplus dev buster minimal beta yes
+
+# orangepiplus2e
+
+orangepiplus2e next buster desktop stable yes
+orangepiplus2e next buster cli stable yes
+orangepiplus2e next bionic cli stable yes
+orangepiplus2e next stretch cli stable yes
+orangepiplus2e dev buster minimal beta yes
+
+# Orangepi Prime
+
+orangepiprime next buster cli stable yes
+orangepiprime next stretch cli stable yes
+orangepiprime dev buster minimal beta yes
+
+# Orangepi Win
+
+orangepiwin next buster cli stable yes
+orangepiwin next stretch cli stable yes
+orangepiwin dev buster minimal beta yes
+
+# orangepizero
+
+orangepizero next buster cli stable yes
+orangepizero next stretch cli stable yes
+orangepizero dev buster minimal beta yes
+
+# orangepizeroplus
+
+orangepizeroplus next buster cli stable yes
+orangepizeroplus next stretch cli stable yes
+orangepizeroplus dev buster minimal beta yes
+
+# orangepizeroplus2-h3
+
+orangepizeroplus2-h3 next buster cli stable yes
+orangepizeroplus2-h3 next stretch cli stable yes
+orangepizeroplus2-h3 dev buster minimal beta yes
+
+# orangepizeroplus2-h5
+
+orangepizeroplus2-h5 next buster cli stable yes
+orangepizeroplus2-h5 next stretch cli stable yes
+orangepizeroplus2-h5 dev buster minimal beta yes
+
+# Pine64so
+
+pine64so next buster cli stable yes
+pine64so next stretch cli stable yes
+pine64so dev buster minimal beta yes
+
+# Pinebook A64
+
+pinebook-a64 next bionic desktop stable yes
+pinebook-a64 next buster minimal stable yes
+pinebook-a64 dev buster desktop beta yes
+
+# Pine H64
+
+pineh64 dev buster minimal beta yes
+
+# Renegade
+
+renegade default buster cli stable yes
+renegade default buster cli stable yes
+renegade default bionic desktop stable yes
+renegade default bionic desktop stable yes
+renegade dev buster minimal beta yes
+
+# Rock64
+
+rock64 default buster cli stable yes
+rock64 default buster cli stable yes
+rock64 default bionic desktop stable yes
+rock64 default bionic desktop stable yes
+rock64 dev buster minimal beta yes
+
+# Rock-pi-4
+
+rockpi-4b default buster cli stable yes
+rockpi-4b default buster cli stable yes
+rockpi-4b default bionic desktop stable yes
+rockpi-4b default bionic desktop stable yes
+rockpi-4b dev buster minimal beta yes
+
+# Rock64pro
+
+rockpro64 default buster cli stable yes
+rockpro64 default buster cli stable yes
+rockpro64 default bionic desktop stable yes
+rockpro64 default bionic desktop stable yes
+rockpro64 dev buster minimal beta yes
+
+# Teres A64
+
+teres-a64 next bionic desktop stable yes
+teres-a64 next buster minimal stable yes
+teres-a64 dev buster desktop beta yes
+
+# Tinkerboard
+
+tinkerboard default buster cli stable yes
+tinkerboard default buster desktop stable yes
+tinkerboard default bionic cli stable yes
+tinkerboard default bionic desktop stable yes
+tinkerboard next buster minimal stable yes
+tinkerboard dev buster minimal beta yes
+
+# tritium-h3
+
+tritium-h3 next buster cli stable yes
+tritium-h3 next buster cli stable yes
+tritium-h3 next bionic desktop stable yes
+tritium-h3 next bionic desktop stable yes
+tritium-h3 dev buster minimal beta yes
+
+# tritium-h5
+
+tritium-h5 next buster cli stable yes
+tritium-h5 next buster cli stable yes
+tritium-h5 next bionic desktop stable yes
+tritium-h5 next bionic desktop stable yes
+tritium-h5 dev buster minimal beta yes
+
+# xt-q8l-v10
+
+xt-q8l-v10 default buster cli stable yes
+xt-q8l-v10 default buster cli stable yes
+xt-q8l-v10 default bionic desktop stable yes
+xt-q8l-v10 default bionic desktop stable yes
+
+# Z28 pro
+
+z28pro default buster cli stable no
+z28pro default buster cli stable no
+z28pro default bionic desktop stable no
+z28pro default bionic desktop stable no
diff --git a/config/templates/example.deb b/config/templates/example.deb
new file mode 100644
index 000000000..da97d98ed
Binary files /dev/null and b/config/templates/example.deb differ
diff --git a/lib/build-all-ng.sh b/lib/build-all-ng.sh
new file mode 100644
index 000000000..73a42833e
--- /dev/null
+++ b/lib/build-all-ng.sh
@@ -0,0 +1,320 @@
+#!/bin/bash
+#
+# Copyright (c) Authors: http://www.armbian.com/authors
+#
+# This file is licensed under the terms of the GNU General Public
+# License version 2. This program is licensed "as is" without any
+# warranty of any kind, whether express or implied.
+
+# This file is a part of the Armbian build script
+# https://github.com/armbian/build/
+
+# Functions:
+# pack_upload
+# build_main
+# array_contains
+# build_all
+
+
+
+
+
+if [[ $BETA == "yes" ]]; then STABILITY="beta"; else STABILITY="stable"; fi
+if [[ -z $KERNEL_ONLY ]]; then KERNEL_ONLY="yes"; fi
+# just to make sure we set those variables
+KERNEL_CONFIGURE="no"
+CLEAN_LEVEL="make,oldcache"
+
+
+# cleanup
+rm -f /run/armbian/*.pid
+mkdir -p /run/armbian
+
+
+# support user defined configurations
+if [[ -f $USERPATCHES_PATH/targets.conf ]]; then
+
+ display_alert "Adding user provided targets configuration"
+ TARGETS="${USERPATCHES_PATH}/targets.conf"
+
+else
+
+ TARGETS="${SRC}/config/targets.conf"
+
+fi
+
+pack_upload ()
+{
+
+ # pack into .7z and upload to server or just pack. In the background
+
+ display_alert "Signing" "Please wait!" "info"
+ local version="Armbian_${REVISION}_${BOARD^}_${DISTRIBUTION}_${RELEASE}_${BRANCH}_${VER/-$LINUXFAMILY/}"
+ local subdir="archive"
+
+ [[ $BUILD_DESKTOP == yes ]] && version=${version}_desktop
+ [[ $BUILD_MINIMAL == yes ]] && version=${version}_minimal
+
+ [[ $BETA == yes ]] && local subdir=nightly
+ local filename=$DESTIMG/${version}.7z
+
+ # stage: generate sha256sum.sha
+ cd "${DESTIMG}" || exit
+ sha256sum -b "${version}.img" > ${version}.img.sha
+
+ # stage: sign with PGP
+ if [[ -n $GPG_PASS ]]; then
+
+ echo "${GPG_PASS}" | gpg --passphrase-fd 0 --armor --detach-sign --pinentry-mode loopback --batch --yes \
+ "${version}.img"
+
+ fi
+
+ if [[ -n "${SEND_TO_SERVER}" ]]; then
+
+ display_alert "Compressing and uploading" "Please wait!" "info"
+ # pack and move file to server under new process
+ nice -n 19 bash -c "7za a -t7z -bd -m0=lzma2 -mx=3 -mfb=64 -md=32m -ms=on $filename ${version}.img \
+ ${version}.img.txt *.asc ${version}.img.sha >/dev/null 2>&1 ; \
+ find . -type f -not -name '*.7z' -print0 | xargs -0 rm -- ; \
+ while ! rsync -arP $DESTIMG/. -e 'ssh -p 22' ${SEND_TO_SERVER}:/var/www/dl.armbian.com/${BOARD}/${subdir}; \
+ do sleep 5; done; rm -r $DESTIMG; \
+ rm /run/armbian/Armbian_${BOARD^}_${BRANCH}_${RELEASE}_${BUILD_DESKTOP}_${BUILD_MINIMAL}.pid" &
+
+ else
+
+ display_alert "Compressing" "Please wait!" "info"
+ # pack and move file to debs subdirectory
+ nice -n 19 bash -c "7za a -t7z -bd -m0=lzma2 -mx=3 -mfb=64 -md=32m -ms=on $filename ${version}.img \
+ ${version}.img.txt *.asc ${version}.img.sha >/dev/null 2>&1 ; \
+ find . -type f -not -name '*.7z' -print0 | xargs -0 rm -- ; mv $filename $DEST/images ; \
+ rm -r $DESTIMG; rm /run/armbian/Armbian_${BOARD^}_${BRANCH}_${RELEASE}_${BUILD_DESKTOP}_${BUILD_MINIMAL}.pid" &
+
+ fi
+
+}
+
+
+
+
+build_main ()
+{
+
+ # build images which we do pack or kernel
+
+ touch "/run/armbian/Armbian_${BOARD^}_${BRANCH}_${RELEASE}_${BUILD_DESKTOP}_${BUILD_MINIMAL}.pid";
+ if [[ $KERNEL_ONLY != yes ]]; then
+
+ source "${SRC}"/lib/main.sh
+ [[ $BSP_BUILD != yes ]] && pack_upload
+
+ else
+
+ source "${SRC}"/lib/main.sh
+ rm "/run/armbian/Armbian_${BOARD^}_${BRANCH}_${RELEASE}_${BUILD_DESKTOP}_${BUILD_MINIMAL}.pid"
+
+ fi
+
+}
+
+
+
+
+array_contains ()
+{
+
+ # utility snippet
+
+ local array="$1[@]"
+ local seeking=$2
+ local in=1
+
+ for element in "${!array}"; do
+ if [[ $element == $seeking ]]; then
+ in=0
+ break
+ fi
+ done
+ return $in
+
+}
+
+
+
+
+function build_all()
+{
+
+ # main routine
+
+ buildall_start=$(date +%s)
+ n=0
+ ARRAY=()
+ buildlist="cat "
+
+ # building selected ones
+ if [[ -n ${REBUILD_IMAGES} ]]; then
+
+ buildlist="grep -w '"
+ filter="'"
+ for build in $(tr ',' ' ' <<< $REBUILD_IMAGES); do
+ buildlist=$buildlist"$build\|"
+ filter=$filter"$build\|"
+ done
+ buildlist=${buildlist::-2}"'"
+ filter=${filter::-2}"'"
+
+ fi
+
+ # TO DO!
+ # find unique boards - we will build debs for all variants
+ sorted_unique_ids=($(echo "${ids[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
+ unique_boards=$(eval $buildlist ${SRC}/config/targets.conf | sed '/^#/ d' | awk '{print $1}')
+ unique_boards=$(echo "${unique_boards[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
+
+ while read line; do
+
+ [[ "$line" =~ ^#.*$ ]] && continue
+ [[ -n ${REBUILD_IMAGES} ]] && [[ -z $(echo $line | eval grep -w $filter) ]] && continue
+
+ unset LINUXFAMILY LINUXCONFIG KERNELDIR KERNELSOURCE KERNELBRANCH BOOTDIR BOOTSOURCE BOOTBRANCH ARCH \
+ UBOOT_USE_GCC KERNEL_USE_GCC DEFAULT_OVERLAYS CPUMIN CPUMAX UBOOT_VER KERNEL_VER GOVERNOR BOOTSIZE \
+ BOOTFS_TYPE UBOOT_TOOLCHAIN KERNEL_TOOLCHAIN DEBOOTSTRAP_LIST PACKAGE_LIST_EXCLUDE KERNEL_IMAGE_TYPE \
+ write_uboot_platform family_tweaks family_tweaks_bsp setup_write_uboot_platform uboot_custom_postprocess \
+ atf_custom_postprocess family_tweaks_s BOOTSCRIPT UBOOT_TARGET_MAP LOCALVERSION UBOOT_COMPILER \
+ KERNEL_COMPILER BOOTCONFIG BOOTCONFIG_VAR_NAME BOOTCONFIG_DEFAULT BOOTCONFIG_NEXT BOOTCONFIG_DEV MODULES \
+ MODULES_NEXT MODULES_DEV INITRD_ARCH BOOTENV_FILE BOOTDELAY MODULES_BLACKLIST MODULES_BLACKLIST_NEXT \
+ ATF_TOOLCHAIN2 MODULES_BLACKLIST_DEV MOUNT SDCARD BOOTPATCHDIR KERNELPATCHDIR RELEASE FULL_DESKTOP \
+ IMAGE_TYPE OVERLAY_PREFIX ASOUND_STATE ATF_COMPILER ATF_USE_GCC ATFSOURCE ATFDIR ATFBRANCH ATFSOURCEDIR \
+ PACKAGE_LIST_RM NM_IGNORE_DEVICES DISPLAY_MANAGER family_tweaks_bsp_s CRYPTROOT_ENABLE CRYPTROOT_PASSPHRASE \
+ CRYPTROOT_SSH_UNLOCK CRYPTROOT_SSH_UNLOCK_PORT CRYPTROOT_SSH_UNLOCK_KEY_NAME ROOT_MAPPER NETWORK HDMI \
+ USB WIRELESS ARMBIANMONITOR DEFAULT_CONSOLE FORCE_BOOTSCRIPT_UPDATE SERIALCON UBOOT_TOOLCHAIN2 toolchain2 \
+ BUILD_REPOSITORY_URL BUILD_REPOSITORY_COMMIT DESKTOP_AUTOLOGIN BUILD_MINIMAL BUILD_TARGET BUILD_STABILITY \
+ HOST BUILD_IMAGE BOARDFAMILY DEB_STORAGE REPO_STORAGE REPO_CONFIG REPOSITORY_UPDATE PACKAGE_LIST_RELEASE
+
+ read -r BOARD BRANCH RELEASE BUILD_TARGET BUILD_STABILITY BUILD_IMAGE <<< "${line}"
+
+ # read all possible configurations
+ source ${SRC}"/config/boards/${BOARD}".eos 2> /dev/null
+ source ${SRC}"/config/boards/${BOARD}".tvb 2> /dev/null
+ source ${SRC}"/config/boards/${BOARD}".csc 2> /dev/null
+ source ${SRC}"/config/boards/${BOARD}".wip 2> /dev/null
+ source ${SRC}"/config/boards/${BOARD}".conf 2> /dev/null
+
+ # exceptions handling
+ [[ ${BOARDFAMILY} == sun*i* && $BRANCH != default ]] && BOARDFAMILY=sunxi
+
+ # small optimisation. we only (try to) build needed kernels
+ if [[ $KERNEL_ONLY == yes ]]; then
+
+ array_contains ARRAY "${BOARDFAMILY}${BRANCH}${BUILD_STABILITY}" && continue
+
+ elif [[ $BUILD_IMAGE == no ]] ; then
+
+ continue
+
+ fi
+ ARRAY+=("${BOARDFAMILY}${BRANCH}${BUILD_STABILITY}")
+
+ BUILD_DESKTOP="no"
+ BUILD_MINIMAL="no"
+
+ [[ ${BUILD_TARGET} == "desktop" ]] && BUILD_DESKTOP="yes"
+ [[ ${BUILD_TARGET} == "minimal" ]] && BUILD_MINIMAL="yes"
+
+ # create beta or stable
+ if [[ "${BUILD_STABILITY}" == "${STABILITY}" ]]; then
+
+ ((n+=1))
+
+ if [[ $1 != "dryrun" ]]; then
+ if [[ $(find /run/armbian/*.pid 2>/dev/null | wc -l) -lt ${MULTITHREAD} ]]; then
+
+ display_alert "Building in the back ${n}."
+ if [[ "${BSP_BUILD}" == yes && ${ALLTARGETS} == "yes" ]]; then
+ TARGETS=(xenial stretch buster bionic disco)
+ for RELEASE in "${TARGETS[@]}"
+ do
+ display_alert "BSP for ${RELEASE}."
+ sleep .5
+ (build_main) &
+ done
+ else
+ (build_main) &
+ sleep $(( ( RANDOM % 10 ) + 10 ))
+ fi
+
+ else
+
+ display_alert "Building ${n}."
+ if [[ "${BSP_BUILD}" == yes && ${ALLTARGETS} == "yes" ]]; then
+ TARGETS=(xenial stretch buster bionic disco)
+ for RELEASE in "${TARGETS[@]}"
+ do
+ display_alert "BSP for ${RELEASE}."
+ build_main
+ done
+ else
+ build_main
+ fi
+
+ fi
+
+ else
+
+ # In dryrun it only prints out what will be build
+ printf "%s\t%-32s\t%-8s\t%-14s\t%-6s\t%-6s\t%-6s\n" "${n}." \
+ "$BOARD (${BOARDFAMILY})" "${BRANCH}" "${RELEASE}" "${BUILD_DESKTOP}" "${BUILD_MINIMAL}"
+
+ # create remote directory structure
+ if [[ -n "${SEND_TO_SERVER}" ]]; then
+ ssh "${SEND_TO_SERVER}" "mkdir -p /var/www/dl.armbian.com/${BOARD}/{archive,nightly}"
+ fi
+
+ fi
+
+ fi
+
+ done < ${TARGETS}
+
+}
+
+# display what will be build
+echo ""
+display_alert "Building all targets" "$STABILITY $(if [[ $KERNEL_ONLY == "yes" ]] ; then echo "kernels"; \
+else echo "images"; fi)" "info"
+
+printf "\n%s\t%-32s\t%-8s\t%-14s\t%-6s\t%-6s\t%-6s\n\n" "" "board" "branch" "release" "XFCE" "minimal"
+
+# display what we will build
+build_all "dryrun"
+
+if [[ $BUILD_ALL != demo ]] ; then
+
+ echo ""
+ # build
+ build_all
+
+fi
+
+# wait until they are not finshed
+sleep 5
+while :
+do
+ if [[ $(df | grep .tmp | wc -l) -lt 1 ]]; then
+ break
+ fi
+ sleep 5
+done
+
+while :
+do
+ if [[ -z $(ps -uax | grep 7z | grep Armbian) ]]; then
+ break
+ fi
+ sleep 5
+done
+
+buildall_end=$(date +%s)
+buildall_runtime=$(((buildall_end - buildall_start) / 60))
+display_alert "Runtime in total" "$buildall_runtime min" "info"
diff --git a/lib/build-all.sh b/lib/build-all.sh
deleted file mode 100644
index 294b60242..000000000
--- a/lib/build-all.sh
+++ /dev/null
@@ -1,282 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) Authors: http://www.armbian.com/authors
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-FORCEDRELEASE=$RELEASE
-
-# when we want to build from certain start
-#from=1
-#stop=2
-
-rm -rf /run/armbian
-mkdir -p /run/armbian
-RELEASE_LIST=("xenial" "jessie" "stretch" "bionic" "buster" "disco" )
-BRANCH_LIST=("default" "next" "dev")
-
-pack_upload ()
-{
- # pack into .7z and upload to server
- # stage: init
- display_alert "Signing and compressing" "Please wait!" "info"
- local version="Armbian_${REVISION}_${BOARD^}_${DISTRIBUTION}_${RELEASE}_${BRANCH}_${VER/-$LINUXFAMILY/}"
- local subdir="archive"
- [[ $BUILD_DESKTOP == yes ]] && version=${version}_desktop
- [[ $BETA == yes ]] && local subdir=nightly
- local filename=$DESTIMG/${version}.7z
-
- # stage: generate sha256sum.sha
- cd "${DESTIMG}" || exit
- sha256sum -b "${version}.img" > sha256sum.sha
-
- # stage: sign with PGP
- if [[ -n $GPG_PASS ]]; then
- echo "${GPG_PASS}" | gpg --passphrase-fd 0 --armor --detach-sign --pinentry-mode loopback --batch --yes "${version}.img"
- fi
-
- if [[ -n "${SEND_TO_SERVER}" ]]; then
- # create remote directory structure
- ssh "${SEND_TO_SERVER}" "mkdir -p /var/www/dl.armbian.com/${BOARD}/{archive,nightly};";
-
- # pack and move file to server under new process
- nice -n 19 bash -c "\
- 7za a -t7z -bd -m0=lzma2 -mx=3 -mfb=64 -md=32m -ms=on $filename ${version}.img armbian.txt *.asc sha256sum.sha >/dev/null 2>&1 ; \
- find . -type f -not -name '*.7z' -print0 | xargs -0 rm -- ; \
- while ! rsync -arP $DESTIMG/. -e 'ssh -p 22' ${SEND_TO_SERVER}:/var/www/dl.armbian.com/${BOARD}/${subdir};do sleep 5;done; \
- rm -r $DESTIMG" &
- else
- # pack and move file to debs subdirectory
- nice -n 19 bash -c "\
- 7za a -t7z -bd -m0=lzma2 -mx=3 -mfb=64 -md=32m -ms=on $filename ${version}.img armbian.txt *.asc sha256sum.sha >/dev/null 2>&1 ; \
- find . -type f -not -name '*.7z' -print0 | xargs -0 rm -- ; \
- mv $filename $DEST/images ; rm -r $DESTIMG" &
- fi
-}
-
-build_main ()
-{
- touch "/run/armbian/Armbian_${BOARD^}_${BRANCH}_${RELEASE}_${BUILD_DESKTOP}.pid";
- # shellcheck source=main.sh
- source "${SRC}"/lib/main.sh;
- [[ $KERNEL_ONLY != yes ]] && pack_upload
- rm "/run/armbian/Armbian_${BOARD^}_${BRANCH}_${RELEASE}_${BUILD_DESKTOP}.pid"
-}
-
-
-make_targets ()
-{
- if [[ -n $CLI_TARGET && -z $1 ]]; then
- # RELEASES : BRANCHES
- CLI_TARGET=($(tr ':' ' ' <<< "$CLI_TARGET"))
- build_settings_target=($(tr ',' ' ' <<< "${CLI_TARGET[0]}"))
- build_settings_branch=($(tr ',' ' ' <<< "${CLI_TARGET[1]}"))
-
- [[ ${build_settings_target[0]} == "%" ]] && build_settings_target[0]="${RELEASE_LIST[@]}"
- [[ ${build_settings_branch[0]} == "%" ]] && build_settings_branch[0]="${BRANCH_LIST[@]}"
-
- for release in ${build_settings_target[@]}; do
- for kernel in ${build_settings_branch[@]}; do
- buildlist+=("$BOARD $kernel $release no")
- done
- done
- fi
-
- if [[ -n $DESKTOP_TARGET && -z $1 ]]; then
- # RELEASES : BRANCHES
- DESKTOP_TARGET=($(tr ':' ' ' <<< "$DESKTOP_TARGET"))
- build_settings_target=($(tr ',' ' ' <<< "${DESKTOP_TARGET[0]}"))
- build_settings_branch=($(tr ',' ' ' <<< "${DESKTOP_TARGET[1]}"))
-
- [[ ${build_settings_target[0]} == "%" ]] && build_settings_target[0]="${RELEASE_LIST[@]}"
- [[ ${build_settings_branch[0]} == "%" ]] && build_settings_branch[0]="${BRANCH_LIST[@]}"
-
- for release in ${build_settings_target[@]}; do
- for kernel in ${build_settings_branch[@]}; do
- buildlist+=("$BOARD $kernel $release yes")
- done
- done
- fi
-
- if [[ -n $CLI_BETA_TARGET && -n $1 ]]; then
- # RELEASES : BRANCHES
- CLI_BETA_TARGET=($(tr ':' ' ' <<< "$CLI_BETA_TARGET"))
- build_settings_target=($(tr ',' ' ' <<< "${CLI_BETA_TARGET[0]}"))
- build_settings_branch=($(tr ',' ' ' <<< "${CLI_BETA_TARGET[1]}"))
-
- [[ ${build_settings_target[0]} == "%" ]] && build_settings_target[0]="${RELEASE_LIST[@]}"
- [[ ${build_settings_branch[0]} == "%" ]] && build_settings_branch[0]="${BRANCH_LIST[@]}"
-
- for release in ${build_settings_target[@]}; do
- for kernel in ${build_settings_branch[@]}; do
- buildlist+=("$BOARD $kernel $release no")
- done
- done
- fi
-
- if [[ -n $DESKTOP_BETA_TARGET && -n $1 ]]; then
- # RELEASES : BRANCHES
- DESKTOP_BETA_TARGET=($(tr ':' ' ' <<< "$DESKTOP_BETA_TARGET"))
- build_settings_target=($(tr ',' ' ' <<< "${DESKTOP_BETA_TARGET[0]}"))
- build_settings_branch=($(tr ',' ' ' <<< "${DESKTOP_BETA_TARGET[1]}"))
-
- [[ ${build_settings_target[0]} == "%" ]] && build_settings_target[0]="${RELEASE_LIST[@]}"
- [[ ${build_settings_branch[0]} == "%" ]] && build_settings_branch[0]="${BRANCH_LIST[@]}"
-
- for release in ${build_settings_target[@]}; do
- for kernel in ${build_settings_branch[@]}; do
- buildlist+=("$BOARD $kernel $release yes")
- done
- done
- fi
-}
-
-create_images_list()
-{
- #
- # if parameter is true, than we build beta list
- #
- local naming="$SRC/config/boards/*.conf";
- if [[ "$EXPERT" == "yes" ]]; then naming=$naming" $SRC/config/boards/*.wip"; fi
- if [[ -n $REBUILD_IMAGES ]]; then naming=$naming" $SRC/config/boards/*.csc"; REBUILD_IMAGES=$REBUILD_IMAGES","; fi
-
- for board in $naming; do
- BOARD=$(basename "${board}" | cut -d'.' -f1)
- local file="${SRC}/config/boards/${BOARD}"
- if [[ -f $file".conf" ]]; then source "${file}.conf"; fi
- if [[ -f $file".wip" ]]; then source "${file}.wip"; fi
- if [[ -f $file".csc" ]]; then source "${file}.csc"; fi
- if [[ -f $file".tvb" ]]; then source "${file}.tvb"; fi
-
- # beta targets are the same as stable. To build the same set beta set as future stable.
- if [[ "$MERGETARGETS" == "yes" ]]; then
- CLI_BETA_TARGET=$CLI_TARGET
- DESKTOP_BETA_TARGET=$DESKTOP_TARGET
- fi
-
- if [[ -z $REBUILD_IMAGES ]]; then
- make_targets $1
- elif [[ $REBUILD_IMAGES == *"$BOARD,"* ]]; then
- make_targets $1
- fi
- unset CLI_TARGET CLI_BRANCH DESKTOP_TARGET DESKTOP_BRANCH KERNEL_TARGET CLI_BETA_TARGET DESKTOP_BETA_TARGET
- done
-}
-
-create_kernels_list()
-{
- local naming="$SRC/config/boards/*.conf";
- if [[ "$EXPERT" == "yes" ]]; then naming=$naming" $SRC/config/boards/*.wip"; fi
- if [[ -n $REBUILD_IMAGES ]]; then naming=$naming" $SRC/config/boards/*.csc"; fi
- for board in $naming; do
- BOARD=$(basename $board | cut -d'.' -f1)
- local file="${SRC}/config/boards/${BOARD}"
- if [[ -f $file".conf" ]]; then source "${file}.conf"; fi
- if [[ -f $file".wip" ]]; then source "${file}.wip"; fi
- if [[ -f $file".csc" ]]; then source "${file}.csc"; fi
- if [[ -f $file".tvb" ]]; then source "${file}.tvb"; fi
-
- if [[ -n $KERNEL_TARGET ]]; then
- for kernel in $(tr ',' ' ' <<< $KERNEL_TARGET); do
- buildlist+=("$BOARD $kernel")
- done
- fi
- unset KERNEL_TARGET
- done
-}
-
-buildlist=()
-
-
-htmlicons ()
-{
-[[ ${1^^} == YES ]] && echo "
"
-[[ ${1^^} == NO ]] && echo "
"
-[[ ${1^^} == NT ]] && echo "
"
-[[ ${1^^} == NA ]] && echo "
"
-}
-
-if [[ $KERNEL_ONLY == yes ]]; then
- create_kernels_list
- printf "%-3s %-20s %-10s %-10s %-10s\n" \# BOARD BRANCH
- REPORT="|# |Board|Branch|U-boot|Kernel version| Network | Wireless | HDMI | USB| Armbianmonitor |"
- REPORTHTML="
| # | Board | Branch | U-boot | Kernel | Network | WiFi | HDMI | USB | Logs |
"
- REPORT=$REPORT"\n|--|--|--|--:|--:|--:|--:|--:|--:|--:|"
-else
- create_images_list $BETA
- printf "%-3s %-20s %-10s %-10s %-10s\n" \# BOARD BRANCH RELEASE DESKTOP
-fi
-
-n=0
-for line in "${buildlist[@]}"; do
- ((n+=1))
- read -r BOARD BRANCH RELEASE BUILD_DESKTOP <<< "${line}"
- printf "%-3s %-20s %-10s %-10s %-10s\n" "$n" "$BOARD" "$BRANCH" "$RELEASE" "$BUILD_DESKTOP"
-done
-echo -e "\n${#buildlist[@]} total\n"
-
-[[ $BUILD_ALL == demo ]] && exit 0
-
-buildall_start=$(date +%s)
-n=0
-for line in "${buildlist[@]}"; do
- unset LINUXFAMILY LINUXCONFIG KERNELDIR KERNELSOURCE KERNELBRANCH BOOTDIR BOOTSOURCE BOOTBRANCH ARCH UBOOT_USE_GCC KERNEL_USE_GCC DEFAULT_OVERLAYS \
- CPUMIN CPUMAX UBOOT_VER KERNEL_VER GOVERNOR BOOTSIZE BOOTFS_TYPE UBOOT_TOOLCHAIN KERNEL_TOOLCHAIN PACKAGE_LIST_EXCLUDE KERNEL_IMAGE_TYPE \
- write_uboot_platform family_tweaks family_tweaks_bsp setup_write_uboot_platform uboot_custom_postprocess atf_custom_postprocess family_tweaks_s \
- BOOTSCRIPT UBOOT_TARGET_MAP LOCALVERSION UBOOT_COMPILER KERNEL_COMPILER BOOTCONFIG BOOTCONFIG_VAR_NAME BOOTCONFIG_DEFAULT BOOTCONFIG_NEXT BOOTCONFIG_DEV \
- MODULES MODULES_NEXT MODULES_DEV INITRD_ARCH BOOTENV_FILE BOOTDELAY MODULES_BLACKLIST MODULES_BLACKLIST_NEXT ATF_TOOLCHAIN2 \
- MODULES_BLACKLIST_DEV MOUNT SDCARD BOOTPATCHDIR KERNELPATCHDIR buildtext RELEASE IMAGE_TYPE OVERLAY_PREFIX ASOUND_STATE \
- ATF_COMPILER ATF_USE_GCC ATFSOURCE ATFDIR ATFBRANCH ATFSOURCEDIR PACKAGE_LIST_RM NM_IGNORE_DEVICES DISPLAY_MANAGER family_tweaks_bsp_s \
- CRYPTROOT_ENABLE CRYPTROOT_PASSPHRASE CRYPTROOT_SSH_UNLOCK CRYPTROOT_SSH_UNLOCK_PORT CRYPTROOT_SSH_UNLOCK_KEY_NAME ROOT_MAPPER \
- NETWORK HDMI USB WIRELESS ARMBIANMONITOR DEFAULT_CONSOLE FORCE_BOOTSCRIPT_UPDATE SERIALCON UBOOT_TOOLCHAIN2 toolchain2 \
- BUILD_REPOSITORY_URL BUILD_REPOSITORY_COMMIT DESKTOP_AUTOLOGIN BUILD_MINIMAL
-
- read -r BOARD BRANCH RELEASE BUILD_DESKTOP <<< "${line}"
- ((n+=1))
- [[ -z $RELEASE ]] && RELEASE=$FORCEDRELEASE;
- if [[ $from -le $n ]]; then
- [[ -z $BUILD_DESKTOP ]] && BUILD_DESKTOP="no"
- jobs=$(find /run/armbian | wc -l)
- if [[ $jobs -lt $MULTITHREAD ]]; then
- display_alert "Building in the back $n / ${#buildlist[@]}" "Board: $BOARD Kernel:$BRANCH${RELEASE:+ Release: $RELEASE}${BUILD_DESKTOP:+ Desktop: $BUILD_DESKTOP}" "ext"
- (build_main) &
- [[ $KERNEL_ONLY != yes ]] && sleep $(( ( RANDOM % 10 ) + 1 ))
- else
- display_alert "Building $buildtext $n / ${#buildlist[@]}" "Board: $BOARD Kernel:$BRANCH${RELEASE:+ Release: $RELEASE}${BUILD_DESKTOP:+ Desktop: $BUILD_DESKTOP}" "ext"
- build_main
- # include testing report if exist
- if [[ -f $SRC/cache/sources/testing-reports/${BOARD}-${BRANCH}.report ]]; then
- display_alert "Loading board report" "${BOARD}-${BRANCH}.report" "info"
- # shellcheck source=/dev/null
- source "${SRC}/cache/sources/testing-reports/${BOARD}-${BRANCH}.report"
- fi
- if [[ $KERNEL_ONLY == yes ]]; then
- REPORT=$REPORT"\n|$n|$BOARD|$BRANCH|$UBOOT_VER|$VER|$NETWORK|$WIRELESS|$HDMI|$USB|$ARMBIANMONITOR|"
- [[ -n $ARMBIANMONITOR ]] && ARMBIANMONITOR="
"
- REPORTHTML=$REPORTHTML"\n| $n | $BOARD | $BRANCH | $UBOOT_VER | $VER | $(htmlicons "$NETWORK") | $(htmlicons "$WIRELESS") | $(htmlicons "$HDMI") | $(htmlicons "$USB") | $ARMBIANMONITOR |
"
- fi
- fi
-
- fi
- if [[ -n $stop && $n -ge $stop ]]; then break; fi
-done
-
-display_alert "Build report" "$DEST/debug/report.md" "info"
-buildall_end=$(date +%s)
-buildall_runtime=$(((buildall_end - buildall_start) / 60))
-display_alert "Runtime in total" "$buildall_runtime min" "info"
-
-if [[ $KERNEL_ONLY == yes ]]; then
-
- echo -e "${REPORT}" > "${DEST}"/debug/report.md
-
- echo -e "\nSummary:\n\n|Armbian version | Built date| Built time in total\n|--|--:|--:|" >> "${DEST}"/debug/report.md
- echo -e "|$REVISION|$(date -d "@$buildall_end")|$buildall_runtime|" >> "${DEST}"/debug/report.md
- echo -e "$REPORTHTML| Current version: $REVISION - Refreshed at: $(date -d "@$buildall_end") |
" > "${DEST}"/debug/report.html
-
-fi
diff --git a/lib/chroot-buildpackages.sh b/lib/chroot-buildpackages.sh
index 413c6614d..3c881904b 100644
--- a/lib/chroot-buildpackages.sh
+++ b/lib/chroot-buildpackages.sh
@@ -168,7 +168,7 @@ chroot_build_packages()
continue
fi
- local plugin_target_dir=$DEST/debs/extra/$package_component/
+ local plugin_target_dir=${DEB_STORAGE}/extra/$package_component/
mkdir -p $plugin_target_dir
# check if needs building
@@ -292,8 +292,8 @@ chroot_installpackages_local()
mkdir -p /tmp/aptly-temp/
aptly -config=$conf repo create temp
# NOTE: this works recursively
- aptly -config=$conf repo add temp $DEST/debs/extra/${RELEASE}-desktop/
- aptly -config=$conf repo add temp $DEST/debs/extra/${RELEASE}-utils/
+ aptly -config=$conf repo add temp ${DEB_STORAGE}/extra/${RELEASE}-desktop/
+ aptly -config=$conf repo add temp ${DEB_STORAGE}/extra/${RELEASE}-utils/
# -gpg-key="925644A6"
aptly -keyring="$SRC/packages/extras-buildpkgs/buildpkg-public.gpg" -secret-keyring="$SRC/packages/extras-buildpkgs/buildpkg.gpg" -batch=true -config=$conf \
-gpg-key="925644A6" -passphrase="testkey1234" -component=temp -distribution=$RELEASE publish repo temp
diff --git a/lib/compilation.sh b/lib/compilation.sh
index 8afcd6cda..2afc930a9 100644
--- a/lib/compilation.sh
+++ b/lib/compilation.sh
@@ -11,6 +11,8 @@
# compile_atf
# compile_uboot
# compile_kernel
+# compile_firmware
+# compile_ambian-config
# compile_sunxi_tools
# install_rkbin_tools
# grab_version
@@ -90,6 +92,9 @@ compile_atf()
[[ -f license.md ]] && cp license.md $atftempdir/
}
+
+
+
compile_uboot()
{
# not optimal, but extra cleaning before overlayfs_wrapper should keep sources directory clean
@@ -251,7 +256,7 @@ compile_uboot()
[[ ! -f $SRC/.tmp/${uboot_name}.deb ]] && exit_with_error "Building u-boot package failed"
- mv $SRC/.tmp/${uboot_name}.deb $DEST/debs/
+ mv $SRC/.tmp/${uboot_name}.deb ${DEB_STORAGE}/
}
compile_kernel()
@@ -416,16 +421,115 @@ compile_kernel()
if [[ $BUILD_KSRC != no ]]; then
fakeroot dpkg-deb -z0 -b $sources_pkg_dir ${sources_pkg_dir}.deb
- mv ${sources_pkg_dir}.deb $DEST/debs/
+ mv ${sources_pkg_dir}.deb ${DEB_STORAGE}/
fi
rm -rf $sources_pkg_dir
cd ..
# remove firmare image packages here - easier than patching ~40 packaging scripts at once
rm -f linux-firmware-image-*.deb
- mv *.deb $DEST/debs/ || exit_with_error "Failed moving kernel DEBs"
+ mv *.deb ${DEB_STORAGE}/ || exit_with_error "Failed moving kernel DEBs"
}
+
+
+
+compile_firmware()
+{
+ display_alert "Merging and packaging linux firmware" "@host" "info"
+ if [[ $USE_MAINLINE_GOOGLE_MIRROR == yes ]]; then
+ plugin_repo="https://kernel.googlesource.com/pub/scm/linux/kernel/git/firmware/linux-firmware.git"
+ else
+ plugin_repo="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git"
+ fi
+ local plugin_dir="armbian-firmware${FULL}"
+ [[ -d $SRC/cache/sources/$plugin_dir ]] && rm -rf $SRC/cache/sources/$plugin_dir
+ mkdir -p $SRC/cache/sources/$plugin_dir/lib/firmware
+
+ fetch_from_repo "https://github.com/armbian/firmware" "armbian-firmware-git" "branch:master"
+ if [[ -n $FULL ]]; then
+ fetch_from_repo "$plugin_repo" "linux-firmware-git" "branch:master"
+ # cp : create hardlinks
+ cp -alf $SRC/cache/sources/linux-firmware-git/* $SRC/cache/sources/$plugin_dir/lib/firmware/
+ fi
+ # overlay our firmware
+ # cp : create hardlinks
+ cp -alf $SRC/cache/sources/armbian-firmware-git/* $SRC/cache/sources/$plugin_dir/lib/firmware/
+
+ # cleanup what's not needed for sure
+ rm -rf $SRC/cache/sources/$plugin_dir/lib/firmware/{amdgpu,amd-ucode,radeon,nvidia,matrox,.git}
+ cd $SRC/cache/sources/$plugin_dir
+
+ # set up control file
+ mkdir -p DEBIAN
+ cat <<-END > DEBIAN/control
+ Package: armbian-firmware${FULL}
+ Version: $REVISION
+ Architecture: all
+ Maintainer: $MAINTAINER <$MAINTAINERMAIL>
+ Installed-Size: 1
+ Replaces: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, armbian-firmware${REPLACE}
+ Section: kernel
+ Priority: optional
+ Description: Linux firmware${FULL}
+ END
+
+ cd $SRC/cache/sources
+ # pack
+ mv armbian-firmware${FULL} armbian-firmware${FULL}_${REVISION}_all
+ fakeroot dpkg -b armbian-firmware${FULL}_${REVISION}_all >> $DEST/debug/install.log 2>&1
+ mv armbian-firmware${FULL}_${REVISION}_all armbian-firmware${FULL}
+ mv armbian-firmware${FULL}_${REVISION}_all.deb ${DEB_STORAGE}/
+}
+
+
+
+
+compile_armbian-config()
+{
+ local tmpdir=$SRC/.tmp/armbian-config_${REVISION}_all
+
+ display_alert "Building deb" "armbian-config" "info"
+
+ fetch_from_repo "https://github.com/armbian/config" "armbian-config" "branch:master"
+
+ mkdir -p $tmpdir/{DEBIAN,usr/bin/,usr/sbin/,usr/lib/armbian-config/}
+
+ # set up control file
+ cat <<-END > $tmpdir/DEBIAN/control
+ Package: armbian-config
+ Version: $REVISION
+ Architecture: all
+ Maintainer: $MAINTAINER <$MAINTAINERMAIL>
+ Replaces: armbian-bsp
+ Depends: bash, iperf3, psmisc, curl, bc, expect, dialog, iptables, resolvconf, \
+ debconf-utils, unzip, build-essential, html2text, apt-transport-https, html2text, dirmngr, software-properties-common
+ Recommends: armbian-bsp
+ Suggests: libpam-google-authenticator, qrencode, network-manager, sunxi-tools
+ Section: utils
+ Priority: optional
+ Description: Armbian configuration utility
+ END
+
+ install -m 755 $SRC/cache/sources/armbian-config/scripts/tv_grab_file $tmpdir/usr/bin/tv_grab_file
+ install -m 755 $SRC/cache/sources/armbian-config/debian-config $tmpdir/usr/sbin/armbian-config
+ install -m 644 $SRC/cache/sources/armbian-config/debian-config-jobs $tmpdir/usr/lib/armbian-config/jobs.sh
+ install -m 644 $SRC/cache/sources/armbian-config/debian-config-submenu $tmpdir/usr/lib/armbian-config/submenu.sh
+ install -m 644 $SRC/cache/sources/armbian-config/debian-config-functions $tmpdir/usr/lib/armbian-config/functions.sh
+ install -m 644 $SRC/cache/sources/armbian-config/debian-config-functions-network $tmpdir/usr/lib/armbian-config/functions-network.sh
+ install -m 755 $SRC/cache/sources/armbian-config/softy $tmpdir/usr/sbin/softy
+ # fallback to replace armbian-config in BSP
+ ln -sf /usr/sbin/armbian-config $tmpdir/usr/bin/armbian-config
+ ln -sf /usr/sbin/softy $tmpdir/usr/bin/softy
+
+ fakeroot dpkg -b ${tmpdir} >/dev/null
+ mv ${tmpdir}.deb ${DEB_STORAGE}/
+ rm -rf $tmpdir
+}
+
+
+
+
compile_sunxi_tools()
{
# Compile and install only if git commit hash changed
diff --git a/lib/configuration.sh b/lib/configuration.sh
index dcaf59509..89baaf2f4 100644
--- a/lib/configuration.sh
+++ b/lib/configuration.sh
@@ -26,6 +26,16 @@ BUILD_REPOSITORY_URL=$(git remote get-url $(git remote 2>/dev/null) 2>/dev/null)
BUILD_REPOSITORY_COMMIT=$(git describe --match=d_e_a_d_b_e_e_f --always --dirty 2>/dev/null)
ROOTFS_CACHE_MAX=30 # max number of rootfs cache, older ones will be cleaned up
+if [[ $BETA == yes ]]; then
+ DEB_STORAGE=$DEST/debs-beta
+ REPO_STORAGE=$DEST/repository-beta
+ REPO_CONFIG="aptly-beta.conf"
+else
+ DEB_STORAGE=$DEST/debs
+ REPO_STORAGE=$DEST/repository
+ REPO_CONFIG="aptly.conf"
+fi
+
# TODO: fixed name can't be used for parallel image building
ROOT_MAPPER="armbian-root"
@@ -145,21 +155,32 @@ DEBOOTSTRAP_LIST="locales gnupg ifupdown apt-utils apt-transport-https ca-certif
DEBOOTSTRAP_LIST=$(echo $DEBOOTSTRAP_LIST | sed -e 's,\\[trn],,g')
-# Essential packages
-PACKAGE_LIST="bc bridge-utils build-essential cpufrequtils device-tree-compiler figlet fbset fping \
- iw fake-hwclock wpasupplicant psmisc ntp parted sudo curl linux-base dialog crda \
- wireless-regdb ncurses-term python3-apt sysfsutils toilet u-boot-tools unattended-upgrades \
- usbutils wireless-tools console-setup unicode-data openssh-server initramfs-tools \
- ca-certificates resolvconf expect iptables automake nocache debconf-utils html2text \
- bison flex libwrap0-dev libssl-dev libnl-3-dev libnl-genl-3-dev wget keyboard-configuration"
+# For minimal build different set of packages is needed
+# Essential packages for minimal build
+PACKAGE_LIST="bc cpufrequtils device-tree-compiler fping fake-hwclock psmisc chrony parted dialog \
+ ncurses-term sysfsutils toilet figlet u-boot-tools usbutils openssh-server \
+ nocache debconf-utils"
+
+# Non-essential packages for minimal build
+PACKAGE_LIST_ADDITIONAL="network-manager wireless-tools lsof htop mmc-utils wget nano sysstat net-tools resolvconf"
+
+if [[ "$BUILD_MINIMAL" != "yes" ]]; then
+ # Essential packages
+ PACKAGE_LIST="$PACKAGE_LIST bridge-utils build-essential fbset \
+ iw wpasupplicant sudo curl linux-base crda \
+ wireless-regdb python3-apt unattended-upgrades \
+ console-setup unicode-data initramfs-tools \
+ ca-certificates expect iptables automake html2text \
+ bison flex libwrap0-dev libssl-dev libnl-3-dev libnl-genl-3-dev keyboard-configuration"
-# Non-essential packages
-PACKAGE_LIST_ADDITIONAL="armbian-firmware alsa-utils btrfs-tools dosfstools iotop iozone3 stress screen \
- ntfs-3g vim pciutils evtest htop pv lsof libfuse2 libdigest-sha-perl \
- libproc-processtable-perl aptitude dnsutils f3 haveged hdparm rfkill vlan sysstat bash-completion \
- hostapd git ethtool network-manager unzip ifenslave command-not-found libpam-systemd iperf3 nano \
- software-properties-common libnss-myhostname f2fs-tools avahi-autoipd iputils-arping qrencode mmc-utils sunxi-tools"
+ # Non-essential packages
+ PACKAGE_LIST_ADDITIONAL="$PACKAGE_LIST_ADDITIONAL alsa-utils btrfs-tools dosfstools iotop iozone3 stress screen \
+ ntfs-3g vim pciutils evtest pv libfuse2 libdigest-sha-perl \
+ libproc-processtable-perl aptitude dnsutils f3 haveged hdparm rfkill vlan bash-completion \
+ hostapd git ethtool unzip ifenslave command-not-found libpam-systemd iperf3 \
+ software-properties-common libnss-myhostname f2fs-tools avahi-autoipd iputils-arping qrencode sunxi-tools"
+fi
# Dependent desktop packages
@@ -167,26 +188,15 @@ PACKAGE_LIST_DESKTOP="xserver-xorg xserver-xorg-video-fbdev gvfs-backends gvfs-f
x11-xserver-utils xfce4 lxtask xfce4-terminal thunar-volman gtk2-engines gtk2-engines-murrine gtk2-engines-pixbuf \
libgtk2.0-bin network-manager-gnome xfce4-notifyd gnome-keyring gcr libgck-1-0 p11-kit pasystray pavucontrol \
pulseaudio pavumeter bluez bluez-tools pulseaudio-module-bluetooth blueman libpam-gnome-keyring \
- libgl1-mesa-dri policykit-1 profile-sync-daemon gnome-orca numix-gtk-theme synaptic onboard lightdm lightdm-gtk-greeter"
+ libgl1-mesa-dri policykit-1 profile-sync-daemon gnome-orca numix-gtk-theme synaptic apt-xapian-index onboard lightdm lightdm-gtk-greeter"
# Recommended desktop packages
PACKAGE_LIST_DESKTOP_RECOMMENDS="mirage galculator hexchat xfce4-screenshooter network-manager-openvpn-gnome mpv fbi \
cups-pk-helper cups geany atril xarchiver"
-
-# For minimal build different set of packages is needed
-if [[ $BUILD_MINIMAL == yes ]]; then
-
- # Essential packages for minimal build
- PACKAGE_LIST="bc cpufrequtils device-tree-compiler fping fake-hwclock psmisc ntp parted dialog \
- ncurses-term sysfsutils toilet figlet u-boot-tools usbutils openssh-server \
- nocache debconf-utils"
-
- # Non-essential packages for minimal build
- PACKAGE_LIST_ADDITIONAL="network-manager wireless-tools lsof htop mmc-utils wget armbian-firmware nano sysstat net-tools"
-
-fi
+# Full desktop packages
+PACKAGE_LIST_DESKTOP_FULL="libreoffice libreoffice-style-tango meld remmina thunderbird kazam avahi-daemon transmission"
# Release specific packages
case $RELEASE in
@@ -217,7 +227,7 @@ case $RELEASE in
bionic)
DEBOOTSTRAP_COMPONENTS="main,universe"
- [[ -z $BUILD_MINIMAL || $BUILD_MINIMAL == no ]] && PACKAGE_LIST_RELEASE="man-db kbd net-tools gnupg2 dirmngr"
+ [[ -z $BUILD_MINIMAL || $BUILD_MINIMAL == no ]] && PACKAGE_LIST_RELEASE="man-db kbd net-tools gnupg2 dirmngr networkd-dispatcher"
PACKAGE_LIST_DESKTOP+=" xserver-xorg-input-all paprefs dbus-x11 libgnome2-perl pulseaudio-module-gconf"
PACKAGE_LIST_DESKTOP_RECOMMENDS+=" chromium-browser system-config-printer-common system-config-printer \
language-selector-gnome leafpad"
@@ -225,14 +235,14 @@ case $RELEASE in
buster)
DEBOOTSTRAP_COMPONENTS="main"
- [[ -z $BUILD_MINIMAL || $BUILD_MINIMAL == no ]] && PACKAGE_LIST_RELEASE="man-db kbd net-tools gnupg2 dirmngr"
+ [[ -z $BUILD_MINIMAL || $BUILD_MINIMAL == no ]] && PACKAGE_LIST_RELEASE="man-db kbd net-tools gnupg2 dirmngr networkd-dispatcher"
PACKAGE_LIST_DESKTOP+=" paprefs dbus-x11 numix-icon-theme"
PACKAGE_LIST_DESKTOP_RECOMMENDS+=" chromium system-config-printer-common system-config-printer"
;;
disco)
DEBOOTSTRAP_COMPONENTS="main,universe"
- [[ -z $BUILD_MINIMAL || $BUILD_MINIMAL == no ]] && PACKAGE_LIST_RELEASE="man-db kbd net-tools gnupg2 dirmngr"
+ [[ -z $BUILD_MINIMAL || $BUILD_MINIMAL == no ]] && PACKAGE_LIST_RELEASE="man-db kbd net-tools gnupg2 dirmngr networkd-dispatcher"
PACKAGE_LIST_DESKTOP+=" xserver-xorg-input-all paprefs dbus-x11 pulseaudio-module-gsettings"
PACKAGE_LIST_DESKTOP_RECOMMENDS+=" chromium-browser system-config-printer-common system-config-printer \
language-selector-gnome"
diff --git a/lib/debootstrap.sh b/lib/debootstrap.sh
index 3a9c3f41a..00eda4497 100644
--- a/lib/debootstrap.sh
+++ b/lib/debootstrap.sh
@@ -52,9 +52,6 @@ debootstrap_ng()
install_distribution_specific
install_common
- # install additional applications
- [[ $EXTERNAL == yes ]] && install_external_applications
-
# install locally built packages
[[ $EXTERNAL_NEW == compile ]] && chroot_installpackages_local
@@ -84,8 +81,13 @@ debootstrap_ng()
fi
# stage: unmount tmpfs
- [[ $use_tmpfs = yes ]] && umount $SDCARD
-
+ if [[ $use_tmpfs = yes ]]; then
+ while grep -qs '$SDCARD' /proc/mounts
+ do
+ umount $SDCARD
+ sleep 5
+ done
+ fi
rm -rf $SDCARD
# remove exit trap
@@ -230,6 +232,12 @@ create_rootfs_cache()
# create list of installed packages for debug purposes
chroot $SDCARD /bin/bash -c "dpkg --get-selections" | grep -v deinstall | awk '{print $1}' | cut -f1 -d':' > ${cache_fname}.list 2>&1
+ # creating xapian index that synaptic runs faster
+ if [[ $BUILD_DESKTOP == yes ]]; then
+ display_alert "Recreating Synaptic search index" "Please wait" "info"
+ chroot $SDCARD /bin/bash -c "/usr/sbin/update-apt-xapian-index -u"
+ fi
+
# this is needed for the build process later since resolvconf generated file in /run is not saved
rm $SDCARD/etc/resolv.conf
echo "nameserver $NAMESERVER" >> $SDCARD/etc/resolv.conf
@@ -252,7 +260,7 @@ create_rootfs_cache()
fi
# used for internal purposes. Faster rootfs cache rebuilding
- if [[ -n "$ROOT_FS_CREATE_ONLY" ]]; then
+ if [[ -n "$ROOT_FS_CREATE_ONLY" ]]; then
[[ $use_tmpfs = yes ]] && umount $SDCARD
rm -rf $SDCARD
# remove exit trap
@@ -579,10 +587,18 @@ create_image()
[[ $ROOTFS_TYPE != nfs ]] && umount -l $MOUNT
[[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose $ROOT_MAPPER
+ # to make sure its unmounted
+ while grep -Eq '(${MOUNT}|${DESTIMG})' /proc/mounts
+ do
+ display_alert "Unmounting" "${MOUNT}" "info"
+ sleep 5
+ done
+
losetup -d $LOOP
rm -rf --one-file-system $DESTIMG $MOUNT
+
mkdir -p $DESTIMG
- fingerprint_image "$DESTIMG/${version}.txt" "${version}"
+ fingerprint_image "$DESTIMG/${version}.img.txt" "${version}"
mv ${SDCARD}.raw $DESTIMG/${version}.img
if [[ $BUILD_ALL != yes ]]; then
@@ -615,7 +631,7 @@ create_image()
# compress image
cd $DESTIMG
display_alert "Compressing" "$DEST/images/${version}.7z" "info"
- 7za a -t7z -bd -m0=lzma2 -mx=3 -mfb=64 -md=32m -ms=on $DEST/images/${version}.7z ${version}.key ${version}.img* armbian.txt >/dev/null 2>&1
+ 7za a -t7z -bd -m0=lzma2 -mx=3 -mfb=64 -md=32m -ms=on $DEST/images/${version}.7z ${version}.key ${version}.img* ${version}.img.txt >/dev/null 2>&1
cd ..
fi
@@ -624,7 +640,7 @@ create_image()
pigz < $DESTIMG/${version}.img > $DEST/images/${version}.img.gz
fi
- mv $DESTIMG/${version}.txt $DEST/images/${version}.txt || exit 1
+ mv $DESTIMG/${version}.img.txt $DEST/images/${version}.img.txt || exit 1
mv $DESTIMG/${version}.img $DEST/images/${version}.img || exit 1
rm -rf $DESTIMG
fi
diff --git a/lib/desktop.sh b/lib/desktop.sh
index d9dd312c7..6663a4986 100644
--- a/lib/desktop.sh
+++ b/lib/desktop.sh
@@ -108,8 +108,8 @@ create_desktop_package ()
# create board DEB file
display_alert "Building desktop package" "${CHOSEN_DESKTOP}_${REVISION}_all" "info"
fakeroot dpkg-deb -b "${destination}" "${destination}.deb" >/dev/null
- mkdir -p "${DEST}/debs/${RELEASE}"
- mv "${destination}.deb" "${DEST}/debs/${RELEASE}"
+ mkdir -p "${DEB_STORAGE}/${RELEASE}"
+ mv "${destination}.deb" "${DEB_STORAGE}/${RELEASE}"
# cleanup
rm -rf "${destination}"
}
@@ -118,6 +118,7 @@ desktop_postinstall ()
{
# disable display manager for first run
chroot "${SDCARD}" /bin/bash -c "systemctl --no-reload disable lightdm.service >/dev/null 2>&1"
+ [[ ${FULL_DESKTOP} == yes ]] && chroot "${SDCARD}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive apt-get -yqq --no-install-recommends install $PACKAGE_LIST_DESKTOP_FULL" >> "${DEST}"/debug/install.log
# Compile Turbo Frame buffer for sunxi
if [[ $LINUXFAMILY == sun* && $BRANCH == default ]]; then
diff --git a/lib/distributions.sh b/lib/distributions.sh
index 9ef75762d..8e66a7991 100644
--- a/lib/distributions.sh
+++ b/lib/distributions.sh
@@ -177,34 +177,38 @@ install_common()
EOF
# install kernel and u-boot packages
- install_deb_chroot "$DEST/debs/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb"
- install_deb_chroot "$DEST/debs/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb"
+ install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb"
+ install_deb_chroot "${DEB_STORAGE}/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb"
if [[ $BUILD_DESKTOP == yes ]]; then
- install_deb_chroot "$DEST/debs/$RELEASE/armbian-${RELEASE}-desktop_${REVISION}_all.deb"
- # install display manager
+ install_deb_chroot "${DEB_STORAGE}/$RELEASE/armbian-${RELEASE}-desktop_${REVISION}_all.deb"
+ # install display manager and PACKAGE_LIST_DESKTOP_FULL packages if enabled per board
desktop_postinstall
fi
if [[ $INSTALL_HEADERS == yes ]]; then
- install_deb_chroot "$DEST/debs/${CHOSEN_KERNEL/image/headers}_${REVISION}_${ARCH}.deb"
+ install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KERNEL/image/headers}_${REVISION}_${ARCH}.deb"
fi
- if [[ -f $DEST/debs/armbian-firmware_${REVISION}_${ARCH}.deb ]]; then
- install_deb_chroot "$DEST/debs/armbian-firmware_${REVISION}_${ARCH}.deb"
+ if [[ $BUILD_MINIMAL != yes ]]; then
+ install_deb_chroot "${DEB_STORAGE}/armbian-config_${REVISION}_all.deb"
fi
- if [[ -f $DEST/debs/${CHOSEN_KERNEL/image/dtb}_${REVISION}_${ARCH}.deb ]]; then
- install_deb_chroot "$DEST/debs/${CHOSEN_KERNEL/image/dtb}_${REVISION}_${ARCH}.deb"
+ if [[ -f ${DEB_STORAGE}/armbian-firmware_${REVISION}_all.deb ]]; then
+ install_deb_chroot "${DEB_STORAGE}/armbian-firmware_${REVISION}_all.deb"
fi
- if [[ -f $DEST/debs/${CHOSEN_KSRC}_${REVISION}_all.deb && $INSTALL_KSRC == yes ]]; then
- install_deb_chroot "$DEST/debs/${CHOSEN_KSRC}_${REVISION}_all.deb"
+ if [[ -f ${DEB_STORAGE}/${CHOSEN_KERNEL/image/dtb}_${REVISION}_${ARCH}.deb ]]; then
+ install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KERNEL/image/dtb}_${REVISION}_${ARCH}.deb"
+ fi
+
+ if [[ -f ${DEB_STORAGE}/${CHOSEN_KSRC}_${REVISION}_all.deb && $INSTALL_KSRC == yes ]]; then
+ install_deb_chroot "${DEB_STORAGE}/${CHOSEN_KSRC}_${REVISION}_all.deb"
fi
# install board support package
- install_deb_chroot "$DEST/debs/$RELEASE/${CHOSEN_ROOTFS}_${REVISION}_${ARCH}.deb"
+ install_deb_chroot "${DEB_STORAGE}/$RELEASE/${CHOSEN_ROOTFS}_${REVISION}_${ARCH}.deb"
# freeze armbian packages
if [[ $BSPFREEZE == yes ]]; then
@@ -300,6 +304,10 @@ install_common()
# remove network manager defaults to handle eth by default
rm -f "${SDCARD}"/usr/lib/NetworkManager/conf.d/10-globally-managed-devices.conf
+ # avahi daemon defaults if exists
+ [[ -f "${SDCARD}"/usr/share/doc/avahi-daemon/examples/sftp-ssh.service ]] && cp "${SDCARD}"/usr/share/doc/avahi-daemon/examples/sftp-ssh.service "${SDCARD}"/etc/avahi/services/
+ [[ -f "${SDCARD}"/usr/share/doc/avahi-daemon/examples/ssh.service ]] && cp "${SDCARD}"/usr/share/doc/avahi-daemon/examples/ssh.service "${SDCARD}"/etc/avahi/services/
+
# Just regular DNS and maintain /etc/resolv.conf as a file
sed "/dns/d" -i "${SDCARD}"/etc/NetworkManager/NetworkManager.conf
sed "s/\[main\]/\[main\]\ndns=default\nrc-manager=file/g" -i "${SDCARD}"/etc/NetworkManager/NetworkManager.conf
diff --git a/lib/general.sh b/lib/general.sh
index ab143b38d..2c2fc366b 100644
--- a/lib/general.sh
+++ b/lib/general.sh
@@ -16,6 +16,7 @@
# display_alert
# fingerprint_image
# addtorepo
+# repo-remove-old-packages
# prepare_host
# webseed
# download_and_verify
@@ -33,31 +34,31 @@
cleaning()
{
case $1 in
- debs) # delete output/debs for current branch and family
- if [[ -d $DEST/debs ]]; then
- display_alert "Cleaning output/debs for" "$BOARD $BRANCH" "info"
+ debs) # delete ${DEB_STORAGE} for current branch and family
+ if [[ -d ${DEB_STORAGE} ]]; then
+ display_alert "Cleaning ${DEB_STORAGE} for" "$BOARD $BRANCH" "info"
# easier than dealing with variable expansion and escaping dashes in file names
- find $DEST/debs -name "${CHOSEN_UBOOT}_*.deb" -delete
- find $DEST/debs \( -name "${CHOSEN_KERNEL}_*.deb" -o \
+ find ${DEB_STORAGE} -name "${CHOSEN_UBOOT}_*.deb" -delete
+ find ${DEB_STORAGE} \( -name "${CHOSEN_KERNEL}_*.deb" -o \
-name "armbian-*.deb" -o \
-name "${CHOSEN_KERNEL/image/dtb}_*.deb" -o \
-name "${CHOSEN_KERNEL/image/headers}_*.deb" -o \
-name "${CHOSEN_KERNEL/image/source}_*.deb" -o \
-name "${CHOSEN_KERNEL/image/firmware-image}_*.deb" \) -delete
- [[ -n $RELEASE ]] && rm -f $DEST/debs/$RELEASE/${CHOSEN_ROOTFS}_*.deb
- [[ -n $RELEASE ]] && rm -f $DEST/debs/$RELEASE/armbian-desktop-${RELEASE}_*.deb
+ [[ -n $RELEASE ]] && rm -f ${DEB_STORAGE}/$RELEASE/${CHOSEN_ROOTFS}_*.deb
+ [[ -n $RELEASE ]] && rm -f ${DEB_STORAGE}/$RELEASE/armbian-desktop-${RELEASE}_*.deb
fi
;;
- extras) # delete output/debs/extra/$RELEASE for all architectures
- if [[ -n $RELEASE && -d $DEST/debs/extra/$RELEASE ]]; then
- display_alert "Cleaning output/debs/extra for" "$RELEASE" "info"
- rm -rf $DEST/debs/extra/$RELEASE
+ extras) # delete ${DEB_STORAGE}/extra/$RELEASE for all architectures
+ if [[ -n $RELEASE && -d ${DEB_STORAGE}/extra/$RELEASE ]]; then
+ display_alert "Cleaning ${DEB_STORAGE}/extra for" "$RELEASE" "info"
+ rm -rf ${DEB_STORAGE}/extra/$RELEASE
fi
;;
alldebs) # delete output/debs
- [[ -d $DEST/debs ]] && display_alert "Cleaning" "output/debs" "info" && rm -rf $DEST/debs/*
+ [[ -d ${DEB_STORAGE} ]] && display_alert "Cleaning" "${DEB_STORAGE}" "info" && rm -rf ${DEB_STORAGE}/*
;;
cache) # delete output/cache
@@ -171,9 +172,9 @@ create_sources_list()
echo "deb http://apt.armbian.com $RELEASE main ${RELEASE}-utils ${RELEASE}-desktop" > $SDCARD/etc/apt/sources.list.d/armbian.list
fi
+ display_alert "Add armbian repository and install key" "/etc/apt/sources.list.d/armbian.list" "info"
cp $SRC/config/armbian.key $SDCARD
- eval 'chroot $SDCARD /bin/bash -c "cat armbian.key | apt-key add -"' \
- ${OUTPUT_VERYSILENT:+' >/dev/null 2>/dev/null'}
+ chroot $SDCARD /bin/bash -c "cat armbian.key | apt-key add - > /dev/null 2>&1"
rm $SDCARD/armbian.key
}
@@ -393,14 +394,40 @@ fingerprint_image()
EOF
}
+
+
+
+adding_packages()
+{
+# add deb files to repository if they are not already there
+
+ display_alert "Checking and adding to repository $release" "$3" "ext"
+ for f in ${DEB_STORAGE}$2/*.deb
+ do
+ local name=$(dpkg-deb -I $f | grep Package | awk '{print $2}')
+ local version=$(dpkg-deb -I $f | grep Version | awk '{print $2}')
+ local arch=$(dpkg-deb -I $f | grep Architecture | awk '{print $2}')
+ # add if not already there
+ aptly repo search -architectures=$arch -config=${SCRIPTPATH}config/${REPO_CONFIG} $1 'Name (% '$name'), $Version (='$version'), $Architecture (='$arch')' &>/dev/null
+ if [[ $? -ne 0 ]]; then
+ display_alert "Adding" "$name" "info"
+ aptly repo add -force-replace=true -config=${SCRIPTPATH}config/${REPO_CONFIG} $release ${f} &>/dev/null
+ fi
+ done
+
+}
+
+
+
+
addtorepo()
{
-# add all deb files to repository
+# create repository
# parameter "remove" dumps all and creates new
# parameter "delete" remove incoming directory if publishing is succesful
# function: cycle trough distributions
- local distributions=("jessie" "xenial" "stretch" "bionic" "buster" "disco")
+ local distributions=("xenial" "stretch" "bionic" "buster" "disco")
local errors=0
for release in "${distributions[@]}"; do
@@ -408,113 +435,72 @@ addtorepo()
local forceoverwrite=""
# let's drop from publish if exits
- if [[ -n $(aptly publish list -config=${SCRIPTPATH}config/aptly.conf -raw | awk '{print $(NF)}' | grep $release) ]]; then
- aptly publish drop -config=${SCRIPTPATH}config/aptly.conf $release > /dev/null 2>&1
+ if [[ -n $(aptly publish list -config=${SCRIPTPATH}config/${REPO_CONFIG} -raw | awk '{print $(NF)}' | grep $release) ]]; then
+ aptly publish drop -config=${SCRIPTPATH}config/${REPO_CONFIG} $release > /dev/null 2>&1
fi
# create local repository if not exist
- if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/aptly.conf -raw | awk '{print $(NF)}' | grep $release) ]]; then
+ if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/${REPO_CONFIG} -raw | awk '{print $(NF)}' | grep $release) ]]; then
display_alert "Creating section" "$release" "info"
- aptly repo create -config=${SCRIPTPATH}config/aptly.conf -distribution=$release -component="main" \
- -comment="Armbian main repository" ${release}
+ aptly repo create -config=${SCRIPTPATH}config/${REPO_CONFIG} -distribution=$release -component="main" \
+ -comment="Armbian main repository" ${release} >/dev/null
fi
- if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/aptly.conf -raw | awk '{print $(NF)}' | grep "^utils") ]]; then
- aptly repo create -config=${SCRIPTPATH}config/aptly.conf -distribution=$release -component="utils" \
- -comment="Armbian utilities (backwards compatibility)" utils
+ if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/${REPO_CONFIG} -raw | awk '{print $(NF)}' | grep "^utils") ]]; then
+ aptly repo create -config=${SCRIPTPATH}config/${REPO_CONFIG} -distribution=$release -component="utils" \
+ -comment="Armbian utilities (backwards compatibility)" utils >/dev/null
fi
- if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/aptly.conf -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
- aptly repo create -config=${SCRIPTPATH}config/aptly.conf -distribution=$release -component="${release}-utils" \
- -comment="Armbian ${release} utilities" ${release}-utils
+ if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/${REPO_CONFIG} -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
+ aptly repo create -config=${SCRIPTPATH}config/${REPO_CONFIG} -distribution=$release -component="${release}-utils" \
+ -comment="Armbian ${release} utilities" ${release}-utils >/dev/null
fi
- if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/aptly.conf -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
- aptly repo create -config=${SCRIPTPATH}config/aptly.conf -distribution=$release -component="${release}-desktop" \
- -comment="Armbian ${release} desktop" ${release}-desktop
+ if [[ -z $(aptly repo list -config=${SCRIPTPATH}config/${REPO_CONFIG} -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
+ aptly repo create -config=${SCRIPTPATH}config/${REPO_CONFIG} -distribution=$release -component="${release}-desktop" \
+ -comment="Armbian ${release} desktop" ${release}-desktop >/dev/null
fi
# adding main
- if find $POT -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
- display_alert "Adding to repository $release" "main" "ext"
- aptly repo add -config=${SCRIPTPATH}config/aptly.conf $release ${POT}*.deb
- if [[ $? -ne 0 ]]; then
- # try again with
- display_alert "Adding by force to repository $release" "main" "ext"
- aptly repo add -force-replace=true -config=${SCRIPTPATH}config/aptly.conf $release ${POT}*.deb
- if [[ $? -eq 0 ]]; then forceoverwrite="-force-overwrite"; else errors=$((errors+1)); fi
- fi
+ if find ${DEB_STORAGE}/ -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
+ adding_packages "$release" "" "main"
else
- display_alert "Not adding $release" "main" "wrn"
+ aptly repo add -config=${SCRIPTPATH}config/${REPO_CONFIG} $release ${SCRIPTPATH}config/templates/example.deb >/dev/null
fi
local COMPONENTS="main"
# adding main distribution packages
- if find ${POT}${release} -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
- display_alert "Adding to repository $release" "root" "ext"
- aptly repo add -config=${SCRIPTPATH}config/aptly.conf $release ${POT}${release}/*.deb
- if [[ $? -ne 0 ]]; then
- # try again with
- display_alert "Adding by force to repository $release" "root" "ext"
- aptly repo add -force-replace=true -config=${SCRIPTPATH}config/aptly.conf $release ${POT}${release}/*.deb
- if [[ $? -eq 0 ]]; then forceoverwrite="-force-overwrite"; else errors=$((errors+1));fi
- fi
+ if find ${DEB_STORAGE}/${release} -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
+ adding_packages "$release" "/${release}" "release"
else
- display_alert "Not adding $release" "root" "wrn"
+ # workaround - add dummy package to not trigger error
+ aptly repo add -config=${SCRIPTPATH}config/${REPO_CONFIG} $release ${SCRIPTPATH}config/templates/example.deb >/dev/null
fi
- # adding old utils and new jessie-utils for backwards compatibility with older images
- if find ${POT}extra/jessie-utils -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
- display_alert "Adding to repository $release" "utils" "ext"
- aptly repo add -config=${SCRIPTPATH}config/aptly.conf "utils" ${POT}extra/jessie-utils/*.deb
- if [[ $? -ne 0 ]]; then
- # try again with
- display_alert "Adding by force to repository $release" "utils" "ext"
- aptly repo add -force-replace=true -config=${SCRIPTPATH}config/aptly.conf "utils" ${POT}extra/jessie-utils/*.deb
- if [[ $? -eq 0 ]]; then forceoverwrite="-force-overwrite"; else errors=$((errors+1));fi
- fi
- else
- display_alert "Not adding $release" "utils" "wrn"
- fi
- COMPONENTS="${COMPONENTS} utils"
-
# adding release-specific utils
- if find ${POT}extra/${release}-utils -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
- display_alert "Adding to repository $release" "${release}-utils" "ext"
- aptly repo add -config=${SCRIPTPATH}config/aptly.conf "${release}-utils" ${POT}extra/${release}-utils/*.deb
- if [[ $? -ne 0 ]]; then
- # try again with
- display_alert "Adding by force to repository $release" "${release}-utils" "ext"
- aptly repo add -force-replace=true -config=${SCRIPTPATH}config/aptly.conf "${release}-utils" ${POT}extra/${release}-utils/*.deb
- if [[ $? -eq 0 ]]; then forceoverwrite="-force-overwrite"; else errors=$((errors+1));fi
- fi
+ if find ${DEB_STORAGE}/extra/${release}-utils -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
+ adding_packages "${release}-utils" "/extra/${release}-utils" "release utils"
else
- display_alert "Not adding $release" "${release}-utils" "wrn"
+ aptly repo add -config=${SCRIPTPATH}config/${REPO_CONFIG} "${release}-utils" ${SCRIPTPATH}config/templates/example.deb >/dev/null
fi
COMPONENTS="${COMPONENTS} ${release}-utils"
# adding desktop
- if find ${POT}extra/${release}-desktop -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
- display_alert "Adding to repository $release" "desktop" "ext"
- aptly repo add -config=${SCRIPTPATH}config/aptly.conf "${release}-desktop" ${POT}extra/${release}-desktop/*.deb
- if [[ $? -ne 0 ]]; then
- # try again with
- display_alert "Adding by force to repository $release" "desktop" "ext"
- aptly repo add -force-replace=true -config=${SCRIPTPATH}config/aptly.conf "${release}-desktop" ${POT}extra/${release}-desktop/*.deb
- if [[ $? -eq 0 ]]; then forceoverwrite="-force-overwrite"; else errors=$((errors+1));fi
- fi
+ if find ${DEB_STORAGE}/extra/${release}-desktop -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
+ adding_packages "${release}-desktop" "/extra/${release}-desktop" "desktop"
else
- display_alert "Not adding $release" "desktop" "wrn"
+ # workaround - add dummy package to not trigger error
+ aptly repo add -config=${SCRIPTPATH}config/${REPO_CONFIG} "${release}-desktop" ${SCRIPTPATH}config/templates/example.deb >/dev/null
fi
COMPONENTS="${COMPONENTS} ${release}-desktop"
- local mainnum=$(aptly repo show -with-packages -config=${SCRIPTPATH}config/aptly.conf $release | grep "Number of packages" | awk '{print $NF}')
- local utilnum=$(aptly repo show -with-packages -config=${SCRIPTPATH}config/aptly.conf ${release}-desktop | grep "Number of packages" | awk '{print $NF}')
- local desknum=$(aptly repo show -with-packages -config=${SCRIPTPATH}config/aptly.conf ${release}-utils | grep "Number of packages" | awk '{print $NF}')
+ local mainnum=$(aptly repo show -with-packages -config=${SCRIPTPATH}config/${REPO_CONFIG} $release | grep "Number of packages" | awk '{print $NF}')
+ local utilnum=$(aptly repo show -with-packages -config=${SCRIPTPATH}config/${REPO_CONFIG} ${release}-desktop | grep "Number of packages" | awk '{print $NF}')
+ local desknum=$(aptly repo show -with-packages -config=${SCRIPTPATH}config/${REPO_CONFIG} ${release}-utils | grep "Number of packages" | awk '{print $NF}')
if [ $mainnum -gt 0 ] && [ $utilnum -gt 0 ] && [ $desknum -gt 0 ]; then
# publish
- aptly publish $forceoverwrite -passphrase=$GPG_PASS -gpg-provider=internal -origin=Armbian -label=Armbian -config=${SCRIPTPATH}config/aptly.conf -component=${COMPONENTS// /,} \
- --distribution=$release repo $release ${COMPONENTS//main/}
+ aptly publish $forceoverwrite -passphrase=$GPG_PASS -origin=Armbian -label=Armbian -config=${SCRIPTPATH}config/${REPO_CONFIG} -component=${COMPONENTS// /,} \
+ --distribution=$release repo $release ${COMPONENTS//main/} >/dev/null
if [[ $? -ne 0 ]]; then
display_alert "Publishing failed" "$release" "err"
errors=$((errors+1))
@@ -527,15 +513,20 @@ addtorepo()
done
+ # cleanup
+ display_alert "Cleaning repository" "${DEB_STORAGE}" "info"
+ aptly db cleanup -config=${SCRIPTPATH}config/${REPO_CONFIG}
+
# display what we have
+ echo ""
display_alert "List of local repos" "local" "info"
- (aptly repo list -config=${SCRIPTPATH}config/aptly.conf) | egrep packages
+ (aptly repo list -config=${SCRIPTPATH}config/${REPO_CONFIG}) | egrep packages
# remove debs if no errors found
if [[ $errors -eq 0 ]]; then
if [[ "$2" == "delete" ]]; then
display_alert "Purging incoming debs" "all" "ext"
- find ${POT} -name "*.deb" -type f -delete
+ find ${DEB_STORAGE} -name "*.deb" -type f -delete
fi
else
display_alert "There were some problems $err_txt" "leaving incoming directory intact" "err"
@@ -543,6 +534,100 @@ addtorepo()
}
+
+
+
+repo-manipulate() {
+ local DISTROS=("xenial" "stretch" "bionic" "buster" "disco")
+ case $@ in
+ serve)
+ # display repository content
+ display_alert "Serving content" "common utils" "ext"
+ aptly serve -listen=$(ip -f inet addr | grep -Po 'inet \K[\d.]+' | grep -v 127.0.0.1):8080 -config="${SCRIPTPATH}"config/${REPO_CONFIG}
+ exit 0
+ ;;
+ show)
+ # display repository content
+ for release in "${DISTROS[@]}"; do
+ display_alert "Displaying repository contents for" "$release" "ext"
+ aptly repo show -with-packages -config="${SCRIPTPATH}"config/${REPO_CONFIG} "${release}" | tail -n +7
+ aptly repo show -with-packages -config="${SCRIPTPATH}"config/${REPO_CONFIG} "${release}-desktop" | tail -n +7
+ done
+ display_alert "Displaying repository contents for" "common utils" "ext"
+ aptly repo show -with-packages -config="${SCRIPTPATH}"config/${REPO_CONFIG} utils | tail -n +7
+ echo "done."
+ exit 0
+ ;;
+ update)
+ # display full help test
+ # run repository update
+ addtorepo "update" ""
+ # add a key to repo
+ cp "${SCRIPTPATH}"config/armbian.key "${REPO_STORAGE}"/public/
+ exit 0
+ ;;
+ purge)
+ for release in "${DISTROS[@]}"; do
+ repo-remove-old-packages "$release" "armhf" "3"
+ repo-remove-old-packages "$release" "arm64" "3"
+ repo-remove-old-packages "$release" "all" "3"
+ aptly -config="${SCRIPTPATH}"config/${REPO_CONFIG} -passphrase="${GPG_PASS}" publish update "${release}" > /dev/null 2>&1
+ done
+ exit 0
+ ;;
+ purgesource)
+ for release in "${DISTROS[@]}"; do
+ aptly repo remove -config=${SCRIPTPATH}config/${REPO_CONFIG} ${release} 'Name (% *-source*)'
+ aptly -config="${SCRIPTPATH}"config/${REPO_CONFIG} -passphrase="${GPG_PASS}" publish update "${release}" > /dev/null 2>&1
+ done
+ aptly db cleanup -config=${SCRIPTPATH}config/${REPO_CONFIG} > /dev/null 2>&1
+ exit 0
+ ;;
+ *)
+ echo -e "Usage: repository show | serve | create | update | purge\n"
+ echo -e "\n show = display repository content"
+ echo -e "\n serve = publish your repositories on current server over HTTP"
+ echo -e "\n update = updating repository"
+ echo -e "\n purge = removes all but last 5 versions\n\n"
+ exit 0
+ ;;
+ esac
+} # ParseOptions
+
+
+
+
+# Removes old packages in the received repo
+#
+# $1: Repository
+# $2: Architecture
+# $3: Amount of packages to keep
+repo-remove-old-packages() {
+ local repo=$1
+ local arch=$2
+ local keep=$3
+
+ for pkg in $(aptly repo search -config="${SCRIPTPATH}"config/${REPO_CONFIG} "${repo}" "Architecture ($arch)" | grep -v "ERROR: no results" | sort -rV); do
+ local pkg_name
+ pkg_name=$(echo "${pkg}" | cut -d_ -f1)
+ if [ "$pkg_name" != "$cur_pkg" ]; then
+ local count=0
+ local deleted=""
+ local cur_pkg="$pkg_name"
+ fi
+ test -n "$deleted" && continue
+ ((count+=1))
+ if [[ $count -gt $keep ]]; then
+ pkg_version=$(echo "${pkg}" | cut -d_ -f2)
+ aptly repo remove -config="${SCRIPTPATH}"config/${REPO_CONFIG} "${repo}" "Name ($pkg_name), Version (<= $pkg_version)"
+ deleted='yes'
+ fi
+ done
+}
+
+
+
+
# prepare_host
#
# * checks and installs necessary packages
@@ -692,7 +777,7 @@ prepare_host()
find $SRC/output $USERPATCHES_PATH -type d ! -group sudo -exec chgrp --quiet sudo {} \;
find $SRC/output $USERPATCHES_PATH -type d ! -perm -g+w,g+s -exec chmod --quiet g+w,g+s {} \;
fi
- mkdir -p $DEST/debs/extra $DEST/{config,debug,patch} $USERPATCHES_PATH/overlay $SRC/cache/{sources,toolchains,utility,rootfs} $SRC/.tmp
+ mkdir -p $DEST/debs-beta/extra $DEST/debs/extra $DEST/{config,debug,patch} $USERPATCHES_PATH/overlay $SRC/cache/{sources,toolchains,utility,rootfs} $SRC/.tmp
display_alert "Checking for external GCC compilers" "" "info"
# download external Linaro compiler and missing special dependencies since they are needed for certain sources
diff --git a/lib/image-helpers.sh b/lib/image-helpers.sh
index e8217a699..dc9541dfd 100644
--- a/lib/image-helpers.sh
+++ b/lib/image-helpers.sh
@@ -40,10 +40,14 @@ mount_chroot()
umount_chroot()
{
local target=$1
- umount -l "${target}"/dev/pts >/dev/null 2>&1
- umount -l "${target}"/dev >/dev/null 2>&1
- umount -l "${target}"/proc >/dev/null 2>&1
- umount -l "${target}"/sys >/dev/null 2>&1
+ display_alert "Unmounting" "$target" "info"
+ while grep -Eq "${target}.*(dev|proc|sys)" /proc/mounts
+ do
+ umount -l --recursive "${target}"/dev >/dev/null 2>&1
+ umount -l "${target}"/proc >/dev/null 2>&1
+ umount -l "${target}"/sys >/dev/null 2>&1
+ sleep 5
+ done
} #############################################################################
# unmount_on_exit
@@ -77,15 +81,6 @@ check_loop_device()
fi
} #############################################################################
-install_external_applications()
-{
- display_alert "Installing extra applications and drivers" "" "info"
-
- for plugin in "${SRC}"/packages/extras/*.sh; do
- source "${plugin}"
- done
-} #############################################################################
-
# write_uboot
#
# writes u-boot to loop device
@@ -97,7 +92,7 @@ write_uboot()
local loop=$1
display_alert "Writing U-boot bootloader" "$loop" "info"
mkdir -p /tmp/u-boot/
- dpkg -x "${DEST}/debs/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" /tmp/u-boot/
+ dpkg -x "${DEB_STORAGE}/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" /tmp/u-boot/
write_uboot_platform "/tmp/u-boot/usr/lib/${CHOSEN_UBOOT}_${REVISION}_${ARCH}" "$loop"
[[ $? -ne 0 ]] && exit_with_error "U-boot bootloader failed to install" "@host"
rm -r /tmp/u-boot/
@@ -116,7 +111,7 @@ customize_image()
display_alert "Calling image customization script" "customize-image.sh" "info"
chroot "${SDCARD}" /bin/bash -c "/tmp/customize-image.sh $RELEASE $LINUXFAMILY $BOARD $BUILD_DESKTOP"
CUSTOMIZE_IMAGE_RC=$?
- umount -i "${SDCARD}"/tmp/overlay
+ umount -i "${SDCARD}"/tmp/overlay >/dev/null 2>&1
mountpoint -q "${SDCARD}"/tmp/overlay || rm -r "${SDCARD}"/tmp/overlay
if [[ $CUSTOMIZE_IMAGE_RC != 0 ]]; then
exit_with_error "customize-image.sh exited with error (rc: $CUSTOMIZE_IMAGE_RC)"
diff --git a/lib/main.sh b/lib/main.sh
index bacee31a0..ed2004b95 100644
--- a/lib/main.sh
+++ b/lib/main.sh
@@ -30,8 +30,10 @@ DEST=$SRC/output
[[ -n $COLUMNS ]] && stty cols $COLUMNS
[[ -n $LINES ]] && stty rows $LINES
-TTY_X=$(($(stty size | awk '{print $2}')-6)) # determine terminal width
-TTY_Y=$(($(stty size | awk '{print $1}')-6)) # determine terminal height
+if [[ $BUILD_ALL != "yes" ]]; then
+ TTY_X=$(($(stty size | awk '{print $2}')-6)) # determine terminal width
+ TTY_Y=$(($(stty size | awk '{print $1}')-6)) # determine terminal height
+fi
# We'll use this title on all menus
backtitle="Armbian building script, http://www.armbian.com | Author: Igor Pecovnik"
@@ -103,6 +105,30 @@ fi
# Check and install dependencies, directory structure and settings
prepare_host
+if [[ -n $REPOSITORY_UPDATE ]]; then
+
+ # select stable/beta configuration
+ if [[ $BETA == yes ]]; then
+ DEB_STORAGE=$DEST/debs-beta
+ REPO_STORAGE=$DEST/repository-beta
+ REPO_CONFIG="aptly-beta.conf"
+ else
+ DEB_STORAGE=$DEST/debs
+ REPO_STORAGE=$DEST/repository
+ REPO_CONFIG="aptly.conf"
+ fi
+
+ # For user override
+ if [[ -f $USERPATCHES_PATH/lib.config ]]; then
+ display_alert "Using user configuration override" "userpatches/lib.config" "info"
+ source "$USERPATCHES_PATH"/lib.config
+ fi
+
+ repo-manipulate "$REPOSITORY_UPDATE"
+ exit
+
+fi
+
# if KERNEL_ONLY, KERNEL_CONFIGURE, BOARD, BRANCH or RELEASE are not set, display selection menu
if [[ -z $KERNEL_ONLY ]]; then
@@ -360,7 +386,7 @@ for option in $(tr ',' ' ' <<< "$CLEAN_LEVEL"); do
done
# Compile u-boot if packed .deb does not exist
-if [[ ! -f ${DEST}/debs/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb ]]; then
+if [[ ! -f ${DEB_STORAGE}/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb ]]; then
if [[ -n $ATFSOURCE ]]; then
compile_atf
fi
@@ -368,33 +394,45 @@ if [[ ! -f ${DEST}/debs/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb ]]; then
fi
# Compile kernel if packed .deb does not exist
-if [[ ! -f ${DEST}/debs/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb ]]; then
+if [[ ! -f ${DEB_STORAGE}/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb ]]; then
KDEB_CHANGELOG_DIST=$RELEASE
compile_kernel
fi
+# Pack armbian-config and armbian-firmware
+if [[ ! -f ${DEB_STORAGE}/armbian-config_${REVISION}_all.deb ]]; then
+ compile_armbian-config
+
+ FULL=""
+ REPLACE="-full"
+ [[ ! -f $DEST/debs/armbian-firmware_${REVISION}_all.deb ]] && compile_firmware
+ FULL="-full"
+ REPLACE=""
+ [[ ! -f $DEST/debs/armbian-firmware${FULL}_${REVISION}_all.deb ]] && compile_firmware
+fi
+
overlayfs_wrapper "cleanup"
# extract kernel version from .deb package
-VER=$(dpkg --info "${DEST}/debs/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb" | grep Descr | awk '{print $(NF)}')
+VER=$(dpkg --info "${DEB_STORAGE}/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb" | grep Descr | awk '{print $(NF)}')
VER="${VER/-$LINUXFAMILY/}"
-UBOOT_VER=$(dpkg --info "${DEST}/debs/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" | grep Descr | awk '{print $(NF)}')
+UBOOT_VER=$(dpkg --info "${DEB_STORAGE}/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" | grep Descr | awk '{print $(NF)}')
# create board support package
-[[ -n $RELEASE && ! -f $DEST/debs/$RELEASE/${CHOSEN_ROOTFS}_${REVISION}_${ARCH}.deb ]] && create_board_package
+[[ -n $RELEASE && ! -f ${DEB_STORAGE}/$RELEASE/${CHOSEN_ROOTFS}_${REVISION}_${ARCH}.deb ]] && create_board_package
# create desktop package
-[[ -n $RELEASE && ! -f $DEST/debs/$RELEASE/${CHOSEN_DESKTOP}_${REVISION}_all.deb ]] && create_desktop_package
+[[ -n $RELEASE && ! -f ${DEB_STORAGE}/$RELEASE/${CHOSEN_DESKTOP}_${REVISION}_all.deb ]] && create_desktop_package
# build additional packages
[[ $EXTERNAL_NEW == compile ]] && chroot_build_packages
if [[ $KERNEL_ONLY != yes ]]; then
- debootstrap_ng
+ [[ $BSP_BUILD != yes ]] && debootstrap_ng
else
display_alert "Kernel build done" "@host" "info"
- display_alert "Target directory" "$DEST/debs/" "info"
+ display_alert "Target directory" "${DEB_STORAGE}/" "info"
display_alert "File name" "${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb" "info"
fi
diff --git a/lib/makeboarddeb.sh b/lib/makeboarddeb.sh
index a4f0f1815..0ef1741cd 100644
--- a/lib/makeboarddeb.sh
+++ b/lib/makeboarddeb.sh
@@ -370,8 +370,8 @@ create_board_package()
# create board DEB file
display_alert "Building package" "$CHOSEN_ROOTFS" "info"
fakeroot dpkg-deb -b "${destination}" "${destination}.deb" >> "${DEST}"/debug/install.log 2>&1
- mkdir -p "${DEST}/debs/${RELEASE}/"
- mv "${destination}.deb" "${DEST}/debs/${RELEASE}/"
+ mkdir -p "${DEB_STORAGE}/${RELEASE}/"
+ mv "${destination}.deb" "${DEB_STORAGE}/${RELEASE}/"
# cleanup
rm -rf "${destination}"
}
diff --git a/lib/repository.sh b/lib/repository.sh
deleted file mode 100755
index b74e91f9c..000000000
--- a/lib/repository.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-# This script shows packages in local repository
-
-SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
-SCRIPTPATH=${SCRIPTPATH//lib}
-
-# load user config
-# shellcheck source=/dev/null
-[[ -f "${SCRIPTPATH}userpatches/lib.config" ]] && source "${SCRIPTPATH}/userpatches/lib.config"
-
-# define debs path
-POT="${SCRIPTPATH}/output/debs/"
-
-# load functions
-# shellcheck source=general.sh
-source "${SCRIPTPATH}"lib/general.sh
-
-DISTROS=("jessie" "xenial" "stretch" "bionic" "buster" "disco")
-
-ParseOptions() {
- case $@ in
- serve)
- # display repository content
- display_alert "Serving content" "common utils" "ext"
- aptly serve -listen=:8080 -config="${SCRIPTPATH}"config/aptly.conf
- exit 0
- ;;
- show)
- # display repository content
- for release in "${DISTROS[@]}"; do
- display_alert "Displaying repository contents for" "$release" "ext"
- aptly repo show -with-packages -config="${SCRIPTPATH}"config/aptly.conf "${release}" | tail -n +7
- aptly repo show -with-packages -config="${SCRIPTPATH}"config/aptly.conf "${release}-desktop" | tail -n +7
- done
- display_alert "Displaying repository contents for" "common utils" "ext"
- aptly repo show -with-packages -config="${SCRIPTPATH}"config/aptly.conf utils | tail -n +7
- echo "done."
- exit 0
- ;;
- update)
- # display full help test
- # run repository update
- addtorepo "$@" ""
- # add a key to repo
- cp "${SCRIPTPATH}"config/armbian.key "${SCRIPTPATH}"output/repository/public
- exit 0
- ;;
- purge)
- for release in "${DISTROS[@]}"; do
- repo-remove-old-packages "$release" "armhf" "3"
- repo-remove-old-packages "$release" "arm64" "3"
- repo-remove-old-packages "$release" "all" "3"
- aptly -config="${SCRIPTPATH}"config/aptly.conf -passphrase="${GPG_PASS}" publish update "${release}"
- # example to remove all packages from bionic that contain source in the name
- # aptly repo remove -config=${SCRIPTPATH}config/aptly.conf bionic 'Name (% *-source*)'
- done
- exit 0
- ;;
- *)
- DisplayUsage
- exit 0
- ;;
- esac
-} # ParseOptions
-
-# Removes old packages in the received repo
-#
-# $1: Repository
-# $2: Architecture
-# $3: Amount of packages to keep
-repo-remove-old-packages() {
- local repo=$1
- local arch=$2
- local keep=$3
-
- for pkg in $(aptly repo search -config="${SCRIPTPATH}"config/aptly.conf "${repo}" "Architecture ($arch)" | grep -v "ERROR: no results" | sort -rV); do
- local pkg_name
- pkg_name=$(echo "${pkg}" | cut -d_ -f1)
- if [ "$pkg_name" != "$cur_pkg" ]; then
- local count=0
- local deleted=""
- local cur_pkg="$pkg_name"
- fi
- test -n "$deleted" && continue
- ((count+=1))
- if [[ $count -gt $keep ]]; then
- pkg_version=$(echo "${pkg}" | cut -d_ -f2)
- aptly repo remove -config="${SCRIPTPATH}"config/aptly.conf "${repo}" "Name ($pkg_name), Version (<= $pkg_version)"
- deleted='yes'
- fi
- done
-}
-
-DisplayUsage() {
- echo -e "Usage: repository show | serve | create | update | purge\n"
- echo -e "\n show = display repository content"
- echo -e "\n serve = publish your repositories on current server over HTTP"
- echo -e "\n update = updating repository"
- echo -e "\n purge = removes all but last 5 versions\n\n"
-} # DisplayUsage
-
-ParseOptions "$@"
diff --git a/packages/bsp/common/etc/apt/apt.conf.d/02-armbian-compress-indexes b/packages/bsp/common/etc/apt/apt.conf.d/02-armbian-compress-indexes
index 3caf7b1e3..9dd10cc7e 100644
--- a/packages/bsp/common/etc/apt/apt.conf.d/02-armbian-compress-indexes
+++ b/packages/bsp/common/etc/apt/apt.conf.d/02-armbian-compress-indexes
@@ -1,2 +1,2 @@
-#Acquire::GzipIndexes "true";
-#Acquire::CompressionTypes::Order:: "gz";
+Acquire::GzipIndexes "true";
+Acquire::CompressionTypes::Order:: "gz";
diff --git a/packages/extras/armbian-config.sh b/packages/extras/armbian-config.sh
deleted file mode 100644
index 040d86727..000000000
--- a/packages/extras/armbian-config.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-compile_armbian-config()
-{
- local tmpdir=$SRC/.tmp/armbian-config_${REVISION}_all
-
- display_alert "Building deb" "armbian-config" "info"
-
- fetch_from_repo "https://github.com/armbian/config" "armbian-config" "branch:master"
-
- mkdir -p $tmpdir/{DEBIAN,usr/bin/,usr/sbin/,usr/lib/armbian-config/}
-
- # set up control file
- cat <<-END > $tmpdir/DEBIAN/control
- Package: armbian-config
- Version: $REVISION
- Architecture: all
- Maintainer: $MAINTAINER <$MAINTAINERMAIL>
- Replaces: armbian-bsp
- Depends: bash, iperf3, psmisc, curl, bc, expect, dialog, iptables, resolvconf, \
- debconf-utils, unzip, build-essential, html2text, apt-transport-https, html2text, dirmngr, software-properties-common
- Recommends: armbian-bsp
- Suggests: libpam-google-authenticator, qrencode, network-manager, sunxi-tools
- Section: utils
- Priority: optional
- Description: Armbian configuration utility
- END
-
- install -m 755 $SRC/cache/sources/armbian-config/scripts/tv_grab_file $tmpdir/usr/bin/tv_grab_file
- install -m 755 $SRC/cache/sources/armbian-config/debian-config $tmpdir/usr/sbin/armbian-config
- install -m 644 $SRC/cache/sources/armbian-config/debian-config-jobs $tmpdir/usr/lib/armbian-config/jobs.sh
- install -m 644 $SRC/cache/sources/armbian-config/debian-config-submenu $tmpdir/usr/lib/armbian-config/submenu.sh
- install -m 644 $SRC/cache/sources/armbian-config/debian-config-functions $tmpdir/usr/lib/armbian-config/functions.sh
- install -m 644 $SRC/cache/sources/armbian-config/debian-config-functions-network $tmpdir/usr/lib/armbian-config/functions-network.sh
- install -m 755 $SRC/cache/sources/armbian-config/softy $tmpdir/usr/sbin/softy
- # fallback to replace armbian-config in BSP
- ln -sf /usr/sbin/armbian-config $tmpdir/usr/bin/armbian-config
- ln -sf /usr/sbin/softy $tmpdir/usr/bin/softy
-
- fakeroot dpkg -b ${tmpdir} >/dev/null
- mv ${tmpdir}.deb $DEST/debs
- rm -rf $tmpdir
-}
-
-if [[ ! -f $DEST/debs/armbian-config_${REVISION}_all.deb ]]; then
- compile_armbian-config
-fi
-
-# installing additional dependencies here so they are installed only with armbian-config
-chroot $SDCARD /bin/bash -c "apt install -q -y iperf3 debconf-utils html2text dirmngr expect libassuan0 libnpth0 libksba8"
-install_deb_chroot "$DEST/debs/armbian-config_${REVISION}_all.deb"
diff --git a/packages/extras/firmware.sh b/packages/extras/firmware.sh
deleted file mode 100644
index bba4d2b4e..000000000
--- a/packages/extras/firmware.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-build_firmware()
-{
- display_alert "Merging and packaging linux firmware" "@host" "info"
- if [[ $USE_MAINLINE_GOOGLE_MIRROR == yes ]]; then
- plugin_repo="https://kernel.googlesource.com/pub/scm/linux/kernel/git/firmware/linux-firmware.git"
- else
- plugin_repo="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git"
- fi
- local plugin_dir="armbian-firmware${FULL}"
- [[ -d $SRC/cache/sources/$plugin_dir ]] && rm -rf $SRC/cache/sources/$plugin_dir
- mkdir -p $SRC/cache/sources/$plugin_dir/lib/firmware
-
- fetch_from_repo "https://github.com/armbian/firmware" "armbian-firmware-git" "branch:master"
- if [[ -n $FULL ]]; then
- fetch_from_repo "$plugin_repo" "linux-firmware-git" "branch:master"
- # cp : create hardlinks
- cp -alf $SRC/cache/sources/linux-firmware-git/* $SRC/cache/sources/$plugin_dir/lib/firmware/
- fi
- # overlay our firmware
- # cp : create hardlinks
- cp -alf $SRC/cache/sources/armbian-firmware-git/* $SRC/cache/sources/$plugin_dir/lib/firmware/
-
- # cleanup what's not needed for sure
- rm -rf $SRC/cache/sources/$plugin_dir/lib/firmware/{amdgpu,amd-ucode,radeon,nvidia,matrox,.git}
- cd $SRC/cache/sources/$plugin_dir
-
- # set up control file
- mkdir -p DEBIAN
- cat <<-END > DEBIAN/control
- Package: armbian-firmware${FULL}
- Version: $REVISION
- Architecture: all
- Maintainer: $MAINTAINER <$MAINTAINERMAIL>
- Installed-Size: 1
- Replaces: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, armbian-firmware${REPLACE}
- Section: kernel
- Priority: optional
- Description: Linux firmware${FULL}
- END
-
- cd $SRC/cache/sources
- # pack
- mv armbian-firmware${FULL} armbian-firmware${FULL}_${REVISION}_all
- fakeroot dpkg -b armbian-firmware${FULL}_${REVISION}_all >> $DEST/debug/install.log 2>&1
- mv armbian-firmware${FULL}_${REVISION}_all armbian-firmware${FULL}
- mv armbian-firmware${FULL}_${REVISION}_all.deb $DEST/debs/ || display_alert "Failed moving firmware package" "" "wrn"
-}
-
-FULL=""
-REPLACE="-full"
-[[ ! -f $DEST/debs/armbian-firmware_${REVISION}_all.deb ]] && build_firmware
-FULL="-full"
-REPLACE=""
-[[ ! -f $DEST/debs/armbian-firmware${FULL}_${REVISION}_all.deb ]] && build_firmware
-
-# install basic firmware by default
-install_deb_chroot "$DEST/debs/armbian-firmware_${REVISION}_all.deb"
diff --git a/packages/extras/mt7601.sh b/packages/extras/mt7601.sh
deleted file mode 100644
index a520579d8..000000000
--- a/packages/extras/mt7601.sh
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-install_mt7601()
-{
- local plugin_repo="https://github.com/igorpecovnik/mt7601"
- local plugin_dir="mt7601"
-
- fetch_from_repo "$plugin_repo" "$plugin_dir" "branch:old"
-
- cd $SRC/cache/sources/$plugin_dir
-
- # DKMS support patch
- rm src/dkms.conf
-
- patch --batch --silent -N -p1 <<-'EOF'
- diff --git a/src/dkms.conf b/src/dkms.conf
- new file mode 100644
- index 0000000..7563b5a
- --- /dev/null
- +++ b/src/dkms.conf
- @@ -0,0 +1,8 @@
- +PACKAGE_NAME="mt7601-sta-dkms"
- +PACKAGE_VERSION="3.0.0.4"
- +CLEAN="make clean"
- +BUILT_MODULE_NAME[0]="mt7601Usta"
- +BUILT_MODULE_LOCATION[0]="./os/linux/"
- +DEST_MODULE_LOCATION[0]="/kernel/drivers/net/wireless"
- +AUTOINSTALL=yes
- +MAKE[0]="make -j4 KERNELVER=\$kernelver"
- diff --git a/src/include/os/rt_linux.h b/src/include/os/rt_linux.h
- index 3726b9e..b8be886 100755
- --- a/src/include/os/rt_linux.h
- +++ b/src/include/os/rt_linux.h
- @@ -279,7 +279,7 @@ typedef struct file* RTMP_OS_FD;
-
- typedef struct _OS_FS_INFO_
- {
- -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
- uid_t fsuid;
- gid_t fsgid;
- #else
- diff --git a/src/os/linux/rt_linux.c b/src/os/linux/rt_linux.c
- index 1b6a631..c336611 100755
- --- a/src/os/linux/rt_linux.c
- +++ b/src/os/linux/rt_linux.c
- @@ -51,7 +51,7 @@
- #define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode)
- #endif
-
- -ULONG RTDebugLevel = RT_DEBUG_TRACE;
- +ULONG RTDebugLevel = 0;
- ULONG RTDebugFunc = 0;
-
- #ifdef OS_ABL_FUNC_SUPPORT
- EOF
-
- cd src
- make -s ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" clean >> $DEST/debug/compilation.log 2>&1
- make -s -j4 ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" LINUX_SRC=$SRC/cache/sources/$LINUXSOURCEDIR/ >> $DEST/debug/compilation.log 2>&1
- cp os/linux/*.ko $SDCARD/lib/modules/$VER-$LINUXFAMILY/kernel/net/wireless/
- mkdir -p $SDCARD/etc/Wireless/RT2870STA
- cp RT2870STA.dat $SDCARD/etc/Wireless/RT2870STA/
- depmod -b $SDCARD/ $VER-$LINUXFAMILY
- make -s clean >/dev/null
- cd ..
- mkdir -p $SDCARD/usr/src/
- cp -R src $SDCARD/usr/src/mt7601-3.0.0.4
- # TODO: Set the module to build automatically via dkms in the future here
-}
-
-if [[ $BRANCH == default && $INSTALL_HEADERS == yes ]]; then
- display_alert "Installing additional driver" "MT7601U" "info"
- install_mt7601
-fi
diff --git a/packages/extras/rtl8188eu.sh b/packages/extras/rtl8188eu.sh
deleted file mode 100644
index 36b244527..000000000
--- a/packages/extras/rtl8188eu.sh
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-# NOTE: NEeds gcc5 specific fixes like other wireless drivers
-
-install_rtl8188eu()
-{
- local plugin_repo="https://github.com/lwfinger/rtl8188eu"
- local plugin_dir="rt8188eu"
-
- fetch_from_repo "$plugin_repo" "$plugin_dir" "branch:master"
- cd $SRC/cache/sources/$plugin_dir
-
- make ARCH=$ARCHITECTURE CROSS_COMPILE=$KERNEL_COMPILER clean >> $DEST/debug/compilation.log
-
- # GCC5 compatibility patch
- patch --batch --silent -p1 -N <<-'EOF'
- diff --git a/include/ieee80211.h b/include/ieee80211.h
- index e283a5f..d07bdb8 100755
- --- a/include/ieee80211.h
- +++ b/include/ieee80211.h
- @@ -1194,18 +1194,18 @@ enum ieee80211_state {
- (((Addr[2]) & 0xff) == 0xff) && (((Addr[3]) & 0xff) == 0xff) && (((Addr[4]) & 0xff) == 0xff) && \
- (((Addr[5]) & 0xff) == 0xff))
- #else
- -extern __inline int is_multicast_mac_addr(const u8 *addr)
- +static __inline int is_multicast_mac_addr(const u8 *addr)
- {
- return ((addr[0] != 0xff) && (0x01 & addr[0]));
- }
-
- -extern __inline int is_broadcast_mac_addr(const u8 *addr)
- +static __inline int is_broadcast_mac_addr(const u8 *addr)
- {
- return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \
- (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
- }
-
- -extern __inline int is_zero_mac_addr(const u8 *addr)
- +static __inline int is_zero_mac_addr(const u8 *addr)
- {
- return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \
- (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
- EOF
- # GCC5 compatibility patch end
-
- make ARCH=$ARCHITECTURE CROSS_COMPILE=$KERNEL_COMPILER KSRC=$SRC/cache/sources/$LINUXSOURCEDIR/ >> $DEST/debug/compilation.log
- cp *.ko $SDCARD/lib/modules/$VER-$LINUXFAMILY/kernel/net/wireless/
- depmod -b $SDCARD/ $VER-$LINUXFAMILY
-}
-
-if [[ $BRANCH == default && $ARCHITECTURE == arm ]]; then
- display_alert "Installing additional driver" "RT8188EU" "info"
- install_rtl8188eu
-fi
diff --git a/packages/extras/rtl8192cu.sh b/packages/extras/rtl8192cu.sh
deleted file mode 100644
index 1a63fbc8a..000000000
--- a/packages/extras/rtl8192cu.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-# NOTE: NEeds gcc5 specific fixes like other wireless drivers
-
-install_rtl8192cu()
-{
- local plugin_repo="https://github.com/dz0ny/rt8192cu"
- # https://github.com/pvaret/rtl8192cu-fixes
- local plugin_dir="rt8192cu"
-
- fetch_from_repo "$plugin_repo" "$plugin_dir" "branch:master"
- cd $SRC/cache/sources/$plugin_dir
-
- make ARCH=$ARCHITECTURE CROSS_COMPILE=$KERNEL_COMPILER clean >> $DEST/debug/compilation.log
-
- # GCC5 compatibility patch
- patch --batch --silent -p1 -N <<-'EOF'
- diff --git a/include/ieee80211.h b/include/ieee80211.h
- index e283a5f..d07bdb8 100755
- --- a/include/ieee80211.h
- +++ b/include/ieee80211.h
- @@ -1194,18 +1194,18 @@ enum ieee80211_state {
- (((Addr[2]) & 0xff) == 0xff) && (((Addr[3]) & 0xff) == 0xff) && (((Addr[4]) & 0xff) == 0xff) && \
- (((Addr[5]) & 0xff) == 0xff))
- #else
- -extern __inline int is_multicast_mac_addr(const u8 *addr)
- +static __inline int is_multicast_mac_addr(const u8 *addr)
- {
- return ((addr[0] != 0xff) && (0x01 & addr[0]));
- }
-
- -extern __inline int is_broadcast_mac_addr(const u8 *addr)
- +static __inline int is_broadcast_mac_addr(const u8 *addr)
- {
- return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \
- (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
- }
-
- -extern __inline int is_zero_mac_addr(const u8 *addr)
- +static __inline int is_zero_mac_addr(const u8 *addr)
- {
- return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && \
- (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
- EOF
- # GCC5 compatibility patch end
-
- make ARCH=$ARCHITECTURE CROSS_COMPILE=$KERNEL_COMPILER KSRC=$SRC/cache/sources/$LINUXSOURCEDIR/ >> $DEST/debug/compilation.log
- cp *.ko $SDCARD/lib/modules/$VER-$LINUXFAMILY/kernel/net/wireless/
- depmod -b $SDCARD/ $VER-$LINUXFAMILY
- #cp blacklist*.conf $SDCARD/etc/modprobe.d/
-}
-
-if [[ $BRANCH == default && $ARCHITECTURE == arm && $INSTALL_HEADERS == yes ]]; then
- display_alert "Installing additional driver" "RT8192" "info"
- install_rtl8192cu
-fi
diff --git a/packages/extras/tools.sh b/packages/extras/tools.sh
deleted file mode 100644
index 3c0befaa5..000000000
--- a/packages/extras/tools.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
-#
-# This file is licensed under the terms of the GNU General Public
-# License version 2. This program is licensed "as is" without any
-# warranty of any kind, whether express or implied.
-
-# This file is a part of the Armbian build script
-# https://github.com/armbian/build/
-
-compile_tools()
-{
- local tmpdir=$SDCARD/root/tools
-
- display_alert "Building deb" "armbian-tools" "info"
-
- display_alert "... downloading sources" "BT utils" "info"
- git clone -q https://github.com/phelum/CT_Bluetooth $tmpdir/brcm >> $DEST/debug/brcm-build.log 2>&1
-
- rm -f $tmpdir/brcm/{brcm_patchram_plus,brcm_bt_reset} $tmpdir/brcm/*.o
-
- display_alert "... compiling" "bluetooth utils" "info"
- chroot $SDCARD /bin/bash -c "cd /root/tools/brcm; make $CTHREADS" >> $DEST/debug/tools-build.log 2>&1
- if [[ $? -ne 0 || ! -f $tmpdir/brcm/brcm_bt_reset ]]; then
- cd $SRC/cache
- rm -rf $tmpdir
- display_alert "Error building" "BT utils" "wrn"
- return
- fi
-
- mkdir -p $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/{DEBIAN,usr/bin,/etc/default,/etc/init.d}
-
- # set up control file
- cat <<-END > $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/DEBIAN/control
- Package: armbian-tools-$RELEASE
- Version: $REVISION
- Architecture: $ARCH
- Maintainer: $MAINTAINER <$MAINTAINERMAIL>
- Installed-Size: 1
- Provides: armbian-tools
- Conflicts: armbian-tools
- Depends: libc6 (>= 2.10)
- Section: utils
- Priority: optional
- Description: Armbian tools, Cubie bt utils
- END
-
- # brcm
- cp $tmpdir/brcm/{brcm_bt_reset,brcm_patchram_plus} $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/usr/bin
- # brcm configs and service
- install -m 644 $SRC/packages/extras/tools/brcm40183 $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/etc/default
- install -m 755 $SRC/packages/extras/tools/brcm40183-patch $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/etc/init.d
-
- # ap6212 configs and service
- install -m 644 $SRC/packages/extras/tools/ap6212 $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/etc/default
- install -m 755 $SRC/packages/extras/tools/ap6212-bluetooth $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}/etc/init.d
-
- cd $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}
- find . -type f ! -regex '.*.hg.*' ! -regex '.*?debian-binary.*' ! -regex '.*?DEBIAN.*' -printf '%P ' | xargs md5sum > DEBIAN/md5sums
- cd $tmpdir
- fakeroot dpkg -b armbian-tools-${RELEASE}_${REVISION}_${ARCH} >/dev/null
- mv $tmpdir/armbian-tools-${RELEASE}_${REVISION}_${ARCH}.deb $DEST/debs
- cd $SRC/cache
- rm -rf $tmpdir
-}
-
-if [[ ! -f $DEST/debs/armbian-tools-${RELEASE}_${REVISION}_${ARCH}.deb ]]; then
- compile_tools
-fi
-
-install_deb_chroot "$DEST/debs/armbian-tools-${RELEASE}_${REVISION}_${ARCH}.deb"
diff --git a/packages/extras/tools/ap6212 b/packages/extras/tools/ap6212
deleted file mode 100644
index e87d5d8b0..000000000
--- a/packages/extras/tools/ap6212
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Default it is called to be uncertain wich MAC address the chipset has.
-# Therefore it is recommendable to set the MAC address manually.
-# This can be done by setting the variable MAC_ADDR with a chosen value.
-# If this variable is empty or not set the default 11:22:33:44:55:66 will be chosen.
-
-MAC_ADDR=43:29:B1:55:01:01
-
-#
-
-PORT=ttyS1
diff --git a/packages/extras/tools/ap6212-bluetooth b/packages/extras/tools/ap6212-bluetooth
deleted file mode 100644
index 29ace36ff..000000000
--- a/packages/extras/tools/ap6212-bluetooth
+++ /dev/null
@@ -1,91 +0,0 @@
-#! /bin/sh
-### BEGIN INIT INFO
-# Provides: ap6212-bluetooth
-# Required-Start: $local_fs
-# Required-Stop:
-# X-Start-Before: bluetooth
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Patch firmware for ap6212 adapter
-# Description: Patch firmware for ap6212 adapter
-### END INIT INFO
-
-DEFAULTS="/etc/default/ap6212"
-
-# Include ap6212 defaults if available
-if [ -r "${DEFAULTS}" ]
-then
- . "${DEFAULTS}"
-fi
-
-# exit if bluetooth utils are not installed
-[ -f "/bin/hciconfig" ] || exit 0
-
-# copy firmware
-
-if [ -f "/lib/firmware/ap6212/bcm43438a0.hcd" ] && [ ! -f /etc/firmware/ap6212/4343A0.hcd ]; then
- mkdir -p /etc/firmware/ap6212
- cp /lib/firmware/ap6212/bcm43438a0.hcd /etc/firmware/ap6212/4343A0.hcd
-fi
-
-
-if [ -f "/lib/firmware/ap6212/bcm43438a1.hcd" ] && [ ! -f /etc/firmware/ap6212/BCM43430A1.hcd ]; then
- mkdir -p /etc/firmware/ap6212
- cp /lib/firmware/ap6212/bcm43438a1.hcd /etc/firmware/ap6212/BCM43430A1.hcd
-fi
-
-. /lib/lsb/init-functions
-
-do_start () {
-
-if [ ! -z $(hciconfig | /bin/grep UART | /usr/bin/cut -d: -f1) ]
-then
- echo "ap6212 BT device allready initialized"
- hcitool dev
- else
- # Select MAC address
- if [ -z "$MAC_ADDR" ]; then
- MAC_OPTIONS="11:22:33:44:55:66"
- else
- MAC_OPTIONS="$MAC_ADDR"
- fi
- # Select tty port
- if [ -z "$PORT" ]; then
- log_warning_msg "No PORT set in /etc/default/ap6212, will use ttyS1"
- PORT="ttyS1"
- fi
-
- # Start patching
- rfkill unblock all
- echo "0" > /sys/class/rfkill/rfkill0/state
- echo "1" > /sys/class/rfkill/rfkill0/state
- #on orangepi win following command never ends on first try... force to run with a timeout...
- timeout 5s echo " " > /dev/$PORT
- if [ $? != 0 ]; then
- #timed out... retry
- echo " " > /dev/$PORT
- fi
- hciattach /dev/$PORT bcm43xx 115200 flow bdaddr $MAC_OPTIONS
- hciconfig hci0 up
-fi
-}
-
-case "$1" in
- start)
- do_start
- ;;
- restart|reload|force-reload)
- echo "Error: argument '$1' not supported" >&2
- exit 3
- ;;
- stop)
- # No-op
- ;;
- status)
- hcitool dev
- ;;
- *)
- echo "Usage: ap6212-bluetooth [start|stop|status]" >&2
- exit 3
- ;;
-esac
\ No newline at end of file
diff --git a/packages/extras/tools/brcm40183 b/packages/extras/tools/brcm40183
deleted file mode 100644
index b32877bfa..000000000
--- a/packages/extras/tools/brcm40183
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Default it is called to be uncertain wich MAC address the chipset has.
-# Therefore it is recommendable to set the MAC address manually.
-# This can be done by setting the variable MAC_ADDR with a chosen value.
-# If this variable is empty or not set the default 11:22:33:44:55:66 will be chosen.
-# Needless to say, if more cubietrucks are used chose different adresses for them.
-
-MAC_ADDR=43:29:B1:55:01:01
-
-#
-# The PORT value has to be set with the tty port name connected to the brcm40183 chip.
-# For the cubietruck this chip is connected to uart2.
-# If this port can not be found probebly you have to enable the uart2 using setup.bin
-#
-# For example:
-#
-# [uart_para2]
-# uart_used = 1
-# uart_port = 2
-# uart_type = 4
-# uart_tx = port:PI18<3><1>
-# uart_rx = port:PI19<3><1>
-# uart_rts = port:PI16<3><1>
-# uart_cts = port:PI17<3><1>
-#
-#
-# The correct portname can be found by using the command:
-#
-# ls /sys/devices/platform/sunxi-uart.2/tty/
-#
-# Usually for Cubian it is ttyS1
-#
-
-PORT=ttyS1
diff --git a/packages/extras/tools/brcm40183-patch b/packages/extras/tools/brcm40183-patch
deleted file mode 100644
index 33c853771..000000000
--- a/packages/extras/tools/brcm40183-patch
+++ /dev/null
@@ -1,92 +0,0 @@
-#! /bin/sh
-### BEGIN INIT INFO
-# Provides: brcm40183-patch
-# Required-Start: $local_fs
-# Required-Stop:
-# X-Start-Before: bluetooth
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Patch firmware for brcm40183 Bluetooth adapter
-# Description: Patch firmware for brcm40183 Bluetooth adapter
-### END INIT INFO
-
-DEFAULTS="/etc/default/brcm40183"
-
-# Include brcm40183 defaults if available
-if [ -r "${DEFAULTS}" ]
-then
- . "${DEFAULTS}"
-fi
-
-# exit if bluetooth utils are not installed
-[ -f "/bin/hciconfig" ] || exit 0
-
-. /lib/lsb/init-functions
-
-do_start () {
-
-if [ ! -z $(hciconfig | /bin/grep UART | /usr/bin/cut -d: -f1) ]
-then
- log_action_begin_msg "brcm40183 device allready initialized"
- log_action_end_msg 0
- hcitool dev
-else
- # Select MAC address
- if [ -z "$MAC_ADDR" ]; then
- log_warning_msg "No MAC_ADDR set in /etc/default/brcm40183, will use MAC 11:22:33:44:55:66"
- MAC_OPTIONS="--bd_addr 11:22:33:44:55:66"
- else
- MAC_OPTIONS="--bd_addr $MAC_ADDR"
- fi
-
- # Select tty port
- if [ -z "$PORT" ]; then
- log_warning_msg "No PORT set in /etc/default/brcm40183, will use ttyS1"
- PORT="ttyS1"
- fi
-
- # Different port for mainline
- if [ `uname -r | grep -v '^3.4.' ` ]; then PORT="ttyS2"; fi
-
- # reset port
- /usr/bin/brcm_bt_reset /dev/$PORT
-
- # Start patching
- /bin/echo -en "" > /dev/$PORT # pull down RTS on UART
- log_action_begin_msg "Start pushing firmware to device and waiting max. 60sec to complete"
-
- /usr/bin/timeout 20s /usr/bin/brcm_patchram_plus -d --patchram /lib/firmware/ap6210/bcm20710a1.hcd --enable_hci --no2bytes --tosleep 1000 $MAC_OPTIONS /dev/$PORT > /tmp/brcm40183.firmware 2>&1
-
- case "$?" in
- 0) log_action_end_msg 0
- # Enable interfaces
- hciattach /dev/$PORT any
- rfkill unblock all
- ;;
- *) log_action_end_msg 1
- /bin/echo "Check /tmp/brcm40183.firmware for messages."
- ;;
- esac
-fi
-}
-
-case "$1" in
- start)
- do_start
- ;;
- restart|reload|force-reload)
- echo "Error: argument '$1' not supported" >&2
- exit 3
- ;;
- stop)
- # No-op
- ;;
- status)
- hcitool dev
- ;;
- *)
- echo "Usage: brcm40183-patch.sh [start|stop|status]" >&2
- exit 3
- ;;
-esac
-
diff --git a/packages/extras/tools/brcm40183-patch.service b/packages/extras/tools/brcm40183-patch.service
deleted file mode 100644
index 50b5fbd14..000000000
--- a/packages/extras/tools/brcm40183-patch.service
+++ /dev/null
@@ -1,18 +0,0 @@
-[Unit]
-Description=Patch firmware for brcm40183 Bluetooth adapter
-Before=bluetooth.service
-
-[Service]
-Environment=MAC_ADDR=11:22:33:44:55:66
-Environment=PORT=/dev/ttyS1
-EnvironmentFile=/etc/default/brcm40183
-TimeoutStartSec=60
-Type=simple
-ExecStartPre=/usr/bin/brcm_bt_reset /dev/${PORT}
-ExecStartPre=/bin/echo -en "" > /dev/${PORT}
-ExecStartPre=/usr/bin/brcm_patchram_plus -d --patchram /lib/firmware/ap6210/bcm20710a1.hcd --no2bytes --tosleep 1000 --bd_addr ${MAC_ADDR} /dev/${PORT}
-ExecStart=/usr/bin/hciattach -n /dev/${PORT} any
-ExecStart=/usr/bin/rfkill unblock all
-
-[Install]
-WantedBy=bluetooth.target
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.167-168.patch b/patch/kernel/rk3399-default/04-patch-4.4.167-168.patch
deleted file mode 100644
index 32bb254ac..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.167-168.patch
+++ /dev/null
@@ -1,7597 +0,0 @@
-diff --git a/Documentation/Makefile b/Documentation/Makefile
-index fc759598c4c9..59d516b7afcb 100644
---- a/Documentation/Makefile
-+++ b/Documentation/Makefile
-@@ -1,4 +1,3 @@
- subdir-y := accounting auxdisplay blackfin connector \
- filesystems filesystems ia64 laptops misc-devices \
-- networking pcmcia prctl ptp spi timers vDSO video4linux \
-- watchdog
-+ pcmcia prctl ptp spi timers vDSO video4linux watchdog
-diff --git a/Documentation/networking/Makefile b/Documentation/networking/Makefile
-deleted file mode 100644
-index 4c5d7c485439..000000000000
---- a/Documentation/networking/Makefile
-+++ /dev/null
-@@ -1 +0,0 @@
--subdir-y := timestamping
-diff --git a/Documentation/networking/timestamping/.gitignore b/Documentation/networking/timestamping/.gitignore
-deleted file mode 100644
-index 9e69e982fb38..000000000000
---- a/Documentation/networking/timestamping/.gitignore
-+++ /dev/null
-@@ -1,3 +0,0 @@
--timestamping
--txtimestamp
--hwtstamp_config
-diff --git a/Documentation/networking/timestamping/Makefile b/Documentation/networking/timestamping/Makefile
-deleted file mode 100644
-index 8c20dfaa4d6e..000000000000
---- a/Documentation/networking/timestamping/Makefile
-+++ /dev/null
-@@ -1,14 +0,0 @@
--# To compile, from the source root
--#
--# make headers_install
--# make M=documentation
--
--# List of programs to build
--hostprogs-y := hwtstamp_config timestamping txtimestamp
--
--# Tell kbuild to always build the programs
--always := $(hostprogs-y)
--
--HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
--HOSTCFLAGS_txtimestamp.o += -I$(objtree)/usr/include
--HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
-diff --git a/Documentation/networking/timestamping/hwtstamp_config.c b/Documentation/networking/timestamping/hwtstamp_config.c
-deleted file mode 100644
-index e8b685a7f15f..000000000000
---- a/Documentation/networking/timestamping/hwtstamp_config.c
-+++ /dev/null
-@@ -1,134 +0,0 @@
--/* Test program for SIOC{G,S}HWTSTAMP
-- * Copyright 2013 Solarflare Communications
-- * Author: Ben Hutchings
-- */
--
--#include
--#include
--#include
--#include
--
--#include
--#include
--
--#include
--#include
--#include
--
--static int
--lookup_value(const char **names, int size, const char *name)
--{
-- int value;
--
-- for (value = 0; value < size; value++)
-- if (names[value] && strcasecmp(names[value], name) == 0)
-- return value;
--
-- return -1;
--}
--
--static const char *
--lookup_name(const char **names, int size, int value)
--{
-- return (value >= 0 && value < size) ? names[value] : NULL;
--}
--
--static void list_names(FILE *f, const char **names, int size)
--{
-- int value;
--
-- for (value = 0; value < size; value++)
-- if (names[value])
-- fprintf(f, " %s\n", names[value]);
--}
--
--static const char *tx_types[] = {
--#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
-- TX_TYPE(OFF),
-- TX_TYPE(ON),
-- TX_TYPE(ONESTEP_SYNC)
--#undef TX_TYPE
--};
--#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
--
--static const char *rx_filters[] = {
--#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
-- RX_FILTER(NONE),
-- RX_FILTER(ALL),
-- RX_FILTER(SOME),
-- RX_FILTER(PTP_V1_L4_EVENT),
-- RX_FILTER(PTP_V1_L4_SYNC),
-- RX_FILTER(PTP_V1_L4_DELAY_REQ),
-- RX_FILTER(PTP_V2_L4_EVENT),
-- RX_FILTER(PTP_V2_L4_SYNC),
-- RX_FILTER(PTP_V2_L4_DELAY_REQ),
-- RX_FILTER(PTP_V2_L2_EVENT),
-- RX_FILTER(PTP_V2_L2_SYNC),
-- RX_FILTER(PTP_V2_L2_DELAY_REQ),
-- RX_FILTER(PTP_V2_EVENT),
-- RX_FILTER(PTP_V2_SYNC),
-- RX_FILTER(PTP_V2_DELAY_REQ),
--#undef RX_FILTER
--};
--#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
--
--static void usage(void)
--{
-- fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
-- "tx_type is any of (case-insensitive):\n",
-- stderr);
-- list_names(stderr, tx_types, N_TX_TYPES);
-- fputs("rx_filter is any of (case-insensitive):\n", stderr);
-- list_names(stderr, rx_filters, N_RX_FILTERS);
--}
--
--int main(int argc, char **argv)
--{
-- struct ifreq ifr;
-- struct hwtstamp_config config;
-- const char *name;
-- int sock;
--
-- if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
-- usage();
-- return 2;
-- }
--
-- if (argc == 4) {
-- config.flags = 0;
-- config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
-- config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
-- if (config.tx_type < 0 || config.rx_filter < 0) {
-- usage();
-- return 2;
-- }
-- }
--
-- sock = socket(AF_INET, SOCK_DGRAM, 0);
-- if (sock < 0) {
-- perror("socket");
-- return 1;
-- }
--
-- strcpy(ifr.ifr_name, argv[1]);
-- ifr.ifr_data = (caddr_t)&config;
--
-- if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
-- perror("ioctl");
-- return 1;
-- }
--
-- printf("flags = %#x\n", config.flags);
-- name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
-- if (name)
-- printf("tx_type = %s\n", name);
-- else
-- printf("tx_type = %d\n", config.tx_type);
-- name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
-- if (name)
-- printf("rx_filter = %s\n", name);
-- else
-- printf("rx_filter = %d\n", config.rx_filter);
--
-- return 0;
--}
-diff --git a/Documentation/networking/timestamping/timestamping.c b/Documentation/networking/timestamping/timestamping.c
-deleted file mode 100644
-index 5cdfd743447b..000000000000
---- a/Documentation/networking/timestamping/timestamping.c
-+++ /dev/null
-@@ -1,528 +0,0 @@
--/*
-- * This program demonstrates how the various time stamping features in
-- * the Linux kernel work. It emulates the behavior of a PTP
-- * implementation in stand-alone master mode by sending PTPv1 Sync
-- * multicasts once every second. It looks for similar packets, but
-- * beyond that doesn't actually implement PTP.
-- *
-- * Outgoing packets are time stamped with SO_TIMESTAMPING with or
-- * without hardware support.
-- *
-- * Incoming packets are time stamped with SO_TIMESTAMPING with or
-- * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
-- * SO_TIMESTAMP[NS].
-- *
-- * Copyright (C) 2009 Intel Corporation.
-- * Author: Patrick Ohly
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms and conditions of the GNU General Public License,
-- * version 2, as published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope 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, Inc.,
-- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-- */
--
--#include
--#include
--#include
--#include
--
--#include
--#include
--#include
--#include
--#include
--#include
--
--#include
--#include
--#include
--
--#ifndef SO_TIMESTAMPING
--# define SO_TIMESTAMPING 37
--# define SCM_TIMESTAMPING SO_TIMESTAMPING
--#endif
--
--#ifndef SO_TIMESTAMPNS
--# define SO_TIMESTAMPNS 35
--#endif
--
--#ifndef SIOCGSTAMPNS
--# define SIOCGSTAMPNS 0x8907
--#endif
--
--#ifndef SIOCSHWTSTAMP
--# define SIOCSHWTSTAMP 0x89b0
--#endif
--
--static void usage(const char *error)
--{
-- if (error)
-- printf("invalid option: %s\n", error);
-- printf("timestamping interface option*\n\n"
-- "Options:\n"
-- " IP_MULTICAST_LOOP - looping outgoing multicasts\n"
-- " SO_TIMESTAMP - normal software time stamping, ms resolution\n"
-- " SO_TIMESTAMPNS - more accurate software time stamping\n"
-- " SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
-- " SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
-- " SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
-- " SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
-- " SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
-- " SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
-- " SIOCGSTAMP - check last socket time stamp\n"
-- " SIOCGSTAMPNS - more accurate socket time stamp\n");
-- exit(1);
--}
--
--static void bail(const char *error)
--{
-- printf("%s: %s\n", error, strerror(errno));
-- exit(1);
--}
--
--static const unsigned char sync[] = {
-- 0x00, 0x01, 0x00, 0x01,
-- 0x5f, 0x44, 0x46, 0x4c,
-- 0x54, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x01, 0x01,
--
-- /* fake uuid */
-- 0x00, 0x01,
-- 0x02, 0x03, 0x04, 0x05,
--
-- 0x00, 0x01, 0x00, 0x37,
-- 0x00, 0x00, 0x00, 0x08,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x49, 0x05, 0xcd, 0x01,
-- 0x29, 0xb1, 0x8d, 0xb0,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x01,
--
-- /* fake uuid */
-- 0x00, 0x01,
-- 0x02, 0x03, 0x04, 0x05,
--
-- 0x00, 0x00, 0x00, 0x37,
-- 0x00, 0x00, 0x00, 0x04,
-- 0x44, 0x46, 0x4c, 0x54,
-- 0x00, 0x00, 0xf0, 0x60,
-- 0x00, 0x01, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x01,
-- 0x00, 0x00, 0xf0, 0x60,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x04,
-- 0x44, 0x46, 0x4c, 0x54,
-- 0x00, 0x01,
--
-- /* fake uuid */
-- 0x00, 0x01,
-- 0x02, 0x03, 0x04, 0x05,
--
-- 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00
--};
--
--static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
--{
-- struct timeval now;
-- int res;
--
-- res = sendto(sock, sync, sizeof(sync), 0,
-- addr, addr_len);
-- gettimeofday(&now, 0);
-- if (res < 0)
-- printf("%s: %s\n", "send", strerror(errno));
-- else
-- printf("%ld.%06ld: sent %d bytes\n",
-- (long)now.tv_sec, (long)now.tv_usec,
-- res);
--}
--
--static void printpacket(struct msghdr *msg, int res,
-- char *data,
-- int sock, int recvmsg_flags,
-- int siocgstamp, int siocgstampns)
--{
-- struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
-- struct cmsghdr *cmsg;
-- struct timeval tv;
-- struct timespec ts;
-- struct timeval now;
--
-- gettimeofday(&now, 0);
--
-- printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
-- (long)now.tv_sec, (long)now.tv_usec,
-- (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
-- res,
-- inet_ntoa(from_addr->sin_addr),
-- msg->msg_controllen);
-- for (cmsg = CMSG_FIRSTHDR(msg);
-- cmsg;
-- cmsg = CMSG_NXTHDR(msg, cmsg)) {
-- printf(" cmsg len %zu: ", cmsg->cmsg_len);
-- switch (cmsg->cmsg_level) {
-- case SOL_SOCKET:
-- printf("SOL_SOCKET ");
-- switch (cmsg->cmsg_type) {
-- case SO_TIMESTAMP: {
-- struct timeval *stamp =
-- (struct timeval *)CMSG_DATA(cmsg);
-- printf("SO_TIMESTAMP %ld.%06ld",
-- (long)stamp->tv_sec,
-- (long)stamp->tv_usec);
-- break;
-- }
-- case SO_TIMESTAMPNS: {
-- struct timespec *stamp =
-- (struct timespec *)CMSG_DATA(cmsg);
-- printf("SO_TIMESTAMPNS %ld.%09ld",
-- (long)stamp->tv_sec,
-- (long)stamp->tv_nsec);
-- break;
-- }
-- case SO_TIMESTAMPING: {
-- struct timespec *stamp =
-- (struct timespec *)CMSG_DATA(cmsg);
-- printf("SO_TIMESTAMPING ");
-- printf("SW %ld.%09ld ",
-- (long)stamp->tv_sec,
-- (long)stamp->tv_nsec);
-- stamp++;
-- /* skip deprecated HW transformed */
-- stamp++;
-- printf("HW raw %ld.%09ld",
-- (long)stamp->tv_sec,
-- (long)stamp->tv_nsec);
-- break;
-- }
-- default:
-- printf("type %d", cmsg->cmsg_type);
-- break;
-- }
-- break;
-- case IPPROTO_IP:
-- printf("IPPROTO_IP ");
-- switch (cmsg->cmsg_type) {
-- case IP_RECVERR: {
-- struct sock_extended_err *err =
-- (struct sock_extended_err *)CMSG_DATA(cmsg);
-- printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
-- strerror(err->ee_errno),
-- err->ee_origin,
--#ifdef SO_EE_ORIGIN_TIMESTAMPING
-- err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
-- "bounced packet" : "unexpected origin"
--#else
-- "probably SO_EE_ORIGIN_TIMESTAMPING"
--#endif
-- );
-- if (res < sizeof(sync))
-- printf(" => truncated data?!");
-- else if (!memcmp(sync, data + res - sizeof(sync),
-- sizeof(sync)))
-- printf(" => GOT OUR DATA BACK (HURRAY!)");
-- break;
-- }
-- case IP_PKTINFO: {
-- struct in_pktinfo *pktinfo =
-- (struct in_pktinfo *)CMSG_DATA(cmsg);
-- printf("IP_PKTINFO interface index %u",
-- pktinfo->ipi_ifindex);
-- break;
-- }
-- default:
-- printf("type %d", cmsg->cmsg_type);
-- break;
-- }
-- break;
-- default:
-- printf("level %d type %d",
-- cmsg->cmsg_level,
-- cmsg->cmsg_type);
-- break;
-- }
-- printf("\n");
-- }
--
-- if (siocgstamp) {
-- if (ioctl(sock, SIOCGSTAMP, &tv))
-- printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
-- else
-- printf("SIOCGSTAMP %ld.%06ld\n",
-- (long)tv.tv_sec,
-- (long)tv.tv_usec);
-- }
-- if (siocgstampns) {
-- if (ioctl(sock, SIOCGSTAMPNS, &ts))
-- printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
-- else
-- printf("SIOCGSTAMPNS %ld.%09ld\n",
-- (long)ts.tv_sec,
-- (long)ts.tv_nsec);
-- }
--}
--
--static void recvpacket(int sock, int recvmsg_flags,
-- int siocgstamp, int siocgstampns)
--{
-- char data[256];
-- struct msghdr msg;
-- struct iovec entry;
-- struct sockaddr_in from_addr;
-- struct {
-- struct cmsghdr cm;
-- char control[512];
-- } control;
-- int res;
--
-- memset(&msg, 0, sizeof(msg));
-- msg.msg_iov = &entry;
-- msg.msg_iovlen = 1;
-- entry.iov_base = data;
-- entry.iov_len = sizeof(data);
-- msg.msg_name = (caddr_t)&from_addr;
-- msg.msg_namelen = sizeof(from_addr);
-- msg.msg_control = &control;
-- msg.msg_controllen = sizeof(control);
--
-- res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
-- if (res < 0) {
-- printf("%s %s: %s\n",
-- "recvmsg",
-- (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
-- strerror(errno));
-- } else {
-- printpacket(&msg, res, data,
-- sock, recvmsg_flags,
-- siocgstamp, siocgstampns);
-- }
--}
--
--int main(int argc, char **argv)
--{
-- int so_timestamping_flags = 0;
-- int so_timestamp = 0;
-- int so_timestampns = 0;
-- int siocgstamp = 0;
-- int siocgstampns = 0;
-- int ip_multicast_loop = 0;
-- char *interface;
-- int i;
-- int enabled = 1;
-- int sock;
-- struct ifreq device;
-- struct ifreq hwtstamp;
-- struct hwtstamp_config hwconfig, hwconfig_requested;
-- struct sockaddr_in addr;
-- struct ip_mreq imr;
-- struct in_addr iaddr;
-- int val;
-- socklen_t len;
-- struct timeval next;
--
-- if (argc < 2)
-- usage(0);
-- interface = argv[1];
--
-- for (i = 2; i < argc; i++) {
-- if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
-- so_timestamp = 1;
-- else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
-- so_timestampns = 1;
-- else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
-- siocgstamp = 1;
-- else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
-- siocgstampns = 1;
-- else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
-- ip_multicast_loop = 1;
-- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
-- so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
-- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
-- so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
-- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
-- so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
-- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
-- so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
-- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
-- so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
-- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
-- so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
-- else
-- usage(argv[i]);
-- }
--
-- sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-- if (sock < 0)
-- bail("socket");
--
-- memset(&device, 0, sizeof(device));
-- strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
-- if (ioctl(sock, SIOCGIFADDR, &device) < 0)
-- bail("getting interface IP address");
--
-- memset(&hwtstamp, 0, sizeof(hwtstamp));
-- strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
-- hwtstamp.ifr_data = (void *)&hwconfig;
-- memset(&hwconfig, 0, sizeof(hwconfig));
-- hwconfig.tx_type =
-- (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
-- HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
-- hwconfig.rx_filter =
-- (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
-- HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
-- hwconfig_requested = hwconfig;
-- if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
-- if ((errno == EINVAL || errno == ENOTSUP) &&
-- hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
-- hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
-- printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
-- else
-- bail("SIOCSHWTSTAMP");
-- }
-- printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
-- hwconfig_requested.tx_type, hwconfig.tx_type,
-- hwconfig_requested.rx_filter, hwconfig.rx_filter);
--
-- /* bind to PTP port */
-- addr.sin_family = AF_INET;
-- addr.sin_addr.s_addr = htonl(INADDR_ANY);
-- addr.sin_port = htons(319 /* PTP event port */);
-- if (bind(sock,
-- (struct sockaddr *)&addr,
-- sizeof(struct sockaddr_in)) < 0)
-- bail("bind");
--
-- /* set multicast group for outgoing packets */
-- inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
-- addr.sin_addr = iaddr;
-- imr.imr_multiaddr.s_addr = iaddr.s_addr;
-- imr.imr_interface.s_addr =
-- ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
-- if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
-- &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
-- bail("set multicast");
--
-- /* join multicast group, loop our own packet */
-- if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-- &imr, sizeof(struct ip_mreq)) < 0)
-- bail("join multicast group");
--
-- if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
-- &ip_multicast_loop, sizeof(enabled)) < 0) {
-- bail("loop multicast");
-- }
--
-- /* set socket options for time stamping */
-- if (so_timestamp &&
-- setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
-- &enabled, sizeof(enabled)) < 0)
-- bail("setsockopt SO_TIMESTAMP");
--
-- if (so_timestampns &&
-- setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
-- &enabled, sizeof(enabled)) < 0)
-- bail("setsockopt SO_TIMESTAMPNS");
--
-- if (so_timestamping_flags &&
-- setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
-- &so_timestamping_flags,
-- sizeof(so_timestamping_flags)) < 0)
-- bail("setsockopt SO_TIMESTAMPING");
--
-- /* request IP_PKTINFO for debugging purposes */
-- if (setsockopt(sock, SOL_IP, IP_PKTINFO,
-- &enabled, sizeof(enabled)) < 0)
-- printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
--
-- /* verify socket options */
-- len = sizeof(val);
-- if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
-- printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
-- else
-- printf("SO_TIMESTAMP %d\n", val);
--
-- if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
-- printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
-- strerror(errno));
-- else
-- printf("SO_TIMESTAMPNS %d\n", val);
--
-- if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
-- printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
-- strerror(errno));
-- } else {
-- printf("SO_TIMESTAMPING %d\n", val);
-- if (val != so_timestamping_flags)
-- printf(" not the expected value %d\n",
-- so_timestamping_flags);
-- }
--
-- /* send packets forever every five seconds */
-- gettimeofday(&next, 0);
-- next.tv_sec = (next.tv_sec + 1) / 5 * 5;
-- next.tv_usec = 0;
-- while (1) {
-- struct timeval now;
-- struct timeval delta;
-- long delta_us;
-- int res;
-- fd_set readfs, errorfs;
--
-- gettimeofday(&now, 0);
-- delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
-- (long)(next.tv_usec - now.tv_usec);
-- if (delta_us > 0) {
-- /* continue waiting for timeout or data */
-- delta.tv_sec = delta_us / 1000000;
-- delta.tv_usec = delta_us % 1000000;
--
-- FD_ZERO(&readfs);
-- FD_ZERO(&errorfs);
-- FD_SET(sock, &readfs);
-- FD_SET(sock, &errorfs);
-- printf("%ld.%06ld: select %ldus\n",
-- (long)now.tv_sec, (long)now.tv_usec,
-- delta_us);
-- res = select(sock + 1, &readfs, 0, &errorfs, &delta);
-- gettimeofday(&now, 0);
-- printf("%ld.%06ld: select returned: %d, %s\n",
-- (long)now.tv_sec, (long)now.tv_usec,
-- res,
-- res < 0 ? strerror(errno) : "success");
-- if (res > 0) {
-- if (FD_ISSET(sock, &readfs))
-- printf("ready for reading\n");
-- if (FD_ISSET(sock, &errorfs))
-- printf("has error\n");
-- recvpacket(sock, 0,
-- siocgstamp,
-- siocgstampns);
-- recvpacket(sock, MSG_ERRQUEUE,
-- siocgstamp,
-- siocgstampns);
-- }
-- } else {
-- /* write one packet */
-- sendpacket(sock,
-- (struct sockaddr *)&addr,
-- sizeof(addr));
-- next.tv_sec += 5;
-- continue;
-- }
-- }
--
-- return 0;
--}
-diff --git a/Documentation/networking/timestamping/txtimestamp.c b/Documentation/networking/timestamping/txtimestamp.c
-deleted file mode 100644
-index 5df07047ca86..000000000000
---- a/Documentation/networking/timestamping/txtimestamp.c
-+++ /dev/null
-@@ -1,549 +0,0 @@
--/*
-- * Copyright 2014 Google Inc.
-- * Author: willemb@google.com (Willem de Bruijn)
-- *
-- * Test software tx timestamping, including
-- *
-- * - SCHED, SND and ACK timestamps
-- * - RAW, UDP and TCP
-- * - IPv4 and IPv6
-- * - various packet sizes (to test GSO and TSO)
-- *
-- * Consult the command line arguments for help on running
-- * the various testcases.
-- *
-- * This test requires a dummy TCP server.
-- * A simple `nc6 [-u] -l -p $DESTPORT` will do
-- *
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms and conditions of the GNU General Public License,
-- * version 2, as published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope 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, Inc.,
-- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-- */
--
--#define _GNU_SOURCE
--
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--#include
--
--/* command line parameters */
--static int cfg_proto = SOCK_STREAM;
--static int cfg_ipproto = IPPROTO_TCP;
--static int cfg_num_pkts = 4;
--static int do_ipv4 = 1;
--static int do_ipv6 = 1;
--static int cfg_payload_len = 10;
--static bool cfg_show_payload;
--static bool cfg_do_pktinfo;
--static bool cfg_loop_nodata;
--static uint16_t dest_port = 9000;
--
--static struct sockaddr_in daddr;
--static struct sockaddr_in6 daddr6;
--static struct timespec ts_prev;
--
--static void __print_timestamp(const char *name, struct timespec *cur,
-- uint32_t key, int payload_len)
--{
-- if (!(cur->tv_sec | cur->tv_nsec))
-- return;
--
-- fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)",
-- name, cur->tv_sec, cur->tv_nsec / 1000,
-- key, payload_len);
--
-- if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
-- int64_t cur_ms, prev_ms;
--
-- cur_ms = (long) cur->tv_sec * 1000 * 1000;
-- cur_ms += cur->tv_nsec / 1000;
--
-- prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
-- prev_ms += ts_prev.tv_nsec / 1000;
--
-- fprintf(stderr, " (%+" PRId64 " us)", cur_ms - prev_ms);
-- }
--
-- ts_prev = *cur;
-- fprintf(stderr, "\n");
--}
--
--static void print_timestamp_usr(void)
--{
-- struct timespec ts;
-- struct timeval tv; /* avoid dependency on -lrt */
--
-- gettimeofday(&tv, NULL);
-- ts.tv_sec = tv.tv_sec;
-- ts.tv_nsec = tv.tv_usec * 1000;
--
-- __print_timestamp(" USR", &ts, 0, 0);
--}
--
--static void print_timestamp(struct scm_timestamping *tss, int tstype,
-- int tskey, int payload_len)
--{
-- const char *tsname;
--
-- switch (tstype) {
-- case SCM_TSTAMP_SCHED:
-- tsname = " ENQ";
-- break;
-- case SCM_TSTAMP_SND:
-- tsname = " SND";
-- break;
-- case SCM_TSTAMP_ACK:
-- tsname = " ACK";
-- break;
-- default:
-- error(1, 0, "unknown timestamp type: %u",
-- tstype);
-- }
-- __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
--}
--
--/* TODO: convert to check_and_print payload once API is stable */
--static void print_payload(char *data, int len)
--{
-- int i;
--
-- if (!len)
-- return;
--
-- if (len > 70)
-- len = 70;
--
-- fprintf(stderr, "payload: ");
-- for (i = 0; i < len; i++)
-- fprintf(stderr, "%02hhx ", data[i]);
-- fprintf(stderr, "\n");
--}
--
--static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
--{
-- char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
--
-- fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n",
-- ifindex,
-- saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
-- daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
--}
--
--static void __poll(int fd)
--{
-- struct pollfd pollfd;
-- int ret;
--
-- memset(&pollfd, 0, sizeof(pollfd));
-- pollfd.fd = fd;
-- ret = poll(&pollfd, 1, 100);
-- if (ret != 1)
-- error(1, errno, "poll");
--}
--
--static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
--{
-- struct sock_extended_err *serr = NULL;
-- struct scm_timestamping *tss = NULL;
-- struct cmsghdr *cm;
-- int batch = 0;
--
-- for (cm = CMSG_FIRSTHDR(msg);
-- cm && cm->cmsg_len;
-- cm = CMSG_NXTHDR(msg, cm)) {
-- if (cm->cmsg_level == SOL_SOCKET &&
-- cm->cmsg_type == SCM_TIMESTAMPING) {
-- tss = (void *) CMSG_DATA(cm);
-- } else if ((cm->cmsg_level == SOL_IP &&
-- cm->cmsg_type == IP_RECVERR) ||
-- (cm->cmsg_level == SOL_IPV6 &&
-- cm->cmsg_type == IPV6_RECVERR)) {
-- serr = (void *) CMSG_DATA(cm);
-- if (serr->ee_errno != ENOMSG ||
-- serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
-- fprintf(stderr, "unknown ip error %d %d\n",
-- serr->ee_errno,
-- serr->ee_origin);
-- serr = NULL;
-- }
-- } else if (cm->cmsg_level == SOL_IP &&
-- cm->cmsg_type == IP_PKTINFO) {
-- struct in_pktinfo *info = (void *) CMSG_DATA(cm);
-- print_pktinfo(AF_INET, info->ipi_ifindex,
-- &info->ipi_spec_dst, &info->ipi_addr);
-- } else if (cm->cmsg_level == SOL_IPV6 &&
-- cm->cmsg_type == IPV6_PKTINFO) {
-- struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
-- print_pktinfo(AF_INET6, info6->ipi6_ifindex,
-- NULL, &info6->ipi6_addr);
-- } else
-- fprintf(stderr, "unknown cmsg %d,%d\n",
-- cm->cmsg_level, cm->cmsg_type);
--
-- if (serr && tss) {
-- print_timestamp(tss, serr->ee_info, serr->ee_data,
-- payload_len);
-- serr = NULL;
-- tss = NULL;
-- batch++;
-- }
-- }
--
-- if (batch > 1)
-- fprintf(stderr, "batched %d timestamps\n", batch);
--}
--
--static int recv_errmsg(int fd)
--{
-- static char ctrl[1024 /* overprovision*/];
-- static struct msghdr msg;
-- struct iovec entry;
-- static char *data;
-- int ret = 0;
--
-- data = malloc(cfg_payload_len);
-- if (!data)
-- error(1, 0, "malloc");
--
-- memset(&msg, 0, sizeof(msg));
-- memset(&entry, 0, sizeof(entry));
-- memset(ctrl, 0, sizeof(ctrl));
--
-- entry.iov_base = data;
-- entry.iov_len = cfg_payload_len;
-- msg.msg_iov = &entry;
-- msg.msg_iovlen = 1;
-- msg.msg_name = NULL;
-- msg.msg_namelen = 0;
-- msg.msg_control = ctrl;
-- msg.msg_controllen = sizeof(ctrl);
--
-- ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
-- if (ret == -1 && errno != EAGAIN)
-- error(1, errno, "recvmsg");
--
-- if (ret >= 0) {
-- __recv_errmsg_cmsg(&msg, ret);
-- if (cfg_show_payload)
-- print_payload(data, cfg_payload_len);
-- }
--
-- free(data);
-- return ret == -1;
--}
--
--static void do_test(int family, unsigned int opt)
--{
-- char *buf;
-- int fd, i, val = 1, total_len;
--
-- if (family == AF_INET6 && cfg_proto != SOCK_STREAM) {
-- /* due to lack of checksum generation code */
-- fprintf(stderr, "test: skipping datagram over IPv6\n");
-- return;
-- }
--
-- total_len = cfg_payload_len;
-- if (cfg_proto == SOCK_RAW) {
-- total_len += sizeof(struct udphdr);
-- if (cfg_ipproto == IPPROTO_RAW)
-- total_len += sizeof(struct iphdr);
-- }
--
-- buf = malloc(total_len);
-- if (!buf)
-- error(1, 0, "malloc");
--
-- fd = socket(family, cfg_proto, cfg_ipproto);
-- if (fd < 0)
-- error(1, errno, "socket");
--
-- if (cfg_proto == SOCK_STREAM) {
-- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
-- (char*) &val, sizeof(val)))
-- error(1, 0, "setsockopt no nagle");
--
-- if (family == PF_INET) {
-- if (connect(fd, (void *) &daddr, sizeof(daddr)))
-- error(1, errno, "connect ipv4");
-- } else {
-- if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
-- error(1, errno, "connect ipv6");
-- }
-- }
--
-- if (cfg_do_pktinfo) {
-- if (family == AF_INET6) {
-- if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
-- &val, sizeof(val)))
-- error(1, errno, "setsockopt pktinfo ipv6");
-- } else {
-- if (setsockopt(fd, SOL_IP, IP_PKTINFO,
-- &val, sizeof(val)))
-- error(1, errno, "setsockopt pktinfo ipv4");
-- }
-- }
--
-- opt |= SOF_TIMESTAMPING_SOFTWARE |
-- SOF_TIMESTAMPING_OPT_CMSG |
-- SOF_TIMESTAMPING_OPT_ID;
-- if (cfg_loop_nodata)
-- opt |= SOF_TIMESTAMPING_OPT_TSONLY;
--
-- if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
-- (char *) &opt, sizeof(opt)))
-- error(1, 0, "setsockopt timestamping");
--
-- for (i = 0; i < cfg_num_pkts; i++) {
-- memset(&ts_prev, 0, sizeof(ts_prev));
-- memset(buf, 'a' + i, total_len);
--
-- if (cfg_proto == SOCK_RAW) {
-- struct udphdr *udph;
-- int off = 0;
--
-- if (cfg_ipproto == IPPROTO_RAW) {
-- struct iphdr *iph = (void *) buf;
--
-- memset(iph, 0, sizeof(*iph));
-- iph->ihl = 5;
-- iph->version = 4;
-- iph->ttl = 2;
-- iph->daddr = daddr.sin_addr.s_addr;
-- iph->protocol = IPPROTO_UDP;
-- /* kernel writes saddr, csum, len */
--
-- off = sizeof(*iph);
-- }
--
-- udph = (void *) buf + off;
-- udph->source = ntohs(9000); /* random spoof */
-- udph->dest = ntohs(dest_port);
-- udph->len = ntohs(sizeof(*udph) + cfg_payload_len);
-- udph->check = 0; /* not allowed for IPv6 */
-- }
--
-- print_timestamp_usr();
-- if (cfg_proto != SOCK_STREAM) {
-- if (family == PF_INET)
-- val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
-- else
-- val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
-- } else {
-- val = send(fd, buf, cfg_payload_len, 0);
-- }
-- if (val != total_len)
-- error(1, errno, "send");
--
-- /* wait for all errors to be queued, else ACKs arrive OOO */
-- usleep(50 * 1000);
--
-- __poll(fd);
--
-- while (!recv_errmsg(fd)) {}
-- }
--
-- if (close(fd))
-- error(1, errno, "close");
--
-- free(buf);
-- usleep(400 * 1000);
--}
--
--static void __attribute__((noreturn)) usage(const char *filepath)
--{
-- fprintf(stderr, "\nUsage: %s [options] hostname\n"
-- "\nwhere options are:\n"
-- " -4: only IPv4\n"
-- " -6: only IPv6\n"
-- " -h: show this message\n"
-- " -I: request PKTINFO\n"
-- " -l N: send N bytes at a time\n"
-- " -n: set no-payload option\n"
-- " -r: use raw\n"
-- " -R: use raw (IP_HDRINCL)\n"
-- " -p N: connect to port N\n"
-- " -u: use udp\n"
-- " -x: show payload (up to 70 bytes)\n",
-- filepath);
-- exit(1);
--}
--
--static void parse_opt(int argc, char **argv)
--{
-- int proto_count = 0;
-- char c;
--
-- while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) {
-- switch (c) {
-- case '4':
-- do_ipv6 = 0;
-- break;
-- case '6':
-- do_ipv4 = 0;
-- break;
-- case 'I':
-- cfg_do_pktinfo = true;
-- break;
-- case 'n':
-- cfg_loop_nodata = true;
-- break;
-- case 'r':
-- proto_count++;
-- cfg_proto = SOCK_RAW;
-- cfg_ipproto = IPPROTO_UDP;
-- break;
-- case 'R':
-- proto_count++;
-- cfg_proto = SOCK_RAW;
-- cfg_ipproto = IPPROTO_RAW;
-- break;
-- case 'u':
-- proto_count++;
-- cfg_proto = SOCK_DGRAM;
-- cfg_ipproto = IPPROTO_UDP;
-- break;
-- case 'l':
-- cfg_payload_len = strtoul(optarg, NULL, 10);
-- break;
-- case 'p':
-- dest_port = strtoul(optarg, NULL, 10);
-- break;
-- case 'x':
-- cfg_show_payload = true;
-- break;
-- case 'h':
-- default:
-- usage(argv[0]);
-- }
-- }
--
-- if (!cfg_payload_len)
-- error(1, 0, "payload may not be nonzero");
-- if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
-- error(1, 0, "udp packet might exceed expected MTU");
-- if (!do_ipv4 && !do_ipv6)
-- error(1, 0, "pass -4 or -6, not both");
-- if (proto_count > 1)
-- error(1, 0, "pass -r, -R or -u, not multiple");
--
-- if (optind != argc - 1)
-- error(1, 0, "missing required hostname argument");
--}
--
--static void resolve_hostname(const char *hostname)
--{
-- struct addrinfo *addrs, *cur;
-- int have_ipv4 = 0, have_ipv6 = 0;
--
-- if (getaddrinfo(hostname, NULL, NULL, &addrs))
-- error(1, errno, "getaddrinfo");
--
-- cur = addrs;
-- while (cur && !have_ipv4 && !have_ipv6) {
-- if (!have_ipv4 && cur->ai_family == AF_INET) {
-- memcpy(&daddr, cur->ai_addr, sizeof(daddr));
-- daddr.sin_port = htons(dest_port);
-- have_ipv4 = 1;
-- }
-- else if (!have_ipv6 && cur->ai_family == AF_INET6) {
-- memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
-- daddr6.sin6_port = htons(dest_port);
-- have_ipv6 = 1;
-- }
-- cur = cur->ai_next;
-- }
-- if (addrs)
-- freeaddrinfo(addrs);
--
-- do_ipv4 &= have_ipv4;
-- do_ipv6 &= have_ipv6;
--}
--
--static void do_main(int family)
--{
-- fprintf(stderr, "family: %s\n",
-- family == PF_INET ? "INET" : "INET6");
--
-- fprintf(stderr, "test SND\n");
-- do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
--
-- fprintf(stderr, "test ENQ\n");
-- do_test(family, SOF_TIMESTAMPING_TX_SCHED);
--
-- fprintf(stderr, "test ENQ + SND\n");
-- do_test(family, SOF_TIMESTAMPING_TX_SCHED |
-- SOF_TIMESTAMPING_TX_SOFTWARE);
--
-- if (cfg_proto == SOCK_STREAM) {
-- fprintf(stderr, "\ntest ACK\n");
-- do_test(family, SOF_TIMESTAMPING_TX_ACK);
--
-- fprintf(stderr, "\ntest SND + ACK\n");
-- do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
-- SOF_TIMESTAMPING_TX_ACK);
--
-- fprintf(stderr, "\ntest ENQ + SND + ACK\n");
-- do_test(family, SOF_TIMESTAMPING_TX_SCHED |
-- SOF_TIMESTAMPING_TX_SOFTWARE |
-- SOF_TIMESTAMPING_TX_ACK);
-- }
--}
--
--const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
--
--int main(int argc, char **argv)
--{
-- if (argc == 1)
-- usage(argv[0]);
--
-- parse_opt(argc, argv);
-- resolve_hostname(argv[argc - 1]);
--
-- fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]);
-- fprintf(stderr, "payload: %u\n", cfg_payload_len);
-- fprintf(stderr, "server port: %u\n", dest_port);
-- fprintf(stderr, "\n");
--
-- if (do_ipv4)
-- do_main(PF_INET);
-- if (do_ipv6)
-- do_main(PF_INET6);
--
-- return 0;
--}
-diff --git a/Makefile b/Makefile
-index 6b30551caee4..082f82471b51 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 167
-+SUBLEVEL = 168
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
-index a95499ea8706..fa1d41edce68 100644
---- a/arch/arm/mach-omap1/board-ams-delta.c
-+++ b/arch/arm/mach-omap1/board-ams-delta.c
-@@ -511,6 +511,9 @@ static void modem_pm(struct uart_port *port, unsigned int state, unsigned old)
- {
- struct modem_private_data *priv = port->private_data;
-
-+ if (!priv)
-+ return;
-+
- if (IS_ERR(priv->regulator))
- return;
-
-diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
-index 30768003f854..8c505284bc0c 100644
---- a/arch/arm/mach-omap2/prm44xx.c
-+++ b/arch/arm/mach-omap2/prm44xx.c
-@@ -344,7 +344,7 @@ static void omap44xx_prm_reconfigure_io_chain(void)
- * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
- * omap44xx_prm_reconfigure_io_chain() must be called. No return value.
- */
--static void __init omap44xx_prm_enable_io_wakeup(void)
-+static void omap44xx_prm_enable_io_wakeup(void)
- {
- s32 inst = omap4_prmst_get_prm_dev_inst();
-
-diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
-index 877da1908234..98e2a5dbcfda 100644
---- a/arch/cris/arch-v32/drivers/cryptocop.c
-+++ b/arch/cris/arch-v32/drivers/cryptocop.c
-@@ -2724,7 +2724,6 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
- (unsigned long int)(oper.indata + prev_ix),
- noinpages,
- 0, /* read access only for in data */
-- 0, /* no force */
- inpages,
- NULL);
-
-@@ -2740,8 +2739,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
- current->mm,
- (unsigned long int)oper.cipher_outdata,
- nooutpages,
-- 1, /* write access for out data */
-- 0, /* no force */
-+ FOLL_WRITE, /* write access for out data */
- outpages,
- NULL);
- up_read(¤t->mm->mmap_sem);
-diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
-index 0c161ed6d18e..8205b456de7a 100644
---- a/arch/ia64/kernel/err_inject.c
-+++ b/arch/ia64/kernel/err_inject.c
-@@ -143,7 +143,7 @@ store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
- int ret;
-
- ret = get_user_pages(current, current->mm, virt_addr,
-- 1, VM_READ, 0, NULL, NULL);
-+ 1, FOLL_WRITE, NULL, NULL);
- if (ret<=0) {
- #ifdef ERR_INJ_DEBUG
- printk("Virtual address %lx is not existing.\n",virt_addr);
-diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c
-index 349995d19c7f..e596e0a1cecc 100644
---- a/arch/mips/mm/gup.c
-+++ b/arch/mips/mm/gup.c
-@@ -303,7 +303,7 @@ slow_irqon:
-
- ret = get_user_pages_unlocked(current, mm, start,
- (end - start) >> PAGE_SHIFT,
-- write, 0, pages);
-+ pages, write ? FOLL_WRITE : 0);
-
- /* Have to be a bit careful with return values */
- if (nr > 0) {
-diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
-index 929c147e07b4..1b69bfdf59f9 100644
---- a/arch/s390/kernel/perf_cpum_cf.c
-+++ b/arch/s390/kernel/perf_cpum_cf.c
-@@ -344,6 +344,8 @@ static int __hw_perf_event_init(struct perf_event *event)
- break;
-
- case PERF_TYPE_HARDWARE:
-+ if (is_sampling_event(event)) /* No sampling support */
-+ return -ENOENT;
- ev = attr->config;
- /* Count user space (problem-state) only */
- if (!attr->exclude_user && attr->exclude_kernel) {
-diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
-index 12bbf0e8478f..7ad41be8b373 100644
---- a/arch/s390/mm/gup.c
-+++ b/arch/s390/mm/gup.c
-@@ -242,7 +242,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
- start += nr << PAGE_SHIFT;
- pages += nr;
- ret = get_user_pages_unlocked(current, mm, start,
-- nr_pages - nr, write, 0, pages);
-+ nr_pages - nr, pages, write ? FOLL_WRITE : 0);
- /* Have to be a bit careful with return values */
- if (nr > 0)
- ret = (ret < 0) ? nr : ret + nr;
-diff --git a/arch/sh/mm/gup.c b/arch/sh/mm/gup.c
-index e7af6a65baab..8c51a0e94854 100644
---- a/arch/sh/mm/gup.c
-+++ b/arch/sh/mm/gup.c
-@@ -258,7 +258,8 @@ slow_irqon:
- pages += nr;
-
- ret = get_user_pages_unlocked(current, mm, start,
-- (end - start) >> PAGE_SHIFT, write, 0, pages);
-+ (end - start) >> PAGE_SHIFT, pages,
-+ write ? FOLL_WRITE : 0);
-
- /* Have to be a bit careful with return values */
- if (nr > 0) {
-diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
-index 2e5c4fc2daa9..150f48303fb0 100644
---- a/arch/sparc/mm/gup.c
-+++ b/arch/sparc/mm/gup.c
-@@ -250,7 +250,8 @@ slow:
- pages += nr;
-
- ret = get_user_pages_unlocked(current, mm, start,
-- (end - start) >> PAGE_SHIFT, write, 0, pages);
-+ (end - start) >> PAGE_SHIFT, pages,
-+ write ? FOLL_WRITE : 0);
-
- /* Have to be a bit careful with return values */
- if (nr > 0) {
-diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
-index 3a37cdbdfbaa..c048d0d70cc4 100644
---- a/arch/x86/include/asm/kvm_host.h
-+++ b/arch/x86/include/asm/kvm_host.h
-@@ -765,7 +765,7 @@ struct kvm_x86_ops {
- int (*hardware_setup)(void); /* __init */
- void (*hardware_unsetup)(void); /* __exit */
- bool (*cpu_has_accelerated_tpr)(void);
-- bool (*cpu_has_high_real_mode_segbase)(void);
-+ bool (*has_emulated_msr)(int index);
- void (*cpuid_update)(struct kvm_vcpu *vcpu);
-
- /* Create, but do not attach this VCPU */
-diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
-index d788b0cdc0ad..6f8eadf0681f 100644
---- a/arch/x86/include/asm/uaccess.h
-+++ b/arch/x86/include/asm/uaccess.h
-@@ -144,9 +144,14 @@ extern int __get_user_4(void);
- extern int __get_user_8(void);
- extern int __get_user_bad(void);
-
- #define __uaccess_begin() stac()
- #define __uaccess_end() clac()
-+#define __uaccess_begin_nospec() \
-+({ \
-+ stac(); \
-+ barrier_nospec(); \
-+})
-
- /*
- * This is a type: either unsigned long, if the argument fits into
- * that type, or otherwise unsigned long long.
-@@ -423,9 +428,9 @@ do { \
- ({ \
- int __gu_err; \
- unsigned long __gu_val; \
-- __uaccess_begin(); \
-+ __uaccess_begin_nospec(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err, -EFAULT); \
- __uaccess_end(); \
- (x) = (__force __typeof__(*(ptr)))__gu_val; \
- __builtin_expect(__gu_err, 0); \
- })
-@@ -471,11 +476,15 @@ struct __large_struct { unsigned long buf[100]; };
- */
- #define uaccess_try do { \
- current_thread_info()->uaccess_err = 0; \
- __uaccess_begin(); \
- barrier();
-
-+#define uaccess_try_nospec do { \
-+ current_thread_info()->uaccess_err = 0; \
-+ __uaccess_begin_nospec(); \
-+
- #define uaccess_catch(err) \
- __uaccess_end(); \
- (err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \
- } while (0)
-
-@@ -537,7 +546,7 @@ struct __large_struct { unsigned long buf[100]; };
- * get_user_ex(...);
- * } get_user_catch(err)
- */
--#define get_user_try uaccess_try
-+#define get_user_try uaccess_try_nospec
- #define get_user_catch(err) uaccess_catch(err)
-
- #define get_user_ex(x, ptr) do { \
-@@ -572,12 +581,12 @@ extern void __cmpxchg_wrong_size(void)
- __typeof__(ptr) __uval = (uval); \
- __typeof__(*(ptr)) __old = (old); \
- __typeof__(*(ptr)) __new = (new); \
-- __uaccess_begin(); \
-+ __uaccess_begin_nospec(); \
- switch (size) { \
- case 1: \
- { \
- asm volatile("\n" \
- "1:\t" LOCK_PREFIX "cmpxchgb %4, %2\n" \
- "2:\n" \
- "\t.section .fixup, \"ax\"\n" \
- "3:\tmov %3, %0\n" \
- "\tjmp 2b\n" \
-diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
-index f5dcb5204dcd..f575ee3aea5c 100644
---- a/arch/x86/include/asm/uaccess_32.h
-+++ b/arch/x86/include/asm/uaccess_32.h
-@@ -102,19 +102,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
-
- switch (n) {
- case 1:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_size(*(u8 *)to, from, 1, ret, 1);
- __uaccess_end();
- return ret;
- case 2:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_size(*(u16 *)to, from, 2, ret, 2);
- __uaccess_end();
- return ret;
- case 4:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_size(*(u32 *)to, from, 4, ret, 4);
- __uaccess_end();
- return ret;
- }
- }
-@@ -130,19 +130,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
-
- switch (n) {
- case 1:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_size(*(u8 *)to, from, 1, ret, 1);
- __uaccess_end();
- return ret;
- case 2:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_size(*(u16 *)to, from, 2, ret, 2);
- __uaccess_end();
- return ret;
- case 4:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_size(*(u32 *)to, from, 4, ret, 4);
- __uaccess_end();
- return ret;
- }
- }
-diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
-index d83a55b95a48..dc2d00e7ced3 100644
---- a/arch/x86/include/asm/uaccess_64.h
-+++ b/arch/x86/include/asm/uaccess_64.h
-@@ -57,49 +57,49 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
- if (!__builtin_constant_p(size))
- return copy_user_generic(dst, (__force void *)src, size);
- switch (size) {
- case 1:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(*(u8 *)dst, (u8 __user *)src,
- ret, "b", "b", "=q", 1);
- __uaccess_end();
- return ret;
- case 2:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(*(u16 *)dst, (u16 __user *)src,
- ret, "w", "w", "=r", 2);
- __uaccess_end();
- return ret;
- case 4:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(*(u32 *)dst, (u32 __user *)src,
- ret, "l", "k", "=r", 4);
- __uaccess_end();
- return ret;
- case 8:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 8);
- __uaccess_end();
- return ret;
- case 10:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 10);
- if (likely(!ret))
- __get_user_asm(*(u16 *)(8 + (char *)dst),
- (u16 __user *)(8 + (char __user *)src),
- ret, "w", "w", "=r", 2);
- __uaccess_end();
- return ret;
- case 16:
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(*(u64 *)dst, (u64 __user *)src,
- ret, "q", "", "=r", 16);
- if (likely(!ret))
- __get_user_asm(*(u64 *)(8 + (char *)dst),
- (u64 __user *)(8 + (char __user *)src),
- ret, "q", "", "=r", 8);
- __uaccess_end();
- return ret;
- default:
- return copy_user_generic(dst, (__force void *)src, size);
-@@ -192,47 +192,47 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
- switch (size) {
- case 1: {
- u8 tmp;
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(tmp, (u8 __user *)src,
- ret, "b", "b", "=q", 1);
- if (likely(!ret))
- __put_user_asm(tmp, (u8 __user *)dst,
- ret, "b", "b", "iq", 1);
- __uaccess_end();
- return ret;
- }
- case 2: {
- u16 tmp;
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(tmp, (u16 __user *)src,
- ret, "w", "w", "=r", 2);
- if (likely(!ret))
- __put_user_asm(tmp, (u16 __user *)dst,
- ret, "w", "w", "ir", 2);
- __uaccess_end();
- return ret;
- }
-
- case 4: {
- u32 tmp;
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(tmp, (u32 __user *)src,
- ret, "l", "k", "=r", 4);
- if (likely(!ret))
- __put_user_asm(tmp, (u32 __user *)dst,
- ret, "l", "k", "ir", 4);
- __uaccess_end();
- return ret;
- }
- case 8: {
- u64 tmp;
-- __uaccess_begin();
-+ __uaccess_begin_nospec();
- __get_user_asm(tmp, (u64 __user *)src,
- ret, "q", "", "=r", 8);
- if (likely(!ret))
- __put_user_asm(tmp, (u64 __user *)dst,
- ret, "q", "", "er", 8);
- __uaccess_end();
- return ret;
- }
- default:
-diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
-index b12c0287d6cf..e8b46f575306 100644
---- a/arch/x86/kernel/cpu/common.c
-+++ b/arch/x86/kernel/cpu/common.c
-@@ -693,7 +693,8 @@ static void init_speculation_control(struct cpuinfo_x86 *c)
- if (cpu_has(c, X86_FEATURE_INTEL_STIBP))
- set_cpu_cap(c, X86_FEATURE_STIBP);
-
-- if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD))
-+ if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD) ||
-+ cpu_has(c, X86_FEATURE_VIRT_SSBD))
- set_cpu_cap(c, X86_FEATURE_SSBD);
-
- if (cpu_has(c, X86_FEATURE_AMD_IBRS)) {
-diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
-index 338d13d4fd2f..b857bb9f6f23 100644
---- a/arch/x86/kvm/cpuid.c
-+++ b/arch/x86/kvm/cpuid.c
-@@ -341,6 +341,10 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
- F(3DNOWPREFETCH) | F(OSVW) | 0 /* IBS */ | F(XOP) |
- 0 /* SKINIT, WDT, LWP */ | F(FMA4) | F(TBM);
-
-+ /* cpuid 0x80000008.ebx */
-+ const u32 kvm_cpuid_8000_0008_ebx_x86_features =
-+ F(AMD_IBPB) | F(AMD_IBRS) | F(VIRT_SSBD);
-+
- /* cpuid 0xC0000001.edx */
- const u32 kvm_supported_word5_x86_features =
- F(XSTORE) | F(XSTORE_EN) | F(XCRYPT) | F(XCRYPT_EN) |
-@@ -358,6 +362,10 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
- const u32 kvm_supported_word10_x86_features =
- F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | f_xsaves;
-
-+ /* cpuid 7.0.edx*/
-+ const u32 kvm_cpuid_7_0_edx_x86_features =
-+ F(SPEC_CTRL) | F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES);
-+
- /* all calls to cpuid_count() should be made on the same cpu */
- get_cpu();
-
-@@ -435,11 +443,14 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
- cpuid_mask(&entry->ebx, 9);
- // TSC_ADJUST is emulated
- entry->ebx |= F(TSC_ADJUST);
-- } else
-+ entry->edx &= kvm_cpuid_7_0_edx_x86_features;
-+ cpuid_mask(&entry->edx, CPUID_7_EDX);
-+ } else {
- entry->ebx = 0;
-+ entry->edx = 0;
-+ }
- entry->eax = 0;
- entry->ecx = 0;
-- entry->edx = 0;
- break;
- }
- case 9:
-@@ -583,7 +594,21 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
- if (!g_phys_as)
- g_phys_as = phys_as;
- entry->eax = g_phys_as | (virt_as << 8);
-- entry->ebx = entry->edx = 0;
-+ entry->edx = 0;
-+ /*
-+ * IBRS, IBPB and VIRT_SSBD aren't necessarily present in
-+ * hardware cpuid
-+ */
-+ if (boot_cpu_has(X86_FEATURE_AMD_IBPB))
-+ entry->ebx |= F(AMD_IBPB);
-+ if (boot_cpu_has(X86_FEATURE_AMD_IBRS))
-+ entry->ebx |= F(AMD_IBRS);
-+ if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
-+ entry->ebx |= F(VIRT_SSBD);
-+ entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features;
-+ cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX);
-+ if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
-+ entry->ebx |= F(VIRT_SSBD);
- break;
- }
- case 0x80000019:
-diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
-index d1534feefcfe..72f159f4d456 100644
---- a/arch/x86/kvm/cpuid.h
-+++ b/arch/x86/kvm/cpuid.h
-@@ -159,6 +159,46 @@ static inline bool guest_cpuid_has_rdtscp(struct kvm_vcpu *vcpu)
- return best && (best->edx & bit(X86_FEATURE_RDTSCP));
- }
-
-+static inline bool guest_cpuid_has_ibpb(struct kvm_vcpu *vcpu)
-+{
-+ struct kvm_cpuid_entry2 *best;
-+
-+ best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
-+ if (best && (best->ebx & bit(X86_FEATURE_AMD_IBPB)))
-+ return true;
-+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
-+ return best && (best->edx & bit(X86_FEATURE_SPEC_CTRL));
-+}
-+
-+static inline bool guest_cpuid_has_spec_ctrl(struct kvm_vcpu *vcpu)
-+{
-+ struct kvm_cpuid_entry2 *best;
-+
-+ best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
-+ if (best && (best->ebx & bit(X86_FEATURE_AMD_IBRS)))
-+ return true;
-+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
-+ return best && (best->edx & (bit(X86_FEATURE_SPEC_CTRL) | bit(X86_FEATURE_SPEC_CTRL_SSBD)));
-+}
-+
-+static inline bool guest_cpuid_has_arch_capabilities(struct kvm_vcpu *vcpu)
-+{
-+ struct kvm_cpuid_entry2 *best;
-+
-+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
-+ return best && (best->edx & bit(X86_FEATURE_ARCH_CAPABILITIES));
-+}
-+
-+static inline bool guest_cpuid_has_virt_ssbd(struct kvm_vcpu *vcpu)
-+{
-+ struct kvm_cpuid_entry2 *best;
-+
-+ best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
-+ return best && (best->ebx & bit(X86_FEATURE_VIRT_SSBD));
-+}
-+
-+
-+
- /*
- * NRIPS is provided through cpuidfn 0x8000000a.edx bit 3
- */
-diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
-index a1afd80a68aa..3c70f6c76d3a 100644
---- a/arch/x86/kvm/lapic.c
-+++ b/arch/x86/kvm/lapic.c
-@@ -56,7 +56,7 @@
- #define APIC_BUS_CYCLE_NS 1
-
- /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */
--#define apic_debug(fmt, arg...)
-+#define apic_debug(fmt, arg...) do {} while (0)
-
- #define APIC_LVT_NUM 6
- /* 14 is the version for Xeon and Pentium 8.4.8*/
-diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
-index df7827a981dd..ecdf724da371 100644
---- a/arch/x86/kvm/svm.c
-+++ b/arch/x86/kvm/svm.c
-@@ -37,6 +37,7 @@
- #include
- #include
- #include
-+#include
- #include
-
- #include
-@@ -147,6 +148,14 @@ struct vcpu_svm {
- u64 gs_base;
- } host;
-
-+ u64 spec_ctrl;
-+ /*
-+ * Contains guest-controlled bits of VIRT_SPEC_CTRL, which will be
-+ * translated into the appropriate L2_CFG bits on the host to
-+ * perform speculative control.
-+ */
-+ u64 virt_spec_ctrl;
-+
- u32 *msrpm;
-
- ulong nmi_iret_rip;
-@@ -182,6 +191,8 @@ static const struct svm_direct_access_msrs {
- { .index = MSR_CSTAR, .always = true },
- { .index = MSR_SYSCALL_MASK, .always = true },
- #endif
-+ { .index = MSR_IA32_SPEC_CTRL, .always = false },
-+ { .index = MSR_IA32_PRED_CMD, .always = false },
- { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
- { .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
- { .index = MSR_IA32_LASTINTFROMIP, .always = false },
-@@ -411,6 +422,7 @@ struct svm_cpu_data {
- struct kvm_ldttss_desc *tss_desc;
-
- struct page *save_area;
-+ struct vmcb *current_vmcb;
- };
-
- static DEFINE_PER_CPU(struct svm_cpu_data *, svm_data);
-@@ -762,6 +774,25 @@ static bool valid_msr_intercept(u32 index)
- return false;
- }
-
-+static bool msr_write_intercepted(struct kvm_vcpu *vcpu, unsigned msr)
-+{
-+ u8 bit_write;
-+ unsigned long tmp;
-+ u32 offset;
-+ u32 *msrpm;
-+
-+ msrpm = is_guest_mode(vcpu) ? to_svm(vcpu)->nested.msrpm:
-+ to_svm(vcpu)->msrpm;
-+
-+ offset = svm_msrpm_offset(msr);
-+ bit_write = 2 * (msr & 0x0f) + 1;
-+ tmp = msrpm[offset];
-+
-+ BUG_ON(offset == MSR_INVALID);
-+
-+ return !!test_bit(bit_write, &tmp);
-+}
-+
- static void set_msr_interception(u32 *msrpm, unsigned msr,
- int read, int write)
- {
-@@ -1120,6 +1151,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
- u32 dummy;
- u32 eax = 1;
-
-+ svm->spec_ctrl = 0;
-+ svm->virt_spec_ctrl = 0;
-+
- if (!init_event) {
- svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
- MSR_IA32_APICBASE_ENABLE;
-@@ -1210,11 +1244,17 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
- __free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
- kvm_vcpu_uninit(vcpu);
- kmem_cache_free(kvm_vcpu_cache, svm);
-+ /*
-+ * The vmcb page can be recycled, causing a false negative in
-+ * svm_vcpu_load(). So do a full IBPB now.
-+ */
-+ indirect_branch_prediction_barrier();
- }
-
- static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
- {
- struct vcpu_svm *svm = to_svm(vcpu);
-+ struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
- int i;
-
- if (unlikely(cpu != vcpu->cpu)) {
-@@ -1239,6 +1279,10 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
- wrmsrl(MSR_AMD64_TSC_RATIO, tsc_ratio);
- }
- }
-+ if (sd->current_vmcb != svm->vmcb) {
-+ sd->current_vmcb = svm->vmcb;
-+ indirect_branch_prediction_barrier();
-+ }
- }
-
- static void svm_vcpu_put(struct kvm_vcpu *vcpu)
-@@ -3051,6 +3095,20 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
- case MSR_VM_CR:
- msr_info->data = svm->nested.vm_cr_msr;
- break;
-+ case MSR_IA32_SPEC_CTRL:
-+ if (!msr_info->host_initiated &&
-+ !guest_cpuid_has_spec_ctrl(vcpu))
-+ return 1;
-+
-+ msr_info->data = svm->spec_ctrl;
-+ break;
-+ case MSR_AMD64_VIRT_SPEC_CTRL:
-+ if (!msr_info->host_initiated &&
-+ !guest_cpuid_has_virt_ssbd(vcpu))
-+ return 1;
-+
-+ msr_info->data = svm->virt_spec_ctrl;
-+ break;
- case MSR_IA32_UCODE_REV:
- msr_info->data = 0x01000065;
- break;
-@@ -3125,6 +3183,59 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
- case MSR_IA32_TSC:
- kvm_write_tsc(vcpu, msr);
- break;
-+ case MSR_IA32_SPEC_CTRL:
-+ if (!msr->host_initiated &&
-+ !guest_cpuid_has_spec_ctrl(vcpu))
-+ return 1;
-+
-+ /* The STIBP bit doesn't fault even if it's not advertised */
-+ if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP))
-+ return 1;
-+
-+ svm->spec_ctrl = data;
-+
-+ if (!data)
-+ break;
-+
-+ /*
-+ * For non-nested:
-+ * When it's written (to non-zero) for the first time, pass
-+ * it through.
-+ *
-+ * For nested:
-+ * The handling of the MSR bitmap for L2 guests is done in
-+ * nested_svm_vmrun_msrpm.
-+ * We update the L1 MSR bit as well since it will end up
-+ * touching the MSR anyway now.
-+ */
-+ set_msr_interception(svm->msrpm, MSR_IA32_SPEC_CTRL, 1, 1);
-+ break;
-+ case MSR_IA32_PRED_CMD:
-+ if (!msr->host_initiated &&
-+ !guest_cpuid_has_ibpb(vcpu))
-+ return 1;
-+
-+ if (data & ~PRED_CMD_IBPB)
-+ return 1;
-+
-+ if (!data)
-+ break;
-+
-+ wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
-+ if (is_guest_mode(vcpu))
-+ break;
-+ set_msr_interception(svm->msrpm, MSR_IA32_PRED_CMD, 0, 1);
-+ break;
-+ case MSR_AMD64_VIRT_SPEC_CTRL:
-+ if (!msr->host_initiated &&
-+ !guest_cpuid_has_virt_ssbd(vcpu))
-+ return 1;
-+
-+ if (data & ~SPEC_CTRL_SSBD)
-+ return 1;
-+
-+ svm->virt_spec_ctrl = data;
-+ break;
- case MSR_STAR:
- svm->vmcb->save.star = data;
- break;
-@@ -3811,6 +3922,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
-
- local_irq_enable();
-
-+ /*
-+ * If this vCPU has touched SPEC_CTRL, restore the guest's value if
-+ * it's non-zero. Since vmentry is serialising on affected CPUs, there
-+ * is no need to worry about the conditional branch over the wrmsr
-+ * being speculatively taken.
-+ */
-+ x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
-+
- asm volatile (
- "push %%" _ASM_BP "; \n\t"
- "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
-@@ -3915,6 +4034,26 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
- #endif
- #endif
-
-+ /*
-+ * We do not use IBRS in the kernel. If this vCPU has used the
-+ * SPEC_CTRL MSR it may have left it on; save the value and
-+ * turn it off. This is much more efficient than blindly adding
-+ * it to the atomic save/restore list. Especially as the former
-+ * (Saving guest MSRs on vmexit) doesn't even exist in KVM.
-+ *
-+ * For non-nested case:
-+ * If the L01 MSR bitmap does not intercept the MSR, then we need to
-+ * save it.
-+ *
-+ * For nested case:
-+ * If the L02 MSR bitmap does not intercept the MSR, then we need to
-+ * save it.
-+ */
-+ if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))
-+ svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
-+
-+ x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
-+
- reload_tss(vcpu);
-
- local_irq_disable();
-@@ -4015,7 +4154,7 @@ static bool svm_cpu_has_accelerated_tpr(void)
- return false;
- }
-
--static bool svm_has_high_real_mode_segbase(void)
-+static bool svm_has_emulated_msr(int index)
- {
- return true;
- }
-@@ -4299,7 +4438,7 @@ static struct kvm_x86_ops svm_x86_ops = {
- .hardware_enable = svm_hardware_enable,
- .hardware_disable = svm_hardware_disable,
- .cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
-- .cpu_has_high_real_mode_segbase = svm_has_high_real_mode_segbase,
-+ .has_emulated_msr = svm_has_emulated_msr,
-
- .vcpu_create = svm_create_vcpu,
- .vcpu_free = svm_free_vcpu,
-diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
-index c5a4b1978cbf..e4b5fd72ca24 100644
---- a/arch/x86/kvm/vmx.c
-+++ b/arch/x86/kvm/vmx.c
-@@ -48,6 +48,7 @@
- #include
- #include
- #include
-+#include
- #include
-
- #include "trace.h"
-@@ -109,6 +110,14 @@ static u64 __read_mostly host_xss;
- static bool __read_mostly enable_pml = 1;
- module_param_named(pml, enable_pml, bool, S_IRUGO);
-
-+#define MSR_TYPE_R 1
-+#define MSR_TYPE_W 2
-+#define MSR_TYPE_RW 3
-+
-+#define MSR_BITMAP_MODE_X2APIC 1
-+#define MSR_BITMAP_MODE_X2APIC_APICV 2
-+#define MSR_BITMAP_MODE_LM 4
-+
- #define KVM_VMX_TSC_MULTIPLIER_MAX 0xffffffffffffffffULL
-
- #define KVM_GUEST_CR0_MASK (X86_CR0_NW | X86_CR0_CD)
-@@ -172,7 +181,6 @@ module_param(ple_window_max, int, S_IRUGO);
- extern const ulong vmx_return;
-
- #define NR_AUTOLOAD_MSRS 8
--#define VMCS02_POOL_SIZE 1
-
- struct vmcs {
- u32 revision_id;
-@@ -189,6 +197,7 @@ struct loaded_vmcs {
- struct vmcs *vmcs;
- int cpu;
- int launched;
-+ unsigned long *msr_bitmap;
- struct list_head loaded_vmcss_on_cpu_link;
- };
-
-@@ -205,7 +214,7 @@ struct shared_msr_entry {
- * stored in guest memory specified by VMPTRLD, but is opaque to the guest,
- * which must access it using VMREAD/VMWRITE/VMCLEAR instructions.
- * More than one of these structures may exist, if L1 runs multiple L2 guests.
-- * nested_vmx_run() will use the data here to build a vmcs02: a VMCS for the
-+ * nested_vmx_run() will use the data here to build the vmcs02: a VMCS for the
- * underlying hardware which will be used to run L2.
- * This structure is packed to ensure that its layout is identical across
- * machines (necessary for live migration).
-@@ -384,13 +393,6 @@ struct __packed vmcs12 {
- */
- #define VMCS12_SIZE 0x1000
-
--/* Used to remember the last vmcs02 used for some recently used vmcs12s */
--struct vmcs02_list {
-- struct list_head list;
-- gpa_t vmptr;
-- struct loaded_vmcs vmcs02;
--};
--
- /*
- * The nested_vmx structure is part of vcpu_vmx, and holds information we need
- * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
-@@ -412,16 +414,16 @@ struct nested_vmx {
- */
- bool sync_shadow_vmcs;
-
-- /* vmcs02_list cache of VMCSs recently used to run L2 guests */
-- struct list_head vmcs02_pool;
-- int vmcs02_num;
- u64 vmcs01_tsc_offset;
- bool change_vmcs01_virtual_x2apic_mode;
- /* L2 must run next, and mustn't decide to exit to L1. */
- bool nested_run_pending;
-+
-+ struct loaded_vmcs vmcs02;
-+
- /*
-- * Guest pages referred to in vmcs02 with host-physical pointers, so
-- * we must keep them pinned while L2 runs.
-+ * Guest pages referred to in the vmcs02 with host-physical
-+ * pointers, so we must keep them pinned while L2 runs.
- */
- struct page *apic_access_page;
- struct page *virtual_apic_page;
-@@ -531,6 +533,7 @@ struct vcpu_vmx {
- unsigned long host_rsp;
- u8 fail;
- bool nmi_known_unmasked;
-+ u8 msr_bitmap_mode;
- u32 exit_intr_info;
- u32 idt_vectoring_info;
- ulong rflags;
-@@ -542,6 +545,10 @@ struct vcpu_vmx {
- u64 msr_host_kernel_gs_base;
- u64 msr_guest_kernel_gs_base;
- #endif
-+
-+ u64 arch_capabilities;
-+ u64 spec_ctrl;
-+
- u32 vm_entry_controls_shadow;
- u32 vm_exit_controls_shadow;
- /*
-@@ -889,6 +896,9 @@ static void vmx_sync_pir_to_irr_dummy(struct kvm_vcpu *vcpu);
- static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx);
- static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx);
- static int alloc_identity_pagetable(struct kvm *kvm);
-+static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
-+static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
-+ u32 msr, int type);
-
- static DEFINE_PER_CPU(struct vmcs *, vmxarea);
- static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
-@@ -908,11 +918,6 @@ static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
-
- static unsigned long *vmx_io_bitmap_a;
- static unsigned long *vmx_io_bitmap_b;
--static unsigned long *vmx_msr_bitmap_legacy;
--static unsigned long *vmx_msr_bitmap_longmode;
--static unsigned long *vmx_msr_bitmap_legacy_x2apic;
--static unsigned long *vmx_msr_bitmap_longmode_x2apic;
--static unsigned long *vmx_msr_bitmap_nested;
- static unsigned long *vmx_vmread_bitmap;
- static unsigned long *vmx_vmwrite_bitmap;
-
-@@ -1689,6 +1694,52 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
- vmcs_write32(EXCEPTION_BITMAP, eb);
- }
-
-+/*
-+ * Check if MSR is intercepted for currently loaded MSR bitmap.
-+ */
-+static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
-+{
-+ unsigned long *msr_bitmap;
-+ int f = sizeof(unsigned long);
-+
-+ if (!cpu_has_vmx_msr_bitmap())
-+ return true;
-+
-+ msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap;
-+
-+ if (msr <= 0x1fff) {
-+ return !!test_bit(msr, msr_bitmap + 0x800 / f);
-+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
-+ msr &= 0x1fff;
-+ return !!test_bit(msr, msr_bitmap + 0xc00 / f);
-+ }
-+
-+ return true;
-+}
-+
-+/*
-+ * Check if MSR is intercepted for L01 MSR bitmap.
-+ */
-+static bool msr_write_intercepted_l01(struct kvm_vcpu *vcpu, u32 msr)
-+{
-+ unsigned long *msr_bitmap;
-+ int f = sizeof(unsigned long);
-+
-+ if (!cpu_has_vmx_msr_bitmap())
-+ return true;
-+
-+ msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap;
-+
-+ if (msr <= 0x1fff) {
-+ return !!test_bit(msr, msr_bitmap + 0x800 / f);
-+ } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
-+ msr &= 0x1fff;
-+ return !!test_bit(msr, msr_bitmap + 0xc00 / f);
-+ }
-+
-+ return true;
-+}
-+
- static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx,
- unsigned long entry, unsigned long exit)
- {
-@@ -2074,6 +2125,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
- if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
- per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
- vmcs_load(vmx->loaded_vmcs->vmcs);
-+ indirect_branch_prediction_barrier();
- }
-
- if (vmx->loaded_vmcs->cpu != cpu) {
-@@ -2353,27 +2405,6 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to)
- vmx->guest_msrs[from] = tmp;
- }
-
--static void vmx_set_msr_bitmap(struct kvm_vcpu *vcpu)
--{
-- unsigned long *msr_bitmap;
--
-- if (is_guest_mode(vcpu))
-- msr_bitmap = vmx_msr_bitmap_nested;
-- else if (vcpu->arch.apic_base & X2APIC_ENABLE) {
-- if (is_long_mode(vcpu))
-- msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
-- else
-- msr_bitmap = vmx_msr_bitmap_legacy_x2apic;
-- } else {
-- if (is_long_mode(vcpu))
-- msr_bitmap = vmx_msr_bitmap_longmode;
-- else
-- msr_bitmap = vmx_msr_bitmap_legacy;
-- }
--
-- vmcs_write64(MSR_BITMAP, __pa(msr_bitmap));
--}
--
- /*
- * Set up the vmcs to automatically save and restore system
- * msrs. Don't touch the 64-bit msrs if the guest is in legacy
-@@ -2414,7 +2445,7 @@ static void setup_msrs(struct vcpu_vmx *vmx)
- vmx->save_nmsrs = save_nmsrs;
-
- if (cpu_has_vmx_msr_bitmap())
-- vmx_set_msr_bitmap(&vmx->vcpu);
-+ vmx_update_msr_bitmap(&vmx->vcpu);
- }
-
- /*
-@@ -2828,6 +2859,19 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
- case MSR_IA32_TSC:
- msr_info->data = guest_read_tsc(vcpu);
- break;
-+ case MSR_IA32_SPEC_CTRL:
-+ if (!msr_info->host_initiated &&
-+ !guest_cpuid_has_spec_ctrl(vcpu))
-+ return 1;
-+
-+ msr_info->data = to_vmx(vcpu)->spec_ctrl;
-+ break;
-+ case MSR_IA32_ARCH_CAPABILITIES:
-+ if (!msr_info->host_initiated &&
-+ !guest_cpuid_has_arch_capabilities(vcpu))
-+ return 1;
-+ msr_info->data = to_vmx(vcpu)->arch_capabilities;
-+ break;
- case MSR_IA32_SYSENTER_CS:
- msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
- break;
-@@ -2927,6 +2971,68 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
- case MSR_IA32_TSC:
- kvm_write_tsc(vcpu, msr_info);
- break;
-+ case MSR_IA32_SPEC_CTRL:
-+ if (!msr_info->host_initiated &&
-+ !guest_cpuid_has_spec_ctrl(vcpu))
-+ return 1;
-+
-+ /* The STIBP bit doesn't fault even if it's not advertised */
-+ if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
-+ return 1;
-+
-+ vmx->spec_ctrl = data;
-+
-+ if (!data)
-+ break;
-+
-+ /*
-+ * For non-nested:
-+ * When it's written (to non-zero) for the first time, pass
-+ * it through.
-+ *
-+ * For nested:
-+ * The handling of the MSR bitmap for L2 guests is done in
-+ * nested_vmx_merge_msr_bitmap. We should not touch the
-+ * vmcs02.msr_bitmap here since it gets completely overwritten
-+ * in the merging. We update the vmcs01 here for L1 as well
-+ * since it will end up touching the MSR anyway now.
-+ */
-+ vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
-+ MSR_IA32_SPEC_CTRL,
-+ MSR_TYPE_RW);
-+ break;
-+ case MSR_IA32_PRED_CMD:
-+ if (!msr_info->host_initiated &&
-+ !guest_cpuid_has_ibpb(vcpu))
-+ return 1;
-+
-+ if (data & ~PRED_CMD_IBPB)
-+ return 1;
-+
-+ if (!data)
-+ break;
-+
-+ wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
-+
-+ /*
-+ * For non-nested:
-+ * When it's written (to non-zero) for the first time, pass
-+ * it through.
-+ *
-+ * For nested:
-+ * The handling of the MSR bitmap for L2 guests is done in
-+ * nested_vmx_merge_msr_bitmap. We should not touch the
-+ * vmcs02.msr_bitmap here since it gets completely overwritten
-+ * in the merging.
-+ */
-+ vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
-+ MSR_TYPE_W);
-+ break;
-+ case MSR_IA32_ARCH_CAPABILITIES:
-+ if (!msr_info->host_initiated)
-+ return 1;
-+ vmx->arch_capabilities = data;
-+ break;
- case MSR_IA32_CR_PAT:
- if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
- if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
-@@ -3352,11 +3458,6 @@ static struct vmcs *alloc_vmcs_cpu(int cpu)
- return vmcs;
- }
-
--static struct vmcs *alloc_vmcs(void)
--{
-- return alloc_vmcs_cpu(raw_smp_processor_id());
--}
--
- static void free_vmcs(struct vmcs *vmcs)
- {
- free_pages((unsigned long)vmcs, vmcs_config.order);
-@@ -3372,6 +3473,34 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
- loaded_vmcs_clear(loaded_vmcs);
- free_vmcs(loaded_vmcs->vmcs);
- loaded_vmcs->vmcs = NULL;
-+ if (loaded_vmcs->msr_bitmap)
-+ free_page((unsigned long)loaded_vmcs->msr_bitmap);
-+}
-+
-+static struct vmcs *alloc_vmcs(void)
-+{
-+ return alloc_vmcs_cpu(raw_smp_processor_id());
-+}
-+
-+static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
-+{
-+ loaded_vmcs->vmcs = alloc_vmcs();
-+ if (!loaded_vmcs->vmcs)
-+ return -ENOMEM;
-+
-+ loaded_vmcs_init(loaded_vmcs);
-+
-+ if (cpu_has_vmx_msr_bitmap()) {
-+ loaded_vmcs->msr_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
-+ if (!loaded_vmcs->msr_bitmap)
-+ goto out_vmcs;
-+ memset(loaded_vmcs->msr_bitmap, 0xff, PAGE_SIZE);
-+ }
-+ return 0;
-+
-+out_vmcs:
-+ free_loaded_vmcs(loaded_vmcs);
-+ return -ENOMEM;
- }
-
- static void free_kvm_area(void)
-@@ -4370,10 +4499,8 @@ static void free_vpid(int vpid)
- spin_unlock(&vmx_vpid_lock);
- }
-
--#define MSR_TYPE_R 1
--#define MSR_TYPE_W 2
--static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
-- u32 msr, int type)
-+static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
-+ u32 msr, int type)
- {
- int f = sizeof(unsigned long);
-
-@@ -4407,8 +4534,8 @@ static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
- }
- }
-
--static void __vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
-- u32 msr, int type)
-+static void __always_inline vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
-+ u32 msr, int type)
- {
- int f = sizeof(unsigned long);
-
-@@ -4488,37 +4615,76 @@ static void nested_vmx_disable_intercept_for_msr(unsigned long *msr_bitmap_l1,
- }
- }
-
--static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
-+static void __always_inline vmx_set_intercept_for_msr(unsigned long *msr_bitmap,
-+ u32 msr, int type, bool value)
- {
-- if (!longmode_only)
-- __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy,
-- msr, MSR_TYPE_R | MSR_TYPE_W);
-- __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode,
-- msr, MSR_TYPE_R | MSR_TYPE_W);
-+ if (value)
-+ vmx_enable_intercept_for_msr(msr_bitmap, msr, type);
-+ else
-+ vmx_disable_intercept_for_msr(msr_bitmap, msr, type);
- }
-
--static void vmx_enable_intercept_msr_read_x2apic(u32 msr)
-+static u8 vmx_msr_bitmap_mode(struct kvm_vcpu *vcpu)
- {
-- __vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
-- msr, MSR_TYPE_R);
-- __vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
-- msr, MSR_TYPE_R);
-+ u8 mode = 0;
-+
-+ if (irqchip_in_kernel(vcpu->kvm) && apic_x2apic_mode(vcpu->arch.apic)) {
-+ mode |= MSR_BITMAP_MODE_X2APIC;
-+ if (enable_apicv)
-+ mode |= MSR_BITMAP_MODE_X2APIC_APICV;
-+ }
-+
-+ if (is_long_mode(vcpu))
-+ mode |= MSR_BITMAP_MODE_LM;
-+
-+ return mode;
- }
-
--static void vmx_disable_intercept_msr_read_x2apic(u32 msr)
-+#define X2APIC_MSR(r) (APIC_BASE_MSR + ((r) >> 4))
-+
-+static void vmx_update_msr_bitmap_x2apic(unsigned long *msr_bitmap,
-+ u8 mode)
- {
-- __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
-- msr, MSR_TYPE_R);
-- __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
-- msr, MSR_TYPE_R);
-+ int msr;
-+
-+ for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
-+ unsigned word = msr / BITS_PER_LONG;
-+ msr_bitmap[word] = (mode & MSR_BITMAP_MODE_X2APIC_APICV) ? 0 : ~0;
-+ msr_bitmap[word + (0x800 / sizeof(long))] = ~0;
-+ }
-+
-+ if (mode & MSR_BITMAP_MODE_X2APIC) {
-+ /*
-+ * TPR reads and writes can be virtualized even if virtual interrupt
-+ * delivery is not in use.
-+ */
-+ vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_TASKPRI), MSR_TYPE_RW);
-+ if (mode & MSR_BITMAP_MODE_X2APIC_APICV) {
-+ vmx_enable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_ID), MSR_TYPE_R);
-+ vmx_enable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_TMCCT), MSR_TYPE_R);
-+ vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_EOI), MSR_TYPE_W);
-+ vmx_disable_intercept_for_msr(msr_bitmap, X2APIC_MSR(APIC_SELF_IPI), MSR_TYPE_W);
-+ }
-+ }
- }
-
--static void vmx_disable_intercept_msr_write_x2apic(u32 msr)
-+static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu)
- {
-- __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
-- msr, MSR_TYPE_W);
-- __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
-- msr, MSR_TYPE_W);
-+ struct vcpu_vmx *vmx = to_vmx(vcpu);
-+ unsigned long *msr_bitmap = vmx->vmcs01.msr_bitmap;
-+ u8 mode = vmx_msr_bitmap_mode(vcpu);
-+ u8 changed = mode ^ vmx->msr_bitmap_mode;
-+
-+ if (!changed)
-+ return;
-+
-+ vmx_set_intercept_for_msr(msr_bitmap, MSR_KERNEL_GS_BASE, MSR_TYPE_RW,
-+ !(mode & MSR_BITMAP_MODE_LM));
-+
-+ if (changed & (MSR_BITMAP_MODE_X2APIC | MSR_BITMAP_MODE_X2APIC_APICV))
-+ vmx_update_msr_bitmap_x2apic(msr_bitmap, mode);
-+
-+ vmx->msr_bitmap_mode = mode;
- }
-
- static int vmx_cpu_uses_apicv(struct kvm_vcpu *vcpu)
-@@ -4526,6 +4692,28 @@ static int vmx_cpu_uses_apicv(struct kvm_vcpu *vcpu)
- return enable_apicv && lapic_in_kernel(vcpu);
- }
-
-+static void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu)
-+{
-+ struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-+ gfn_t gfn;
-+
-+ /*
-+ * Don't need to mark the APIC access page dirty; it is never
-+ * written to by the CPU during APIC virtualization.
-+ */
-+
-+ if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
-+ gfn = vmcs12->virtual_apic_page_addr >> PAGE_SHIFT;
-+ kvm_vcpu_mark_page_dirty(vcpu, gfn);
-+ }
-+
-+ if (nested_cpu_has_posted_intr(vmcs12)) {
-+ gfn = vmcs12->posted_intr_desc_addr >> PAGE_SHIFT;
-+ kvm_vcpu_mark_page_dirty(vcpu, gfn);
-+ }
-+}
-+
-+
- static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
- {
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-@@ -4533,18 +4721,15 @@ static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
- void *vapic_page;
- u16 status;
-
-- if (vmx->nested.pi_desc &&
-- vmx->nested.pi_pending) {
-- vmx->nested.pi_pending = false;
-- if (!pi_test_and_clear_on(vmx->nested.pi_desc))
-- return;
--
-- max_irr = find_last_bit(
-- (unsigned long *)vmx->nested.pi_desc->pir, 256);
-+ if (!vmx->nested.pi_desc || !vmx->nested.pi_pending)
-+ return;
-
-- if (max_irr == 256)
-- return;
-+ vmx->nested.pi_pending = false;
-+ if (!pi_test_and_clear_on(vmx->nested.pi_desc))
-+ return;
-
-+ max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
-+ if (max_irr != 256) {
- vapic_page = kmap(vmx->nested.virtual_apic_page);
- __kvm_apic_update_irr(vmx->nested.pi_desc->pir, vapic_page);
- kunmap(vmx->nested.virtual_apic_page);
-@@ -4556,6 +4741,8 @@ static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
- vmcs_write16(GUEST_INTR_STATUS, status);
- }
- }
-+
-+ nested_mark_vmcs12_pages_dirty(vcpu);
- }
-
- static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu)
-@@ -4818,7 +5005,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
- vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmwrite_bitmap));
- }
- if (cpu_has_vmx_msr_bitmap())
-- vmcs_write64(MSR_BITMAP, __pa(vmx_msr_bitmap_legacy));
-+ vmcs_write64(MSR_BITMAP, __pa(vmx->vmcs01.msr_bitmap));
-
- vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
-
-@@ -4890,6 +5077,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
- ++vmx->nmsrs;
- }
-
-+ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
-+ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, vmx->arch_capabilities);
-
- vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl);
-
-@@ -4918,6 +5107,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
- u64 cr0;
-
- vmx->rmode.vm86_active = 0;
-+ vmx->spec_ctrl = 0;
-
- vmx->soft_vnmi_blocked = 0;
-
-@@ -6159,7 +6349,7 @@ static void wakeup_handler(void)
-
- static __init int hardware_setup(void)
- {
-- int r = -ENOMEM, i, msr;
-+ int r = -ENOMEM, i;
-
- rdmsrl_safe(MSR_EFER, &host_efer);
-
-@@ -6174,38 +6364,13 @@ static __init int hardware_setup(void)
- if (!vmx_io_bitmap_b)
- goto out;
-
-- vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL);
-- if (!vmx_msr_bitmap_legacy)
-- goto out1;
--
-- vmx_msr_bitmap_legacy_x2apic =
-- (unsigned long *)__get_free_page(GFP_KERNEL);
-- if (!vmx_msr_bitmap_legacy_x2apic)
-- goto out2;
--
-- vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL);
-- if (!vmx_msr_bitmap_longmode)
-- goto out3;
--
-- vmx_msr_bitmap_longmode_x2apic =
-- (unsigned long *)__get_free_page(GFP_KERNEL);
-- if (!vmx_msr_bitmap_longmode_x2apic)
-- goto out4;
--
-- if (nested) {
-- vmx_msr_bitmap_nested =
-- (unsigned long *)__get_free_page(GFP_KERNEL);
-- if (!vmx_msr_bitmap_nested)
-- goto out5;
-- }
--
- vmx_vmread_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
- if (!vmx_vmread_bitmap)
-- goto out6;
-+ goto out1;
-
- vmx_vmwrite_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
- if (!vmx_vmwrite_bitmap)
-- goto out7;
-+ goto out2;
-
- memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
- memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
-@@ -6214,14 +6379,9 @@ static __init int hardware_setup(void)
-
- memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE);
-
-- memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE);
-- memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE);
-- if (nested)
-- memset(vmx_msr_bitmap_nested, 0xff, PAGE_SIZE);
--
- if (setup_vmcs_config(&vmcs_config) < 0) {
- r = -EIO;
-- goto out8;
-+ goto out3;
- }
-
- if (boot_cpu_has(X86_FEATURE_NX))
-@@ -6287,38 +6447,8 @@ static __init int hardware_setup(void)
- kvm_x86_ops->sync_pir_to_irr = vmx_sync_pir_to_irr_dummy;
- }
-
-- vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
-- vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
-- vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
-- vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
-- vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
-- vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
--
-- memcpy(vmx_msr_bitmap_legacy_x2apic,
-- vmx_msr_bitmap_legacy, PAGE_SIZE);
-- memcpy(vmx_msr_bitmap_longmode_x2apic,
-- vmx_msr_bitmap_longmode, PAGE_SIZE);
--
- set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
-
-- if (enable_apicv) {
-- for (msr = 0x800; msr <= 0x8ff; msr++)
-- vmx_disable_intercept_msr_read_x2apic(msr);
--
-- /* According SDM, in x2apic mode, the whole id reg is used.
-- * But in KVM, it only use the highest eight bits. Need to
-- * intercept it */
-- vmx_enable_intercept_msr_read_x2apic(0x802);
-- /* TMCCT */
-- vmx_enable_intercept_msr_read_x2apic(0x839);
-- /* TPR */
-- vmx_disable_intercept_msr_write_x2apic(0x808);
-- /* EOI */
-- vmx_disable_intercept_msr_write_x2apic(0x80b);
-- /* SELF-IPI */
-- vmx_disable_intercept_msr_write_x2apic(0x83f);
-- }
--
- if (enable_ept) {
- kvm_mmu_set_mask_ptes(0ull,
- (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull,
-@@ -6349,21 +6479,10 @@ static __init int hardware_setup(void)
-
- return alloc_kvm_area();
-
--out8:
-- free_page((unsigned long)vmx_vmwrite_bitmap);
--out7:
-- free_page((unsigned long)vmx_vmread_bitmap);
--out6:
-- if (nested)
-- free_page((unsigned long)vmx_msr_bitmap_nested);
--out5:
-- free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic);
--out4:
-- free_page((unsigned long)vmx_msr_bitmap_longmode);
- out3:
-- free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic);
-+ free_page((unsigned long)vmx_vmwrite_bitmap);
- out2:
-- free_page((unsigned long)vmx_msr_bitmap_legacy);
-+ free_page((unsigned long)vmx_vmread_bitmap);
- out1:
- free_page((unsigned long)vmx_io_bitmap_b);
- out:
-@@ -6374,16 +6493,10 @@ out:
-
- static __exit void hardware_unsetup(void)
- {
-- free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic);
-- free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic);
-- free_page((unsigned long)vmx_msr_bitmap_legacy);
-- free_page((unsigned long)vmx_msr_bitmap_longmode);
- free_page((unsigned long)vmx_io_bitmap_b);
- free_page((unsigned long)vmx_io_bitmap_a);
- free_page((unsigned long)vmx_vmwrite_bitmap);
- free_page((unsigned long)vmx_vmread_bitmap);
-- if (nested)
-- free_page((unsigned long)vmx_msr_bitmap_nested);
-
- free_kvm_area();
- }
-@@ -6426,93 +6539,6 @@ static int handle_monitor(struct kvm_vcpu *vcpu)
- return handle_nop(vcpu);
- }
-
--/*
-- * To run an L2 guest, we need a vmcs02 based on the L1-specified vmcs12.
-- * We could reuse a single VMCS for all the L2 guests, but we also want the
-- * option to allocate a separate vmcs02 for each separate loaded vmcs12 - this
-- * allows keeping them loaded on the processor, and in the future will allow
-- * optimizations where prepare_vmcs02 doesn't need to set all the fields on
-- * every entry if they never change.
-- * So we keep, in vmx->nested.vmcs02_pool, a cache of size VMCS02_POOL_SIZE
-- * (>=0) with a vmcs02 for each recently loaded vmcs12s, most recent first.
-- *
-- * The following functions allocate and free a vmcs02 in this pool.
-- */
--
--/* Get a VMCS from the pool to use as vmcs02 for the current vmcs12. */
--static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
--{
-- struct vmcs02_list *item;
-- list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
-- if (item->vmptr == vmx->nested.current_vmptr) {
-- list_move(&item->list, &vmx->nested.vmcs02_pool);
-- return &item->vmcs02;
-- }
--
-- if (vmx->nested.vmcs02_num >= max(VMCS02_POOL_SIZE, 1)) {
-- /* Recycle the least recently used VMCS. */
-- item = list_entry(vmx->nested.vmcs02_pool.prev,
-- struct vmcs02_list, list);
-- item->vmptr = vmx->nested.current_vmptr;
-- list_move(&item->list, &vmx->nested.vmcs02_pool);
-- return &item->vmcs02;
-- }
--
-- /* Create a new VMCS */
-- item = kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
-- if (!item)
-- return NULL;
-- item->vmcs02.vmcs = alloc_vmcs();
-- if (!item->vmcs02.vmcs) {
-- kfree(item);
-- return NULL;
-- }
-- loaded_vmcs_init(&item->vmcs02);
-- item->vmptr = vmx->nested.current_vmptr;
-- list_add(&(item->list), &(vmx->nested.vmcs02_pool));
-- vmx->nested.vmcs02_num++;
-- return &item->vmcs02;
--}
--
--/* Free and remove from pool a vmcs02 saved for a vmcs12 (if there is one) */
--static void nested_free_vmcs02(struct vcpu_vmx *vmx, gpa_t vmptr)
--{
-- struct vmcs02_list *item;
-- list_for_each_entry(item, &vmx->nested.vmcs02_pool, list)
-- if (item->vmptr == vmptr) {
-- free_loaded_vmcs(&item->vmcs02);
-- list_del(&item->list);
-- kfree(item);
-- vmx->nested.vmcs02_num--;
-- return;
-- }
--}
--
--/*
-- * Free all VMCSs saved for this vcpu, except the one pointed by
-- * vmx->loaded_vmcs. We must be running L1, so vmx->loaded_vmcs
-- * must be &vmx->vmcs01.
-- */
--static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
--{
-- struct vmcs02_list *item, *n;
--
-- WARN_ON(vmx->loaded_vmcs != &vmx->vmcs01);
-- list_for_each_entry_safe(item, n, &vmx->nested.vmcs02_pool, list) {
-- /*
-- * Something will leak if the above WARN triggers. Better than
-- * a use-after-free.
-- */
-- if (vmx->loaded_vmcs == &item->vmcs02)
-- continue;
--
-- free_loaded_vmcs(&item->vmcs02);
-- list_del(&item->list);
-- kfree(item);
-- vmx->nested.vmcs02_num--;
-- }
--}
--
- /*
- * The following 3 functions, nested_vmx_succeed()/failValid()/failInvalid(),
- * set the success or error code of an emulated VMX instruction, as specified
-@@ -6786,6 +6812,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
- struct vmcs *shadow_vmcs;
- const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
- | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
-+ int r;
-
- /* The Intel VMX Instruction Reference lists a bunch of bits that
- * are prerequisite to running VMXON, most notably cr4.VMXE must be
-@@ -6825,10 +6852,14 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
- return 1;
- }
-
-+ r = alloc_loaded_vmcs(&vmx->nested.vmcs02);
-+ if (r < 0)
-+ goto out_vmcs02;
-+
- if (enable_shadow_vmcs) {
- shadow_vmcs = alloc_vmcs();
- if (!shadow_vmcs)
-- return -ENOMEM;
-+ goto out_shadow_vmcs;
- /* mark vmcs as shadow */
- shadow_vmcs->revision_id |= (1u << 31);
- /* init shadow vmcs */
-@@ -6836,9 +6867,6 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
- vmx->nested.current_shadow_vmcs = shadow_vmcs;
- }
-
-- INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool));
-- vmx->nested.vmcs02_num = 0;
--
- hrtimer_init(&vmx->nested.preemption_timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
- vmx->nested.preemption_timer.function = vmx_preemption_timer_fn;
-@@ -6850,6 +6878,12 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
- skip_emulated_instruction(vcpu);
- nested_vmx_succeed(vcpu);
- return 1;
-+
-+out_shadow_vmcs:
-+ free_loaded_vmcs(&vmx->nested.vmcs02);
-+
-+out_vmcs02:
-+ return -ENOMEM;
- }
-
- /*
-@@ -6921,7 +6955,7 @@ static void free_nested(struct vcpu_vmx *vmx)
- nested_release_vmcs12(vmx);
- if (enable_shadow_vmcs)
- free_vmcs(vmx->nested.current_shadow_vmcs);
-- /* Unpin physical memory we referred to in current vmcs02 */
-+ /* Unpin physical memory we referred to in the vmcs02 */
- if (vmx->nested.apic_access_page) {
- nested_release_page(vmx->nested.apic_access_page);
- vmx->nested.apic_access_page = NULL;
-@@ -6937,7 +6971,7 @@ static void free_nested(struct vcpu_vmx *vmx)
- vmx->nested.pi_desc = NULL;
- }
-
-- nested_free_all_saved_vmcss(vmx);
-+ free_loaded_vmcs(&vmx->nested.vmcs02);
- }
-
- /* Emulate the VMXOFF instruction */
-@@ -6971,8 +7005,6 @@ static int handle_vmclear(struct kvm_vcpu *vcpu)
- vmptr + offsetof(struct vmcs12, launch_state),
- &zero, sizeof(zero));
-
-- nested_free_vmcs02(vmx, vmptr);
--
- skip_emulated_instruction(vcpu);
- nested_vmx_succeed(vcpu);
- return 1;
-@@ -7757,6 +7789,19 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
- vmcs_read32(VM_EXIT_INTR_ERROR_CODE),
- KVM_ISA_VMX);
-
-+ /*
-+ * The host physical addresses of some pages of guest memory
-+ * are loaded into the vmcs02 (e.g. vmcs12's Virtual APIC
-+ * Page). The CPU may write to these pages via their host
-+ * physical address while L2 is running, bypassing any
-+ * address-translation-based dirty tracking (e.g. EPT write
-+ * protection).
-+ *
-+ * Mark them dirty on every exit from L2 to prevent them from
-+ * getting out of sync with dirty tracking.
-+ */
-+ nested_mark_vmcs12_pages_dirty(vcpu);
-+
- if (vmx->nested.nested_run_pending)
- return false;
-
-@@ -8244,7 +8289,7 @@ static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
- }
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control);
-
-- vmx_set_msr_bitmap(vcpu);
-+ vmx_update_msr_bitmap(vcpu);
- }
-
- static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
-@@ -8413,9 +8458,21 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
- local_irq_enable();
- }
-
--static bool vmx_has_high_real_mode_segbase(void)
-+static bool vmx_has_emulated_msr(int index)
- {
-- return enable_unrestricted_guest || emulate_invalid_guest_state;
-+ switch (index) {
-+ case MSR_IA32_SMBASE:
-+ /*
-+ * We cannot do SMM unless we can run the guest in big
-+ * real mode.
-+ */
-+ return enable_unrestricted_guest || emulate_invalid_guest_state;
-+ case MSR_AMD64_VIRT_SPEC_CTRL:
-+ /* This is AMD only. */
-+ return false;
-+ default:
-+ return true;
-+ }
- }
-
- static bool vmx_mpx_supported(void)
-@@ -8607,7 +8664,16 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
- atomic_switch_perf_msrs(vmx);
- debugctlmsr = get_debugctlmsr();
-
-+ /*
-+ * If this vCPU has touched SPEC_CTRL, restore the guest's value if
-+ * it's non-zero. Since vmentry is serialising on affected CPUs, there
-+ * is no need to worry about the conditional branch over the wrmsr
-+ * being speculatively taken.
-+ */
-+ x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
-+
- vmx->__launched = vmx->loaded_vmcs->launched;
-+
- asm(
- /* Store host registers */
- "push %%" _ASM_DX "; push %%" _ASM_BP ";"
-@@ -8725,6 +8791,26 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
- #endif
- );
-
-+ /*
-+ * We do not use IBRS in the kernel. If this vCPU has used the
-+ * SPEC_CTRL MSR it may have left it on; save the value and
-+ * turn it off. This is much more efficient than blindly adding
-+ * it to the atomic save/restore list. Especially as the former
-+ * (Saving guest MSRs on vmexit) doesn't even exist in KVM.
-+ *
-+ * For non-nested case:
-+ * If the L01 MSR bitmap does not intercept the MSR, then we need to
-+ * save it.
-+ *
-+ * For nested case:
-+ * If the L02 MSR bitmap does not intercept the MSR, then we need to
-+ * save it.
-+ */
-+ if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))
-+ vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
-+
-+ x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
-+
- /* Eliminate branch target predictions from guest mode */
- vmexit_fill_RSB();
-
-@@ -8824,6 +8910,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
- {
- int err;
- struct vcpu_vmx *vmx = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
-+ unsigned long *msr_bitmap;
- int cpu;
-
- if (!vmx)
-@@ -8856,16 +8943,24 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
- if (!vmx->guest_msrs)
- goto free_pml;
-
-- vmx->loaded_vmcs = &vmx->vmcs01;
-- vmx->loaded_vmcs->vmcs = alloc_vmcs();
-- if (!vmx->loaded_vmcs->vmcs)
-- goto free_msrs;
- if (!vmm_exclusive)
- kvm_cpu_vmxon(__pa(per_cpu(vmxarea, raw_smp_processor_id())));
-- loaded_vmcs_init(vmx->loaded_vmcs);
-+ err = alloc_loaded_vmcs(&vmx->vmcs01);
- if (!vmm_exclusive)
- kvm_cpu_vmxoff();
-+ if (err < 0)
-+ goto free_msrs;
-+
-+ msr_bitmap = vmx->vmcs01.msr_bitmap;
-+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_FS_BASE, MSR_TYPE_RW);
-+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_GS_BASE, MSR_TYPE_RW);
-+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_KERNEL_GS_BASE, MSR_TYPE_RW);
-+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_CS, MSR_TYPE_RW);
-+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_ESP, MSR_TYPE_RW);
-+ vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_EIP, MSR_TYPE_RW);
-+ vmx->msr_bitmap_mode = 0;
-
-+ vmx->loaded_vmcs = &vmx->vmcs01;
- cpu = get_cpu();
- vmx_vcpu_load(&vmx->vcpu, cpu);
- vmx->vcpu.cpu = cpu;
-@@ -9248,9 +9343,26 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
- {
- int msr;
- struct page *page;
-- unsigned long *msr_bitmap;
-+ unsigned long *msr_bitmap_l1;
-+ unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap;
-+ /*
-+ * pred_cmd & spec_ctrl are trying to verify two things:
-+ *
-+ * 1. L0 gave a permission to L1 to actually passthrough the MSR. This
-+ * ensures that we do not accidentally generate an L02 MSR bitmap
-+ * from the L12 MSR bitmap that is too permissive.
-+ * 2. That L1 or L2s have actually used the MSR. This avoids
-+ * unnecessarily merging of the bitmap if the MSR is unused. This
-+ * works properly because we only update the L01 MSR bitmap lazily.
-+ * So even if L0 should pass L1 these MSRs, the L01 bitmap is only
-+ * updated to reflect this when L1 (or its L2s) actually write to
-+ * the MSR.
-+ */
-+ bool pred_cmd = msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD);
-+ bool spec_ctrl = msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL);
-
-- if (!nested_cpu_has_virt_x2apic_mode(vmcs12))
-+ if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
-+ !pred_cmd && !spec_ctrl)
- return false;
-
- page = nested_get_page(vcpu, vmcs12->msr_bitmap);
-@@ -9258,59 +9370,46 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
- WARN_ON(1);
- return false;
- }
-- msr_bitmap = (unsigned long *)kmap(page);
-+ msr_bitmap_l1 = (unsigned long *)kmap(page);
-+
-+ memset(msr_bitmap_l0, 0xff, PAGE_SIZE);
-
- if (nested_cpu_has_virt_x2apic_mode(vmcs12)) {
- if (nested_cpu_has_apic_reg_virt(vmcs12))
- for (msr = 0x800; msr <= 0x8ff; msr++)
- nested_vmx_disable_intercept_for_msr(
-- msr_bitmap,
-- vmx_msr_bitmap_nested,
-+ msr_bitmap_l1, msr_bitmap_l0,
- msr, MSR_TYPE_R);
-- /* TPR is allowed */
-- nested_vmx_disable_intercept_for_msr(msr_bitmap,
-- vmx_msr_bitmap_nested,
-+
-+ nested_vmx_disable_intercept_for_msr(
-+ msr_bitmap_l1, msr_bitmap_l0,
- APIC_BASE_MSR + (APIC_TASKPRI >> 4),
- MSR_TYPE_R | MSR_TYPE_W);
-+
- if (nested_cpu_has_vid(vmcs12)) {
-- /* EOI and self-IPI are allowed */
- nested_vmx_disable_intercept_for_msr(
-- msr_bitmap,
-- vmx_msr_bitmap_nested,
-+ msr_bitmap_l1, msr_bitmap_l0,
- APIC_BASE_MSR + (APIC_EOI >> 4),
- MSR_TYPE_W);
- nested_vmx_disable_intercept_for_msr(
-- msr_bitmap,
-- vmx_msr_bitmap_nested,
-+ msr_bitmap_l1, msr_bitmap_l0,
- APIC_BASE_MSR + (APIC_SELF_IPI >> 4),
- MSR_TYPE_W);
- }
-- } else {
-- /*
-- * Enable reading intercept of all the x2apic
-- * MSRs. We should not rely on vmcs12 to do any
-- * optimizations here, it may have been modified
-- * by L1.
-- */
-- for (msr = 0x800; msr <= 0x8ff; msr++)
-- __vmx_enable_intercept_for_msr(
-- vmx_msr_bitmap_nested,
-- msr,
-- MSR_TYPE_R);
--
-- __vmx_enable_intercept_for_msr(
-- vmx_msr_bitmap_nested,
-- APIC_BASE_MSR + (APIC_TASKPRI >> 4),
-- MSR_TYPE_W);
-- __vmx_enable_intercept_for_msr(
-- vmx_msr_bitmap_nested,
-- APIC_BASE_MSR + (APIC_EOI >> 4),
-- MSR_TYPE_W);
-- __vmx_enable_intercept_for_msr(
-- vmx_msr_bitmap_nested,
-- APIC_BASE_MSR + (APIC_SELF_IPI >> 4),
-- MSR_TYPE_W);
- }
-+
-+ if (spec_ctrl)
-+ nested_vmx_disable_intercept_for_msr(
-+ msr_bitmap_l1, msr_bitmap_l0,
-+ MSR_IA32_SPEC_CTRL,
-+ MSR_TYPE_R | MSR_TYPE_W);
-+
-+ if (pred_cmd)
-+ nested_vmx_disable_intercept_for_msr(
-+ msr_bitmap_l1, msr_bitmap_l0,
-+ MSR_IA32_PRED_CMD,
-+ MSR_TYPE_W);
-+
- kunmap(page);
- nested_release_page_clean(page);
-
-@@ -9729,10 +9828,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
- }
-
- if (cpu_has_vmx_msr_bitmap() &&
-- exec_control & CPU_BASED_USE_MSR_BITMAPS) {
-- nested_vmx_merge_msr_bitmap(vcpu, vmcs12);
-- /* MSR_BITMAP will be set by following vmx_set_efer. */
-- } else
-+ exec_control & CPU_BASED_USE_MSR_BITMAPS &&
-+ nested_vmx_merge_msr_bitmap(vcpu, vmcs12))
-+ ; /* MSR_BITMAP will be set by following vmx_set_efer. */
-+ else
- exec_control &= ~CPU_BASED_USE_MSR_BITMAPS;
-
- /*
-@@ -9784,6 +9883,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
- else
- vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset);
-
-+ if (cpu_has_vmx_msr_bitmap())
-+ vmcs_write64(MSR_BITMAP, __pa(vmx->nested.vmcs02.msr_bitmap));
-+
- if (enable_vpid) {
- /*
- * There is no direct mapping between vpid02 and vpid12, the
-@@ -9876,7 +9978,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
- struct vmcs12 *vmcs12;
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- int cpu;
-- struct loaded_vmcs *vmcs02;
- bool ia32e;
- u32 msr_entry_idx;
-
-@@ -10016,10 +10117,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
- * the nested entry.
- */
-
-- vmcs02 = nested_get_current_vmcs02(vmx);
-- if (!vmcs02)
-- return -ENOMEM;
--
- enter_guest_mode(vcpu);
-
- vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET);
-@@ -10028,7 +10125,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
- vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
-
- cpu = get_cpu();
-- vmx->loaded_vmcs = vmcs02;
-+ vmx->loaded_vmcs = &vmx->nested.vmcs02;
- vmx_vcpu_put(vcpu);
- vmx_vcpu_load(vcpu, cpu);
- vcpu->cpu = cpu;
-@@ -10489,7 +10586,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
- vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
-
- if (cpu_has_vmx_msr_bitmap())
-- vmx_set_msr_bitmap(vcpu);
-+ vmx_update_msr_bitmap(vcpu);
-
- if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr,
- vmcs12->vm_exit_msr_load_count))
-@@ -10540,10 +10637,6 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
- vm_exit_controls_init(vmx, vmcs_read32(VM_EXIT_CONTROLS));
- vmx_segment_cache_clear(vmx);
-
-- /* if no vmcs02 cache requested, remove the one we used */
-- if (VMCS02_POOL_SIZE == 0)
-- nested_free_vmcs02(vmx, vmx->nested.current_vmptr);
--
- load_vmcs12_host_state(vcpu, vmcs12);
-
- /* Update TSC_OFFSET if TSC was changed while L2 ran */
-@@ -10871,7 +10964,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
- .hardware_enable = hardware_enable,
- .hardware_disable = hardware_disable,
- .cpu_has_accelerated_tpr = report_flexpriority,
-- .cpu_has_high_real_mode_segbase = vmx_has_high_real_mode_segbase,
-+ .has_emulated_msr = vmx_has_emulated_msr,
-
- .vcpu_create = vmx_create_vcpu,
- .vcpu_free = vmx_free_vcpu,
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index e6ab034f0bc7..aa1a0277a678 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -961,6 +961,7 @@ static u32 msrs_to_save[] = {
- #endif
- MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
- MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX,
-+ MSR_IA32_SPEC_CTRL, MSR_IA32_ARCH_CAPABILITIES
- };
-
- static unsigned num_msrs_to_save;
-@@ -984,6 +985,7 @@ static u32 emulated_msrs[] = {
- MSR_IA32_MCG_STATUS,
- MSR_IA32_MCG_CTL,
- MSR_IA32_SMBASE,
-+ MSR_AMD64_VIRT_SPEC_CTRL,
- };
-
- static unsigned num_emulated_msrs;
-@@ -2583,7 +2585,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
- * fringe case that is not enabled except via specific settings
- * of the module parameters.
- */
-- r = kvm_x86_ops->cpu_has_high_real_mode_segbase();
-+ r = kvm_x86_ops->has_emulated_msr(MSR_IA32_SMBASE);
- break;
- case KVM_CAP_COALESCED_MMIO:
- r = KVM_COALESCED_MMIO_PAGE_OFFSET;
-@@ -4072,14 +4074,8 @@ static void kvm_init_msr_list(void)
- num_msrs_to_save = j;
-
- for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
-- switch (emulated_msrs[i]) {
-- case MSR_IA32_SMBASE:
-- if (!kvm_x86_ops->cpu_has_high_real_mode_segbase())
-- continue;
-- break;
-- default:
-- break;
-- }
-+ if (!kvm_x86_ops->has_emulated_msr(emulated_msrs[i]))
-+ continue;
-
- if (j < i)
- emulated_msrs[j] = emulated_msrs[i];
-diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
-index 91d93b95bd86..0a6fcae404f8 100644
---- a/arch/x86/lib/usercopy_32.c
-+++ b/arch/x86/lib/usercopy_32.c
-@@ -570,12 +570,12 @@ do { \
- unsigned long __copy_to_user_ll(void __user *to, const void *from,
- unsigned long n)
- {
-- stac();
-+ __uaccess_begin_nospec();
- if (movsl_is_ok(to, from, n))
- __copy_user(to, from, n);
- else
- n = __copy_user_intel(to, from, n);
-- clac();
-+ __uaccess_end();
- return n;
- }
- EXPORT_SYMBOL(__copy_to_user_ll);
-@@ -583,12 +583,12 @@ EXPORT_SYMBOL(__copy_to_user_ll);
- unsigned long __copy_from_user_ll(void *to, const void __user *from,
- unsigned long n)
- {
-- stac();
-+ __uaccess_begin_nospec();
- if (movsl_is_ok(to, from, n))
- __copy_user_zeroing(to, from, n);
- else
- n = __copy_user_zeroing_intel(to, from, n);
-- clac();
-+ __uaccess_end();
- return n;
- }
- EXPORT_SYMBOL(__copy_from_user_ll);
-@@ -596,13 +596,13 @@ EXPORT_SYMBOL(__copy_from_user_ll);
- unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
- unsigned long n)
- {
-- stac();
-+ __uaccess_begin_nospec();
- if (movsl_is_ok(to, from, n))
- __copy_user(to, from, n);
- else
- n = __copy_user_intel((void __user *)to,
- (const void *)from, n);
-- clac();
-+ __uaccess_end();
- return n;
- }
- EXPORT_SYMBOL(__copy_from_user_ll_nozero);
-@@ -610,7 +610,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
- unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
- unsigned long n)
- {
-- stac();
-+ __uaccess_begin_nospec();
- #ifdef CONFIG_X86_INTEL_USERCOPY
- if (n > 64 && cpu_has_xmm2)
- n = __copy_user_zeroing_intel_nocache(to, from, n);
-@@ -619,7 +619,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
- #else
- __copy_user_zeroing(to, from, n);
- #endif
-- clac();
-+ __uaccess_end();
- return n;
- }
- EXPORT_SYMBOL(__copy_from_user_ll_nocache);
-@@ -627,7 +627,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nocache);
- unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
- unsigned long n)
- {
-- stac();
-+ __uaccess_begin_nospec();
- #ifdef CONFIG_X86_INTEL_USERCOPY
- if (n > 64 && cpu_has_xmm2)
- n = __copy_user_intel_nocache(to, from, n);
-@@ -636,7 +636,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
- #else
- __copy_user(to, from, n);
- #endif
-- clac();
-+ __uaccess_end();
- return n;
- }
- EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
-diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
-index ae9a37bf1371..7d2542ad346a 100644
---- a/arch/x86/mm/gup.c
-+++ b/arch/x86/mm/gup.c
-@@ -388,7 +388,7 @@ slow_irqon:
-
- ret = get_user_pages_unlocked(current, mm, start,
- (end - start) >> PAGE_SHIFT,
-- write, 0, pages);
-+ pages, write ? FOLL_WRITE : 0);
-
- /* Have to be a bit careful with return values */
- if (nr > 0) {
-diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
-index 7ed47b1e6f42..7e94fc6f608a 100644
---- a/arch/x86/mm/mpx.c
-+++ b/arch/x86/mm/mpx.c
-@@ -536,10 +536,9 @@ static int mpx_resolve_fault(long __user *addr, int write)
- {
- long gup_ret;
- int nr_pages = 1;
-- int force = 0;
-
- gup_ret = get_user_pages(current, current->mm, (unsigned long)addr,
-- nr_pages, write, force, NULL, NULL);
-+ nr_pages, write ? FOLL_WRITE : 0, NULL, NULL);
- /*
- * get_user_pages() returns number of pages gotten.
- * 0 means we failed to fault in and get anything,
-diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
-index e40a6d8b0b92..062c23125b2a 100644
---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
-+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
-@@ -496,9 +496,13 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
- int r;
-
- int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
-+ unsigned int flags = 0;
- enum dma_data_direction direction = write ?
- DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
-
-+ if (write)
-+ flags |= FOLL_WRITE;
-+
- if (current->mm != gtt->usermm)
- return -EPERM;
-
-@@ -519,7 +523,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
- struct page **pages = ttm->pages + pinned;
-
- r = get_user_pages(current, current->mm, userptr, num_pages,
-- write, 0, pages, NULL);
-+ flags, pages, NULL);
- if (r < 0)
- goto release_pages;
-
-diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
-index 21085f669e21..b19ba1792607 100644
---- a/drivers/gpu/drm/ast/ast_mode.c
-+++ b/drivers/gpu/drm/ast/ast_mode.c
-@@ -968,9 +968,21 @@ static int get_clock(void *i2c_priv)
- {
- struct ast_i2c_chan *i2c = i2c_priv;
- struct ast_private *ast = i2c->dev->dev_private;
-- uint32_t val;
-+ uint32_t val, val2, count, pass;
-+
-+ count = 0;
-+ pass = 0;
-+ val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
-+ do {
-+ val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
-+ if (val == val2) {
-+ pass++;
-+ } else {
-+ pass = 0;
-+ val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
-+ }
-+ } while ((pass < 5) && (count++ < 0x10000));
-
-- val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4;
- return val & 1 ? 1 : 0;
- }
-
-@@ -978,9 +990,21 @@ static int get_data(void *i2c_priv)
- {
- struct ast_i2c_chan *i2c = i2c_priv;
- struct ast_private *ast = i2c->dev->dev_private;
-- uint32_t val;
-+ uint32_t val, val2, count, pass;
-+
-+ count = 0;
-+ pass = 0;
-+ val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
-+ do {
-+ val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
-+ if (val == val2) {
-+ pass++;
-+ } else {
-+ pass = 0;
-+ val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
-+ }
-+ } while ((pass < 5) && (count++ < 0x10000));
-
-- val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5;
- return val & 1 ? 1 : 0;
- }
-
-@@ -993,7 +1017,7 @@ static void set_clock(void *i2c_priv, int clock)
-
- for (i = 0; i < 0x10000; i++) {
- ujcrb7 = ((clock & 0x01) ? 0 : 1);
-- ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfe, ujcrb7);
-+ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
- jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
- if (ujcrb7 == jtemp)
- break;
-@@ -1009,7 +1033,7 @@ static void set_data(void *i2c_priv, int data)
-
- for (i = 0; i < 0x10000; i++) {
- ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
-- ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfb, ujcrb7);
-+ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
- jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
- if (ujcrb7 == jtemp)
- break;
-diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
-index c17efdb238a6..639ea28808e2 100644
---- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
-+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
-@@ -471,7 +471,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
- goto err_free;
- }
-
-- ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec);
-+ ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE,
-+ g2d_userptr->vec);
- if (ret != npages) {
- DRM_ERROR("failed to get user pages from userptr.\n");
- if (ret < 0)
-diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
-index 359fe2b8bb8a..b02113b57d51 100644
---- a/drivers/gpu/drm/i915/i915_gem_userptr.c
-+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
-@@ -581,13 +581,17 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
- pvec = drm_malloc_ab(npages, sizeof(struct page *));
- if (pvec != NULL) {
- struct mm_struct *mm = obj->userptr.mm->mm;
-+ unsigned int flags = 0;
-+
-+ if (!obj->userptr.read_only)
-+ flags |= FOLL_WRITE;
-
- down_read(&mm->mmap_sem);
- while (pinned < npages) {
- ret = get_user_pages(work->task, mm,
- obj->userptr.ptr + pinned * PAGE_SIZE,
- npages - pinned,
-- !obj->userptr.read_only, 0,
-+ flags,
- pvec + pinned, NULL);
- if (ret < 0)
- break;
-diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
-index d684e2b79d2b..0c380fe77382 100644
---- a/drivers/gpu/drm/radeon/radeon_ttm.c
-+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
-@@ -557,7 +557,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm)
- struct page **pages = ttm->pages + pinned;
-
- r = get_user_pages(current, current->mm, userptr, num_pages,
-- write, 0, pages, NULL);
-+ write ? FOLL_WRITE : 0, pages, NULL);
- if (r < 0)
- goto release_pages;
-
-diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
-index d0cbd5ecd7f0..4459cb32d1fe 100644
---- a/drivers/gpu/drm/via/via_dmablit.c
-+++ b/drivers/gpu/drm/via/via_dmablit.c
-@@ -242,8 +242,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
- ret = get_user_pages(current, current->mm,
- (unsigned long)xfer->mem_addr,
- vsg->num_pages,
-- (vsg->direction == DMA_FROM_DEVICE),
-- 0, vsg->pages, NULL);
-+ (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0,
-+ vsg->pages, NULL);
-
- up_read(¤t->mm->mmap_sem);
- if (ret != vsg->num_pages) {
-diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
-index 9ac6e1673375..1f291b344178 100644
---- a/drivers/hwmon/ina2xx.c
-+++ b/drivers/hwmon/ina2xx.c
-@@ -273,7 +273,7 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
- break;
- case INA2XX_CURRENT:
- /* signed register, result in mA */
-- val = regval * data->current_lsb_uA;
-+ val = (s16)regval * data->current_lsb_uA;
- val = DIV_ROUND_CLOSEST(val, 1000);
- break;
- case INA2XX_CALIBRATION:
-diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
-index 49276bbdac3d..1bb80f992aa8 100644
---- a/drivers/hwmon/w83795.c
-+++ b/drivers/hwmon/w83795.c
-@@ -1691,7 +1691,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
- * somewhere else in the code
- */
- #define SENSOR_ATTR_TEMP(index) { \
-- SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
-+ SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 5 ? S_IWUSR : 0), \
- show_temp_mode, store_temp_mode, NOT_USED, index - 1), \
- SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \
- NULL, TEMP_READ, index - 1), \
-diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
-index 98fd9a594841..8762eac47570 100644
---- a/drivers/infiniband/core/umem.c
-+++ b/drivers/infiniband/core/umem.c
-@@ -95,6 +95,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
- DEFINE_DMA_ATTRS(attrs);
- struct scatterlist *sg, *sg_list_start;
- int need_release = 0;
-+ unsigned int gup_flags = FOLL_WRITE;
-
- if (dmasync)
- dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
-@@ -177,6 +178,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
- if (ret)
- goto out;
-
-+ if (!umem->writable)
-+ gup_flags |= FOLL_FORCE;
-+
- need_release = 1;
- sg_list_start = umem->sg_head.sgl;
-
-@@ -184,7 +188,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
- ret = get_user_pages(current, current->mm, cur_base,
- min_t(unsigned long, npages,
- PAGE_SIZE / sizeof (struct page *)),
-- 1, !umem->writable, page_list, vma_list);
-+ gup_flags, page_list, vma_list);
-
- if (ret < 0)
- goto out;
-diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
-index 40becdb3196e..738ccfee7cae 100644
---- a/drivers/infiniband/core/umem_odp.c
-+++ b/drivers/infiniband/core/umem_odp.c
-@@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
- u64 off;
- int j, k, ret = 0, start_idx, npages = 0;
- u64 base_virt_addr;
-+ unsigned int flags = 0;
-
- if (access_mask == 0)
- return -EINVAL;
-@@ -556,6 +557,9 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
- goto out_put_task;
- }
-
-+ if (access_mask & ODP_WRITE_ALLOWED_BIT)
-+ flags |= FOLL_WRITE;
-+
- start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
- k = start_idx;
-
-@@ -574,8 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
- */
- npages = get_user_pages(owning_process, owning_mm, user_virt,
- gup_num_pages,
-- access_mask & ODP_WRITE_ALLOWED_BIT, 0,
-- local_page_list, NULL);
-+ flags, local_page_list, NULL);
- up_read(&owning_mm->mmap_sem);
-
- if (npages < 0)
-diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
-index 7d2e42dd6926..8676685dbf3d 100644
---- a/drivers/infiniband/hw/mthca/mthca_memfree.c
-+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
-@@ -472,8 +472,8 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
- goto out;
- }
-
-- ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
-- pages, NULL);
-+ ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1,
-+ FOLL_WRITE, pages, NULL);
- if (ret < 0)
- goto out;
-
-diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
-index ab1588ae1c85..75c3f0dffe63 100644
---- a/drivers/infiniband/hw/qib/qib_user_pages.c
-+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
-@@ -68,7 +68,8 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
- for (got = 0; got < num_pages; got += ret) {
- ret = get_user_pages(current, current->mm,
- start_page + got * PAGE_SIZE,
-- num_pages - got, 1, 1,
-+ num_pages - got,
-+ FOLL_WRITE | FOLL_FORCE,
- p + got, NULL);
- if (ret < 0)
- goto bail_release;
-diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
-index 645a5f6e6c88..7f0d75e29441 100644
---- a/drivers/infiniband/hw/usnic/usnic_uiom.c
-+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
-@@ -113,6 +113,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
- int flags;
- dma_addr_t pa;
- DEFINE_DMA_ATTRS(attrs);
-+ unsigned int gup_flags;
-
- if (dmasync)
- dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
-@@ -140,6 +141,8 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
-
- flags = IOMMU_READ | IOMMU_CACHE;
- flags |= (writable) ? IOMMU_WRITE : 0;
-+ gup_flags = FOLL_WRITE;
-+ gup_flags |= (writable) ? 0 : FOLL_FORCE;
- cur_base = addr & PAGE_MASK;
- ret = 0;
-
-@@ -147,7 +150,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
- ret = get_user_pages(current, current->mm, cur_base,
- min_t(unsigned long, npages,
- PAGE_SIZE / sizeof(struct page *)),
-- 1, !writable, page_list, NULL);
-+ gup_flags, page_list, NULL);
-
- if (ret < 0)
- goto out;
-diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c
-index f770f6a2c987..3ea9edc8cdbe 100644
---- a/drivers/media/dvb-frontends/ascot2e.c
-+++ b/drivers/media/dvb-frontends/ascot2e.c
-@@ -155,7 +155,9 @@ static int ascot2e_write_regs(struct ascot2e_priv *priv,
-
- static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val)
- {
-- return ascot2e_write_regs(priv, reg, &val, 1);
-+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return ascot2e_write_regs(priv, reg, &tmp, 1);
- }
-
- static int ascot2e_read_regs(struct ascot2e_priv *priv,
-diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
-index 107853b0fddd..bde77671a37c 100644
---- a/drivers/media/dvb-frontends/cxd2841er.c
-+++ b/drivers/media/dvb-frontends/cxd2841er.c
-@@ -241,7 +241,9 @@ static int cxd2841er_write_regs(struct cxd2841er_priv *priv,
- static int cxd2841er_write_reg(struct cxd2841er_priv *priv,
- u8 addr, u8 reg, u8 val)
- {
-- return cxd2841er_write_regs(priv, addr, reg, &val, 1);
-+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return cxd2841er_write_regs(priv, addr, reg, &tmp, 1);
- }
-
- static int cxd2841er_read_regs(struct cxd2841er_priv *priv,
-diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c
-index 000606af70f7..f770ab72a8e3 100644
---- a/drivers/media/dvb-frontends/horus3a.c
-+++ b/drivers/media/dvb-frontends/horus3a.c
-@@ -89,7 +89,9 @@ static int horus3a_write_regs(struct horus3a_priv *priv,
-
- static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val)
- {
-- return horus3a_write_regs(priv, reg, &val, 1);
-+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return horus3a_write_regs(priv, reg, &tmp, 1);
- }
-
- static int horus3a_enter_power_save(struct horus3a_priv *priv)
-diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c
-index cadcae4cff89..ac9d2591bb6f 100644
---- a/drivers/media/dvb-frontends/itd1000.c
-+++ b/drivers/media/dvb-frontends/itd1000.c
-@@ -99,8 +99,9 @@ static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
-
- static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
- {
-- int ret = itd1000_write_regs(state, r, &v, 1);
-- state->shadow[r] = v;
-+ u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+ int ret = itd1000_write_regs(state, r, &tmp, 1);
-+ state->shadow[r] = tmp;
- return ret;
- }
-
-diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
-index c36e6764eead..c44188271028 100644
---- a/drivers/media/dvb-frontends/mt312.c
-+++ b/drivers/media/dvb-frontends/mt312.c
-@@ -142,7 +142,10 @@ static inline int mt312_readreg(struct mt312_state *state,
- static inline int mt312_writereg(struct mt312_state *state,
- const enum mt312_reg_addr reg, const u8 val)
- {
-- return mt312_write(state, reg, &val, 1);
-+ u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+
-+ return mt312_write(state, reg, &tmp, 1);
- }
-
- static inline u32 mt312_div(u32 a, u32 b)
-diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
-index 756650f154ab..ad9b7d4f8d95 100644
---- a/drivers/media/dvb-frontends/stb0899_drv.c
-+++ b/drivers/media/dvb-frontends/stb0899_drv.c
-@@ -552,7 +552,8 @@ int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data,
-
- int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
- {
-- return stb0899_write_regs(state, reg, &data, 1);
-+ u8 tmp = data;
-+ return stb0899_write_regs(state, reg, &tmp, 1);
- }
-
- /*
-diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c
-index 4ef8a5c7003e..44fac2570034 100644
---- a/drivers/media/dvb-frontends/stb6100.c
-+++ b/drivers/media/dvb-frontends/stb6100.c
-@@ -226,12 +226,14 @@ static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int st
-
- static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
- {
-+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
- if (unlikely(reg >= STB6100_NUMREGS)) {
- dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
- return -EREMOTEIO;
- }
-- data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
-- return stb6100_write_reg_range(state, &data, reg, 1);
-+ tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set;
-+ return stb6100_write_reg_range(state, &tmp, reg, 1);
- }
-
-
-diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
-index 44cb73f68af6..ddd0d778ad6e 100644
---- a/drivers/media/dvb-frontends/stv0367.c
-+++ b/drivers/media/dvb-frontends/stv0367.c
-@@ -804,7 +804,9 @@ int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
-
- static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
- {
-- return stv0367_writeregs(state, reg, &data, 1);
-+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return stv0367_writeregs(state, reg, &tmp, 1);
- }
-
- static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
-diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
-index 25bdf6e0f963..f0377e2b341b 100644
---- a/drivers/media/dvb-frontends/stv090x.c
-+++ b/drivers/media/dvb-frontends/stv090x.c
-@@ -761,7 +761,9 @@ static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8
-
- static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
- {
-- return stv090x_write_regs(state, reg, &data, 1);
-+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return stv090x_write_regs(state, reg, &tmp, 1);
- }
-
- static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
-diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c
-index e66154e5c1d7..45d14869e7b8 100644
---- a/drivers/media/dvb-frontends/stv6110x.c
-+++ b/drivers/media/dvb-frontends/stv6110x.c
-@@ -97,7 +97,9 @@ static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 da
-
- static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
- {
-- return stv6110x_write_regs(stv6110x, reg, &data, 1);
-+ u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return stv6110x_write_regs(stv6110x, reg, &tmp, 1);
- }
-
- static int stv6110x_init(struct dvb_frontend *fe)
-diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c
-index ee09ec26c553..b273e4fd8024 100644
---- a/drivers/media/dvb-frontends/zl10039.c
-+++ b/drivers/media/dvb-frontends/zl10039.c
-@@ -138,7 +138,9 @@ static inline int zl10039_writereg(struct zl10039_state *state,
- const enum zl10039_reg_addr reg,
- const u8 val)
- {
-- return zl10039_write(state, reg, &val, 1);
-+ const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-+
-+ return zl10039_write(state, reg, &tmp, 1);
- }
-
- static int zl10039_init(struct dvb_frontend *fe)
-diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c
-index 24152accc66c..8729fdebef8f 100644
---- a/drivers/media/pci/ivtv/ivtv-udma.c
-+++ b/drivers/media/pci/ivtv/ivtv-udma.c
-@@ -125,7 +125,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
-
- /* Get user pages for DMA Xfer */
- err = get_user_pages_unlocked(current, current->mm,
-- user_dma.uaddr, user_dma.page_count, 0, 1, dma->map);
-+ user_dma.uaddr, user_dma.page_count, dma->map,
-+ FOLL_FORCE);
-
- if (user_dma.page_count != err) {
- IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
-diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c
-index 2b8e7b2f2b86..9cd995f418e0 100644
---- a/drivers/media/pci/ivtv/ivtv-yuv.c
-+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
-@@ -76,13 +76,13 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
-
- /* Get user pages for DMA Xfer */
- y_pages = get_user_pages_unlocked(current, current->mm,
-- y_dma.uaddr, y_dma.page_count, 0, 1,
-- &dma->map[0]);
-+ y_dma.uaddr, y_dma.page_count,
-+ &dma->map[0], FOLL_FORCE);
- uv_pages = 0; /* silence gcc. value is set and consumed only if: */
- if (y_pages == y_dma.page_count) {
- uv_pages = get_user_pages_unlocked(current, current->mm,
-- uv_dma.uaddr, uv_dma.page_count, 0, 1,
-- &dma->map[y_pages]);
-+ uv_dma.uaddr, uv_dma.page_count,
-+ &dma->map[y_pages], FOLL_FORCE);
- }
-
- if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
-diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
-index 70c28d19ea04..596359576109 100644
---- a/drivers/media/platform/omap/omap_vout.c
-+++ b/drivers/media/platform/omap/omap_vout.c
-@@ -214,7 +214,7 @@ static int omap_vout_get_userptr(struct videobuf_buffer *vb, u32 virtp,
- if (!vec)
- return -ENOMEM;
-
-- ret = get_vaddr_frames(virtp, 1, true, false, vec);
-+ ret = get_vaddr_frames(virtp, 1, FOLL_WRITE, vec);
- if (ret != 1) {
- frame_vector_destroy(vec);
- return -EINVAL;
-diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
-index f669cedca8bd..f74a74d91b9e 100644
---- a/drivers/media/v4l2-core/videobuf-dma-sg.c
-+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
-@@ -156,6 +156,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
- {
- unsigned long first, last;
- int err, rw = 0;
-+ unsigned int flags = FOLL_FORCE;
-
- dma->direction = direction;
- switch (dma->direction) {
-@@ -178,13 +179,15 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
- if (NULL == dma->pages)
- return -ENOMEM;
-
-+ if (rw == READ)
-+ flags |= FOLL_WRITE;
-+
- dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
- data, size, dma->nr_pages);
-
- err = get_user_pages(current, current->mm,
- data & PAGE_MASK, dma->nr_pages,
-- rw == READ, 1, /* force */
-- dma->pages, NULL);
-+ flags, dma->pages, NULL);
-
- if (err != dma->nr_pages) {
- dma->nr_pages = (err >= 0) ? err : 0;
-diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c
-index 3c3b517f1d1c..1cd322e939c7 100644
---- a/drivers/media/v4l2-core/videobuf2-memops.c
-+++ b/drivers/media/v4l2-core/videobuf2-memops.c
-@@ -42,6 +42,10 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
- unsigned long first, last;
- unsigned long nr;
- struct frame_vector *vec;
-+ unsigned int flags = FOLL_FORCE;
-+
-+ if (write)
-+ flags |= FOLL_WRITE;
-
- first = start >> PAGE_SHIFT;
- last = (start + length - 1) >> PAGE_SHIFT;
-@@ -49,7 +53,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
- vec = frame_vector_create(nr);
- if (!vec)
- return ERR_PTR(-ENOMEM);
-- ret = get_vaddr_frames(start & PAGE_MASK, nr, write, true, vec);
-+ ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
- if (ret < 0)
- goto out_destroy;
- /* We accept only complete set of PFNs */
-diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c
-index 8bd63128d536..71c69e1c4ac0 100644
---- a/drivers/misc/mic/scif/scif_rma.c
-+++ b/drivers/misc/mic/scif/scif_rma.c
-@@ -1398,8 +1398,7 @@ retry:
- mm,
- (u64)addr,
- nr_pages,
-- !!(prot & SCIF_PROT_WRITE),
-- 0,
-+ (prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
- pinned_pages->pages,
- NULL);
- up_write(&mm->mmap_sem);
-diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
-index f74fc0ca2ef9..e6b723c6a2af 100644
---- a/drivers/misc/sgi-gru/grufault.c
-+++ b/drivers/misc/sgi-gru/grufault.c
-@@ -199,7 +199,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
- *pageshift = PAGE_SHIFT;
- #endif
- if (get_user_pages
-- (current, current->mm, vaddr, 1, write, 0, &page, NULL) <= 0)
-+ (current, current->mm, vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0)
- return -EFAULT;
- *paddr = page_to_phys(page);
- put_page(page);
-diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
-index 16baaafed26c..cbdeb54eab51 100644
---- a/drivers/net/ethernet/cavium/thunder/nic_main.c
-+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
-@@ -1090,6 +1090,9 @@ static void nic_remove(struct pci_dev *pdev)
- {
- struct nicpf *nic = pci_get_drvdata(pdev);
-
-+ if (!nic)
-+ return;
-+
- if (nic->flags & NIC_SRIOV_ENABLED)
- pci_disable_sriov(pdev);
-
-diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c
-index 253f8ed0537a..60c727b0b7ab 100644
---- a/drivers/net/ethernet/hisilicon/hip04_eth.c
-+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
-@@ -919,10 +919,8 @@ static int hip04_mac_probe(struct platform_device *pdev)
- }
-
- ret = register_netdev(ndev);
-- if (ret) {
-- free_netdev(ndev);
-+ if (ret)
- goto alloc_fail;
-- }
-
- return 0;
-
-diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
-index ffd2e74e5638..dcd718ce13d5 100644
---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
-+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
-@@ -1429,7 +1429,9 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
- *autoneg = false;
-
- if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
-- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
-+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
-+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
-+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
- *speed = IXGBE_LINK_SPEED_1GB_FULL;
- return 0;
- }
-diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
-index deae10d7426d..9b588251f2a7 100644
---- a/drivers/net/ethernet/realtek/8139cp.c
-+++ b/drivers/net/ethernet/realtek/8139cp.c
-@@ -578,6 +578,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
- struct cp_private *cp;
- int handled = 0;
- u16 status;
-+ u16 mask;
-
- if (unlikely(dev == NULL))
- return IRQ_NONE;
-@@ -585,6 +586,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
-
- spin_lock(&cp->lock);
-
-+ mask = cpr16(IntrMask);
-+ if (!mask)
-+ goto out_unlock;
-+
- status = cpr16(IntrStatus);
- if (!status || (status == 0xFFFF))
- goto out_unlock;
-diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
-index 3920c3eb6006..df6063faad2e 100644
---- a/drivers/net/ethernet/rocker/rocker.c
-+++ b/drivers/net/ethernet/rocker/rocker.c
-@@ -821,37 +821,49 @@ static int rocker_tlv_put(struct rocker_desc_info *desc_info,
- static int rocker_tlv_put_u8(struct rocker_desc_info *desc_info,
- int attrtype, u8 value)
- {
-- return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &value);
-+ u8 tmp = value; /* work around GCC PR81715 */
-+
-+ return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp);
- }
-
- static int rocker_tlv_put_u16(struct rocker_desc_info *desc_info,
- int attrtype, u16 value)
- {
-- return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &value);
-+ u16 tmp = value;
-+
-+ return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp);
- }
-
- static int rocker_tlv_put_be16(struct rocker_desc_info *desc_info,
- int attrtype, __be16 value)
- {
-- return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &value);
-+ __be16 tmp = value;
-+
-+ return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp);
- }
-
- static int rocker_tlv_put_u32(struct rocker_desc_info *desc_info,
- int attrtype, u32 value)
- {
-- return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &value);
-+ u32 tmp = value;
-+
-+ return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp);
- }
-
- static int rocker_tlv_put_be32(struct rocker_desc_info *desc_info,
- int attrtype, __be32 value)
- {
-- return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &value);
-+ __be32 tmp = value;
-+
-+ return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp);
- }
-
- static int rocker_tlv_put_u64(struct rocker_desc_info *desc_info,
- int attrtype, u64 value)
- {
-- return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &value);
-+ u64 tmp = value;
-+
-+ return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp);
- }
-
- static struct rocker_tlv *
-diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
-index 1f2f25a71d18..70f26b30729c 100644
---- a/drivers/net/phy/phy_device.c
-+++ b/drivers/net/phy/phy_device.c
-@@ -1265,20 +1265,17 @@ static int gen10g_resume(struct phy_device *phydev)
-
- static int __set_phy_supported(struct phy_device *phydev, u32 max_speed)
- {
-- phydev->supported &= ~(PHY_1000BT_FEATURES | PHY_100BT_FEATURES |
-- PHY_10BT_FEATURES);
--
- switch (max_speed) {
-- default:
-- return -ENOTSUPP;
-- case SPEED_1000:
-- phydev->supported |= PHY_1000BT_FEATURES;
-+ case SPEED_10:
-+ phydev->supported &= ~PHY_100BT_FEATURES;
- /* fall through */
- case SPEED_100:
-- phydev->supported |= PHY_100BT_FEATURES;
-- /* fall through */
-- case SPEED_10:
-- phydev->supported |= PHY_10BT_FEATURES;
-+ phydev->supported &= ~PHY_1000BT_FEATURES;
-+ break;
-+ case SPEED_1000:
-+ break;
-+ default:
-+ return -ENOTSUPP;
- }
-
- return 0;
-diff --git a/drivers/net/tun.c b/drivers/net/tun.c
-index 5ac0b850d6b1..fd9ff9eff237 100644
---- a/drivers/net/tun.c
-+++ b/drivers/net/tun.c
-@@ -1475,9 +1475,9 @@ static void tun_setup(struct net_device *dev)
- */
- static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
- {
-- if (!data)
-- return 0;
-- return -EINVAL;
-+ /* NL_SET_ERR_MSG(extack,
-+ "tun/tap creation via rtnetlink is not supported."); */
-+ return -EOPNOTSUPP;
- }
-
- static struct rtnl_link_ops tun_link_ops __read_mostly = {
-diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
-index 6ed26baca0e5..7af8479acb98 100644
---- a/drivers/net/wireless/ath/wil6210/wmi.c
-+++ b/drivers/net/wireless/ath/wil6210/wmi.c
-@@ -1035,8 +1035,14 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
- };
- int rc;
- u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
-- struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
-+ struct wmi_set_appie_cmd *cmd;
-
-+ if (len < ie_len) {
-+ rc = -EINVAL;
-+ goto out;
-+ }
-+
-+ cmd = kzalloc(len, GFP_KERNEL);
- if (!cmd) {
- rc = -ENOMEM;
- goto out;
-diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
-index 03054c0e7689..3c3e8115f73d 100644
---- a/drivers/scsi/sr_ioctl.c
-+++ b/drivers/scsi/sr_ioctl.c
-@@ -187,30 +187,25 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
- struct scsi_device *SDev;
- struct scsi_sense_hdr sshdr;
- int result, err = 0, retries = 0;
-- struct request_sense *sense = cgc->sense;
-+ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
-
- SDev = cd->device;
-
-- if (!sense) {
-- sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
-- if (!sense) {
-- err = -ENOMEM;
-- goto out;
-- }
-- }
--
- retry:
- if (!scsi_block_when_processing_errors(SDev)) {
- err = -ENODEV;
- goto out;
- }
-
-- memset(sense, 0, sizeof(*sense));
-+ memset(sense_buffer, 0, sizeof(sense_buffer));
- result = scsi_execute(SDev, cgc->cmd, cgc->data_direction,
-- cgc->buffer, cgc->buflen, (char *)sense,
-+ cgc->buffer, cgc->buflen, sense_buffer,
- cgc->timeout, IOCTL_RETRIES, 0, NULL);
-
-- scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr);
-+ scsi_normalize_sense(sense_buffer, sizeof(sense_buffer), &sshdr);
-+
-+ if (cgc->sense)
-+ memcpy(cgc->sense, sense_buffer, sizeof(*cgc->sense));
-
- /* Minimal error checking. Ignore cases we know about, and report the rest. */
- if (driver_byte(result) != 0) {
-@@ -261,8 +256,6 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
-
- /* Wake up a process waiting for device */
- out:
-- if (!cgc->sense)
-- kfree(sense);
- cgc->stat = err;
- return err;
- }
-diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
-index 2e522951b619..088a68ab4246 100644
---- a/drivers/scsi/st.c
-+++ b/drivers/scsi/st.c
-@@ -4821,9 +4821,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
- current->mm,
- uaddr,
- nr_pages,
-- rw == READ,
-- 0, /* don't force */
-- pages);
-+ pages,
-+ rw == READ ? FOLL_WRITE : 0); /* don't force */
-
- /* Errors and no page mapped should return here */
- if (res < nr_pages)
-diff --git a/drivers/staging/rdma/hfi1/user_pages.c b/drivers/staging/rdma/hfi1/user_pages.c
-index 9071afbd7bf4..b776b74d3d14 100644
---- a/drivers/staging/rdma/hfi1/user_pages.c
-+++ b/drivers/staging/rdma/hfi1/user_pages.c
-@@ -85,7 +85,7 @@ static int __hfi1_get_user_pages(unsigned long start_page, size_t num_pages,
- for (got = 0; got < num_pages; got += ret) {
- ret = get_user_pages(current, current->mm,
- start_page + got * PAGE_SIZE,
-- num_pages - got, 1, 1,
-+ num_pages - got, FOLL_WRITE | FOLL_FORCE,
- p + got, NULL);
- if (ret < 0)
- goto bail_release;
-diff --git a/drivers/staging/rdma/ipath/ipath_user_pages.c b/drivers/staging/rdma/ipath/ipath_user_pages.c
-index d29b4daf61f8..f69ec728e0de 100644
---- a/drivers/staging/rdma/ipath/ipath_user_pages.c
-+++ b/drivers/staging/rdma/ipath/ipath_user_pages.c
-@@ -72,7 +72,7 @@ static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
- for (got = 0; got < num_pages; got += ret) {
- ret = get_user_pages(current, current->mm,
- start_page + got * PAGE_SIZE,
-- num_pages - got, 1, 1,
-+ num_pages - got, FOLL_WRITE | FOLL_FORCE,
- p + got, NULL);
- if (ret < 0)
- goto bail_release;
-diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
-index 06ef26872462..52aed7cfeb24 100644
---- a/drivers/staging/speakup/kobjects.c
-+++ b/drivers/staging/speakup/kobjects.c
-@@ -387,7 +387,7 @@ static ssize_t synth_store(struct kobject *kobj, struct kobj_attribute *attr,
- len = strlen(buf);
- if (len < 2 || len > 9)
- return -EINVAL;
-- strncpy(new_synth_name, buf, len);
-+ memcpy(new_synth_name, buf, len);
- if (new_synth_name[len - 1] == '\n')
- len--;
- new_synth_name[len] = '\0';
-@@ -514,7 +514,7 @@ static ssize_t punc_store(struct kobject *kobj, struct kobj_attribute *attr,
- return -EINVAL;
- }
-
-- strncpy(punc_buf, buf, x);
-+ memcpy(punc_buf, buf, x);
-
- while (x && punc_buf[x - 1] == '\n')
- x--;
-diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
-index 9b7d39484ed3..d1ed92acafa3 100644
---- a/drivers/usb/gadget/udc/omap_udc.c
-+++ b/drivers/usb/gadget/udc/omap_udc.c
-@@ -2037,6 +2037,7 @@ static inline int machine_without_vbus_sense(void)
- {
- return machine_is_omap_innovator()
- || machine_is_omap_osk()
-+ || machine_is_omap_palmte()
- || machine_is_sx1()
- /* No known omap7xx boards with vbus sense */
- || cpu_is_omap7xx();
-@@ -2045,7 +2046,7 @@ static inline int machine_without_vbus_sense(void)
- static int omap_udc_start(struct usb_gadget *g,
- struct usb_gadget_driver *driver)
- {
-- int status = -ENODEV;
-+ int status;
- struct omap_ep *ep;
- unsigned long flags;
-
-@@ -2083,6 +2084,7 @@ static int omap_udc_start(struct usb_gadget *g,
- goto done;
- }
- } else {
-+ status = 0;
- if (can_pullup(udc))
- pullup_enable(udc);
- else
-@@ -2612,9 +2614,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,
-
- static void omap_udc_release(struct device *dev)
- {
-- complete(udc->done);
-+ pullup_disable(udc);
-+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
-+ usb_put_phy(udc->transceiver);
-+ udc->transceiver = NULL;
-+ }
-+ omap_writew(0, UDC_SYSCON1);
-+ remove_proc_file();
-+ if (udc->dc_clk) {
-+ if (udc->clk_requested)
-+ omap_udc_enable_clock(0);
-+ clk_put(udc->hhc_clk);
-+ clk_put(udc->dc_clk);
-+ }
-+ if (udc->done)
-+ complete(udc->done);
- kfree(udc);
-- udc = NULL;
- }
-
- static int
-@@ -2886,8 +2901,8 @@ bad_on_1710:
- udc->clr_halt = UDC_RESET_EP;
-
- /* USB general purpose IRQ: ep0, state changes, dma, etc */
-- status = request_irq(pdev->resource[1].start, omap_udc_irq,
-- 0, driver_name, udc);
-+ status = devm_request_irq(&pdev->dev, pdev->resource[1].start,
-+ omap_udc_irq, 0, driver_name, udc);
- if (status != 0) {
- ERR("can't get irq %d, err %d\n",
- (int) pdev->resource[1].start, status);
-@@ -2895,20 +2910,20 @@ bad_on_1710:
- }
-
- /* USB "non-iso" IRQ (PIO for all but ep0) */
-- status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
-- 0, "omap_udc pio", udc);
-+ status = devm_request_irq(&pdev->dev, pdev->resource[2].start,
-+ omap_udc_pio_irq, 0, "omap_udc pio", udc);
- if (status != 0) {
- ERR("can't get irq %d, err %d\n",
- (int) pdev->resource[2].start, status);
-- goto cleanup2;
-+ goto cleanup1;
- }
- #ifdef USE_ISO
-- status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
-- 0, "omap_udc iso", udc);
-+ status = devm_request_irq(&pdev->dev, pdev->resource[3].start,
-+ omap_udc_iso_irq, 0, "omap_udc iso", udc);
- if (status != 0) {
- ERR("can't get irq %d, err %d\n",
- (int) pdev->resource[3].start, status);
-- goto cleanup3;
-+ goto cleanup1;
- }
- #endif
- if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-@@ -2919,23 +2934,8 @@ bad_on_1710:
- }
-
- create_proc_file();
-- status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
-- omap_udc_release);
-- if (status)
-- goto cleanup4;
--
-- return 0;
--
--cleanup4:
-- remove_proc_file();
--
--#ifdef USE_ISO
--cleanup3:
-- free_irq(pdev->resource[2].start, udc);
--#endif
--
--cleanup2:
-- free_irq(pdev->resource[1].start, udc);
-+ return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
-+ omap_udc_release);
-
- cleanup1:
- kfree(udc);
-@@ -2962,42 +2962,15 @@ static int omap_udc_remove(struct platform_device *pdev)
- {
- DECLARE_COMPLETION_ONSTACK(done);
-
-- if (!udc)
-- return -ENODEV;
--
-- usb_del_gadget_udc(&udc->gadget);
-- if (udc->driver)
-- return -EBUSY;
--
- udc->done = &done;
-
-- pullup_disable(udc);
-- if (!IS_ERR_OR_NULL(udc->transceiver)) {
-- usb_put_phy(udc->transceiver);
-- udc->transceiver = NULL;
-- }
-- omap_writew(0, UDC_SYSCON1);
--
-- remove_proc_file();
--
--#ifdef USE_ISO
-- free_irq(pdev->resource[3].start, udc);
--#endif
-- free_irq(pdev->resource[2].start, udc);
-- free_irq(pdev->resource[1].start, udc);
-+ usb_del_gadget_udc(&udc->gadget);
-
-- if (udc->dc_clk) {
-- if (udc->clk_requested)
-- omap_udc_enable_clock(0);
-- clk_put(udc->hhc_clk);
-- clk_put(udc->dc_clk);
-- }
-+ wait_for_completion(&done);
-
- release_mem_region(pdev->resource[0].start,
- pdev->resource[0].end - pdev->resource[0].start + 1);
-
-- wait_for_completion(&done);
--
- return 0;
- }
-
-diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
-index 195ad7cac1ba..68fa037d8cbc 100644
---- a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
-+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
-@@ -372,7 +372,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
-
- DBG(__func__)
-
-- memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
-+ memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32));
- switch (minfo->fbcon.var.bits_per_pixel) {
- case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
- hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
-diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
-index 0e24eb9c219c..750a384bf191 100644
---- a/drivers/video/fbdev/pvr2fb.c
-+++ b/drivers/video/fbdev/pvr2fb.c
-@@ -687,7 +687,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
- return -ENOMEM;
-
- ret = get_user_pages_unlocked(current, current->mm, (unsigned long)buf,
-- nr_pages, WRITE, 0, pages);
-+ nr_pages, pages, FOLL_WRITE);
-
- if (ret < nr_pages) {
- nr_pages = ret;
-diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
-index 32c8fc5f7a5c..590a0f51a249 100644
---- a/drivers/virt/fsl_hypervisor.c
-+++ b/drivers/virt/fsl_hypervisor.c
-@@ -246,8 +246,8 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
- down_read(¤t->mm->mmap_sem);
- num_pinned = get_user_pages(current, current->mm,
- param.local_vaddr - lb_offset, num_pages,
-- (param.source == -1) ? READ : WRITE,
-- 0, pages, NULL);
-+ (param.source == -1) ? 0 : FOLL_WRITE,
-+ pages, NULL);
- up_read(¤t->mm->mmap_sem);
-
- if (num_pinned != num_pages) {
-diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c
-index 5063c5e796b7..84a1fab0dd6b 100644
---- a/drivers/xen/xlate_mmu.c
-+++ b/drivers/xen/xlate_mmu.c
-@@ -34,6 +34,7 @@
- #include
-
- #include
-+#include
- #include
- #include
- #include
-diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
-index 83c73738165e..40d1ab957fb6 100644
---- a/fs/btrfs/send.c
-+++ b/fs/btrfs/send.c
-@@ -3232,7 +3232,8 @@ static void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m)
- kfree(m);
- }
-
--static void tail_append_pending_moves(struct pending_dir_move *moves,
-+static void tail_append_pending_moves(struct send_ctx *sctx,
-+ struct pending_dir_move *moves,
- struct list_head *stack)
- {
- if (list_empty(&moves->list)) {
-@@ -3243,6 +3244,10 @@ static void tail_append_pending_moves(struct pending_dir_move *moves,
- list_add_tail(&moves->list, stack);
- list_splice_tail(&list, stack);
- }
-+ if (!RB_EMPTY_NODE(&moves->node)) {
-+ rb_erase(&moves->node, &sctx->pending_dir_moves);
-+ RB_CLEAR_NODE(&moves->node);
-+ }
- }
-
- static int apply_children_dir_moves(struct send_ctx *sctx)
-@@ -3257,7 +3262,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
- return 0;
-
- INIT_LIST_HEAD(&stack);
-- tail_append_pending_moves(pm, &stack);
-+ tail_append_pending_moves(sctx, pm, &stack);
-
- while (!list_empty(&stack)) {
- pm = list_first_entry(&stack, struct pending_dir_move, list);
-@@ -3268,7 +3273,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
- goto out;
- pm = get_pending_dir_moves(sctx, parent_ino);
- if (pm)
-- tail_append_pending_moves(pm, &stack);
-+ tail_append_pending_moves(sctx, pm, &stack);
- }
- return 0;
-
-diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
-index 5b68cf526887..c05ab2ec0fef 100644
---- a/fs/cachefiles/rdwr.c
-+++ b/fs/cachefiles/rdwr.c
-@@ -963,11 +963,8 @@ error:
- void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
- {
- struct cachefiles_object *object;
-- struct cachefiles_cache *cache;
-
- object = container_of(_object, struct cachefiles_object, fscache);
-- cache = container_of(object->fscache.cache,
-- struct cachefiles_cache, cache);
-
- _enter("%p,{%lu}", object, page->index);
-
-diff --git a/fs/exec.c b/fs/exec.c
-index 910fc70c4542..3dad755b7048 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
- {
- struct page *page;
- int ret;
-+ unsigned int gup_flags = FOLL_FORCE;
-
- #ifdef CONFIG_STACK_GROWSUP
- if (write) {
-@@ -199,8 +200,12 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
- return NULL;
- }
- #endif
-- ret = get_user_pages(current, bprm->mm, pos,
-- 1, write, 1, &page, NULL);
-+
-+ if (write)
-+ gup_flags |= FOLL_WRITE;
-+
-+ ret = get_user_pages(current, bprm->mm, pos, 1, gup_flags,
-+ &page, NULL);
- if (ret <= 0)
- return NULL;
-
-diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
-index 714cd37a6ba3..6599c6124552 100644
---- a/fs/exportfs/expfs.c
-+++ b/fs/exportfs/expfs.c
-@@ -76,7 +76,7 @@ static bool dentry_connected(struct dentry *dentry)
- struct dentry *parent = dget_parent(dentry);
-
- dput(dentry);
-- if (IS_ROOT(dentry)) {
-+ if (dentry == parent) {
- dput(parent);
- return false;
- }
-diff --git a/fs/fscache/object.c b/fs/fscache/object.c
-index 7a182c87f378..ab1d7f35f6c2 100644
---- a/fs/fscache/object.c
-+++ b/fs/fscache/object.c
-@@ -715,6 +715,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
-
- if (awaken)
- wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
-+ if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
-+ wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
-+
-
- /* Prevent a race with our last child, which has to signal EV_CLEARED
- * before dropping our spinlock.
-diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
-index 1ab19e660e69..1ff5774a5382 100644
---- a/fs/hfs/btree.c
-+++ b/fs/hfs/btree.c
-@@ -328,13 +328,14 @@ void hfs_bmap_free(struct hfs_bnode *node)
-
- nidx -= len * 8;
- i = node->next;
-- hfs_bnode_put(node);
- if (!i) {
- /* panic */;
- pr_crit("unable to free bnode %u. bmap not found!\n",
- node->this);
-+ hfs_bnode_put(node);
- return;
- }
-+ hfs_bnode_put(node);
- node = hfs_bnode_find(tree, i);
- if (IS_ERR(node))
- return;
-diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
-index 3345c7553edc..7adc8a327e03 100644
---- a/fs/hfsplus/btree.c
-+++ b/fs/hfsplus/btree.c
-@@ -453,14 +453,15 @@ void hfs_bmap_free(struct hfs_bnode *node)
-
- nidx -= len * 8;
- i = node->next;
-- hfs_bnode_put(node);
- if (!i) {
- /* panic */;
- pr_crit("unable to free bnode %u. "
- "bmap not found!\n",
- node->this);
-+ hfs_bnode_put(node);
- return;
- }
-+ hfs_bnode_put(node);
- node = hfs_bnode_find(tree, i);
- if (IS_ERR(node))
- return;
-diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
-index a17da8b57fc6..ab34f613fa85 100644
---- a/fs/hugetlbfs/inode.c
-+++ b/fs/hugetlbfs/inode.c
-@@ -118,6 +118,16 @@ static void huge_pagevec_release(struct pagevec *pvec)
- pagevec_reinit(pvec);
- }
-
-+/*
-+ * Mask used when checking the page offset value passed in via system
-+ * calls. This value will be converted to a loff_t which is signed.
-+ * Therefore, we want to check the upper PAGE_SHIFT + 1 bits of the
-+ * value. The extra bit (- 1 in the shift value) is to take the sign
-+ * bit into account.
-+ */
-+#define PGOFF_LOFFT_MAX \
-+ (((1UL << (PAGE_SHIFT + 1)) - 1) << (BITS_PER_LONG - (PAGE_SHIFT + 1)))
-+
- static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
- {
- struct inode *inode = file_inode(file);
-@@ -136,17 +146,31 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
- vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
- vma->vm_ops = &hugetlb_vm_ops;
-
-+ /*
-+ * page based offset in vm_pgoff could be sufficiently large to
-+ * overflow a loff_t when converted to byte offset. This can
-+ * only happen on architectures where sizeof(loff_t) ==
-+ * sizeof(unsigned long). So, only check in those instances.
-+ */
-+ if (sizeof(unsigned long) == sizeof(loff_t)) {
-+ if (vma->vm_pgoff & PGOFF_LOFFT_MAX)
-+ return -EINVAL;
-+ }
-+
-+ /* must be huge page aligned */
- if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
- return -EINVAL;
-
- vma_len = (loff_t)(vma->vm_end - vma->vm_start);
-+ len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
-+ /* check for overflow */
-+ if (len < vma_len)
-+ return -EINVAL;
-
- mutex_lock(&inode->i_mutex);
- file_accessed(file);
-
- ret = -ENOMEM;
-- len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
--
- if (hugetlb_reserve_pages(inode,
- vma->vm_pgoff >> huge_page_order(h),
- len >> huge_page_shift(h), vma,
-@@ -155,7 +179,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
-
- ret = 0;
- if (vma->vm_flags & VM_WRITE && inode->i_size < len)
-- inode->i_size = len;
-+ i_size_write(inode, len);
- out:
- mutex_unlock(&inode->i_mutex);
-
-diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
-index 827fc9809bc2..3494e220b510 100644
---- a/fs/ocfs2/export.c
-+++ b/fs/ocfs2/export.c
-@@ -125,10 +125,10 @@ check_err:
-
- check_gen:
- if (handle->ih_generation != inode->i_generation) {
-- iput(inode);
- trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
- handle->ih_generation,
- inode->i_generation);
-+ iput(inode);
- result = ERR_PTR(-ESTALE);
- goto bail;
- }
-diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
-index 124471d26a73..c1a83c58456e 100644
---- a/fs/ocfs2/move_extents.c
-+++ b/fs/ocfs2/move_extents.c
-@@ -156,18 +156,14 @@ out:
- }
-
- /*
-- * lock allocators, and reserving appropriate number of bits for
-- * meta blocks and data clusters.
-- *
-- * in some cases, we don't need to reserve clusters, just let data_ac
-- * be NULL.
-+ * lock allocator, and reserve appropriate number of bits for
-+ * meta blocks.
- */
--static int ocfs2_lock_allocators_move_extents(struct inode *inode,
-+static int ocfs2_lock_meta_allocator_move_extents(struct inode *inode,
- struct ocfs2_extent_tree *et,
- u32 clusters_to_move,
- u32 extents_to_split,
- struct ocfs2_alloc_context **meta_ac,
-- struct ocfs2_alloc_context **data_ac,
- int extra_blocks,
- int *credits)
- {
-@@ -192,13 +188,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode,
- goto out;
- }
-
-- if (data_ac) {
-- ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac);
-- if (ret) {
-- mlog_errno(ret);
-- goto out;
-- }
-- }
-
- *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);
-
-@@ -260,10 +249,10 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
- }
- }
-
-- ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1,
-- &context->meta_ac,
-- &context->data_ac,
-- extra_blocks, &credits);
-+ ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
-+ *len, 1,
-+ &context->meta_ac,
-+ extra_blocks, &credits);
- if (ret) {
- mlog_errno(ret);
- goto out;
-@@ -286,6 +275,21 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
- }
- }
-
-+ /*
-+ * Make sure ocfs2_reserve_cluster is called after
-+ * __ocfs2_flush_truncate_log, otherwise, dead lock may happen.
-+ *
-+ * If ocfs2_reserve_cluster is called
-+ * before __ocfs2_flush_truncate_log, dead lock on global bitmap
-+ * may happen.
-+ *
-+ */
-+ ret = ocfs2_reserve_clusters(osb, *len, &context->data_ac);
-+ if (ret) {
-+ mlog_errno(ret);
-+ goto out_unlock_mutex;
-+ }
-+
- handle = ocfs2_start_trans(osb, credits);
- if (IS_ERR(handle)) {
- ret = PTR_ERR(handle);
-@@ -606,9 +610,10 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
- }
- }
-
-- ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1,
-- &context->meta_ac,
-- NULL, extra_blocks, &credits);
-+ ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
-+ len, 1,
-+ &context->meta_ac,
-+ extra_blocks, &credits);
- if (ret) {
- mlog_errno(ret);
- goto out;
-diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 4beed301e224..bd8c26a409a7 100644
---- a/fs/proc/base.c
-+++ b/fs/proc/base.c
-@@ -254,7 +254,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
- * Inherently racy -- command line shares address space
- * with code and data.
- */
-- rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0);
-+ rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
- if (rv <= 0)
- goto out_free_page;
-
-@@ -272,7 +272,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
- int nr_read;
-
- _count = min3(count, len, PAGE_SIZE);
-- nr_read = access_remote_vm(mm, p, page, _count, 0);
-+ nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
- if (nr_read < 0)
- rv = nr_read;
- if (nr_read <= 0)
-@@ -307,7 +307,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
- bool final;
-
- _count = min3(count, len, PAGE_SIZE);
-- nr_read = access_remote_vm(mm, p, page, _count, 0);
-+ nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
- if (nr_read < 0)
- rv = nr_read;
- if (nr_read <= 0)
-@@ -356,7 +356,7 @@ skip_argv:
- bool final;
-
- _count = min3(count, len, PAGE_SIZE);
-- nr_read = access_remote_vm(mm, p, page, _count, 0);
-+ nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
- if (nr_read < 0)
- rv = nr_read;
- if (nr_read <= 0)
-@@ -868,6 +868,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
- unsigned long addr = *ppos;
- ssize_t copied;
- char *page;
-+ unsigned int flags;
-
- if (!mm)
- return 0;
-@@ -880,6 +881,11 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
- if (!atomic_inc_not_zero(&mm->mm_users))
- goto free;
-
-+ /* Maybe we should limit FOLL_FORCE to actual ptrace users? */
-+ flags = FOLL_FORCE;
-+ if (write)
-+ flags |= FOLL_WRITE;
-+
- while (count > 0) {
- int this_len = min_t(int, count, PAGE_SIZE);
-
-@@ -888,7 +894,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
- break;
- }
-
-- this_len = access_remote_vm(mm, addr, page, this_len, write);
-+ this_len = access_remote_vm(mm, addr, page, this_len, flags);
- if (!this_len) {
- if (!copied)
- copied = -EIO;
-@@ -1000,8 +1006,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
- max_len = min_t(size_t, PAGE_SIZE, count);
- this_len = min(max_len, this_len);
-
-- retval = access_remote_vm(mm, (env_start + src),
-- page, this_len, 0);
-+ retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
-
- if (retval <= 0) {
- ret = retval;
-diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
-index 588461bb2dd4..e97e7d74e134 100644
---- a/fs/pstore/platform.c
-+++ b/fs/pstore/platform.c
-@@ -392,8 +392,8 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
- } else {
- spin_lock_irqsave(&psinfo->buf_lock, flags);
- }
-- memcpy(psinfo->buf, s, c);
-- psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, 0, 0, c, psinfo);
-+ psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0,
-+ s, 0, c, psinfo);
- spin_unlock_irqrestore(&psinfo->buf_lock, flags);
- s += c;
- c = e - s;
-diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
-index 02fa1dcc5969..29f5b2e589a1 100644
---- a/fs/sysv/inode.c
-+++ b/fs/sysv/inode.c
-@@ -275,7 +275,7 @@ static int __sysv_write_inode(struct inode *inode, int wait)
- }
- }
- brelse(bh);
-- return 0;
-+ return err;
- }
-
- int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
-diff --git a/include/linux/mm.h b/include/linux/mm.h
-index d4e8077fca96..251adf4d8a71 100644
---- a/include/linux/mm.h
-+++ b/include/linux/mm.h
-@@ -1191,7 +1191,7 @@ static inline int fixup_user_fault(struct task_struct *tsk,
-
- extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
- extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-- void *buf, int len, int write);
-+ void *buf, int len, unsigned int gup_flags);
-
- long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-@@ -1199,19 +1199,17 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
- struct vm_area_struct **vmas, int *nonblocking);
- long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-+ unsigned int gup_flags, struct page **pages,
- struct vm_area_struct **vmas);
- long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-- int *locked);
-+ unsigned int gup_flags, struct page **pages, int *locked);
- long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-- unsigned int gup_flags);
-+ struct page **pages, unsigned int gup_flags);
- long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages);
-+ struct page **pages, unsigned int gup_flags);
- int get_user_pages_fast(unsigned long start, int nr_pages, int write,
- struct page **pages);
-
-@@ -1229,7 +1227,7 @@ struct frame_vector {
- struct frame_vector *frame_vector_create(unsigned int nr_frames);
- void frame_vector_destroy(struct frame_vector *vec);
- int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
-- bool write, bool force, struct frame_vector *vec);
-+ unsigned int gup_flags, struct frame_vector *vec);
- void put_vaddr_frames(struct frame_vector *vec);
- int frame_vector_to_pages(struct frame_vector *vec);
- void frame_vector_to_pfns(struct frame_vector *vec);
-@@ -2122,6 +2120,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
- #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */
- #define FOLL_MLOCK 0x1000 /* lock present pages */
- #define FOLL_COW 0x4000 /* internal GUP flag */
-+#define FOLL_ANON 0x8000 /* don't do file mappings */
-
- typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
- void *data);
-diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
-index 907f3fd191ac..3e28a1a8d823 100644
---- a/include/linux/posix-timers.h
-+++ b/include/linux/posix-timers.h
-@@ -65,8 +65,8 @@ struct k_itimer {
- spinlock_t it_lock;
- clockid_t it_clock; /* which timer type */
- timer_t it_id; /* timer id */
-- int it_overrun; /* overrun on pending signal */
-- int it_overrun_last; /* overrun on last delivered signal */
-+ s64 it_overrun; /* overrun on pending signal */
-+ s64 it_overrun_last; /* overrun on last delivered signal */
- int it_requeue_pending; /* waiting to requeue this timer */
- #define REQUEUE_PENDING 1
- int it_sigev_notify; /* notify word of sigevent struct */
-diff --git a/include/net/neighbour.h b/include/net/neighbour.h
-index 8b683841e574..f6017ddc4ded 100644
---- a/include/net/neighbour.h
-+++ b/include/net/neighbour.h
-@@ -448,6 +448,7 @@ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
-
- static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
- {
-+ unsigned int hh_alen = 0;
- unsigned int seq;
- int hh_len;
-
-@@ -455,16 +456,33 @@ static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb
- seq = read_seqbegin(&hh->hh_lock);
- hh_len = hh->hh_len;
- if (likely(hh_len <= HH_DATA_MOD)) {
-- /* this is inlined by gcc */
-- memcpy(skb->data - HH_DATA_MOD, hh->hh_data, HH_DATA_MOD);
-+ hh_alen = HH_DATA_MOD;
-+
-+ /* skb_push() would proceed silently if we have room for
-+ * the unaligned size but not for the aligned size:
-+ * check headroom explicitly.
-+ */
-+ if (likely(skb_headroom(skb) >= HH_DATA_MOD)) {
-+ /* this is inlined by gcc */
-+ memcpy(skb->data - HH_DATA_MOD, hh->hh_data,
-+ HH_DATA_MOD);
-+ }
- } else {
-- int hh_alen = HH_DATA_ALIGN(hh_len);
-+ hh_alen = HH_DATA_ALIGN(hh_len);
-
-- memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
-+ if (likely(skb_headroom(skb) >= hh_alen)) {
-+ memcpy(skb->data - hh_alen, hh->hh_data,
-+ hh_alen);
-+ }
- }
- } while (read_seqretry(&hh->hh_lock, seq));
-
-- skb_push(skb, hh_len);
-+ if (WARN_ON_ONCE(skb_headroom(skb) < hh_alen)) {
-+ kfree_skb(skb);
-+ return NET_XMIT_DROP;
-+ }
-+
-+ __skb_push(skb, hh_len);
- return dev_queue_xmit(skb);
- }
-
-diff --git a/include/sound/pcm.h b/include/sound/pcm.h
-index b0be09279943..ffc161906d36 100644
---- a/include/sound/pcm.h
-+++ b/include/sound/pcm.h
-@@ -100,7 +100,7 @@ struct snd_pcm_ops {
- #endif
-
- #define SNDRV_PCM_IOCTL1_RESET 0
--#define SNDRV_PCM_IOCTL1_INFO 1
-+/* 1 is absent slot. */
- #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2
- #define SNDRV_PCM_IOCTL1_GSTATE 3
- #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4
-diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
-index 35dfa9e9d69e..c43ca9857479 100644
---- a/kernel/bpf/verifier.c
-+++ b/kernel/bpf/verifier.c
-@@ -191,6 +191,7 @@ struct bpf_insn_aux_data {
- enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
- struct bpf_map *map_ptr; /* pointer for call insn into lookup_elem */
- };
-+ int sanitize_stack_off; /* stack slot to be cleared */
- bool seen; /* this insn was processed by the verifier */
- };
-
-@@ -569,10 +570,11 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
- /* check_stack_read/write functions track spill/fill of registers,
- * stack boundary and alignment are checked in check_mem_access()
- */
--static int check_stack_write(struct verifier_state *state, int off, int size,
-- int value_regno)
-+static int check_stack_write(struct verifier_env *env,
-+ struct verifier_state *state, int off,
-+ int size, int value_regno, int insn_idx)
- {
-- int i;
-+ int i, spi = (MAX_BPF_STACK + off) / BPF_REG_SIZE;
- /* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0,
- * so it's aligned access and [off, off + size) are within stack limits
- */
-@@ -587,15 +589,37 @@ static int check_stack_write(struct verifier_state *state, int off, int size,
- }
-
- /* save register state */
-- state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
-- state->regs[value_regno];
--
-- for (i = 0; i < BPF_REG_SIZE; i++)
-+ state->spilled_regs[spi] = state->regs[value_regno];
-+
-+ for (i = 0; i < BPF_REG_SIZE; i++) {
-+ if (state->stack_slot_type[MAX_BPF_STACK + off + i] == STACK_MISC &&
-+ !env->allow_ptr_leaks) {
-+ int *poff = &env->insn_aux_data[insn_idx].sanitize_stack_off;
-+ int soff = (-spi - 1) * BPF_REG_SIZE;
-+
-+ /* detected reuse of integer stack slot with a pointer
-+ * which means either llvm is reusing stack slot or
-+ * an attacker is trying to exploit CVE-2018-3639
-+ * (speculative store bypass)
-+ * Have to sanitize that slot with preemptive
-+ * store of zero.
-+ */
-+ if (*poff && *poff != soff) {
-+ /* disallow programs where single insn stores
-+ * into two different stack slots, since verifier
-+ * cannot sanitize them
-+ */
-+ verbose("insn %d cannot access two stack slots fp%d and fp%d",
-+ insn_idx, *poff, soff);
-+ return -EINVAL;
-+ }
-+ *poff = soff;
-+ }
- state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_SPILL;
-+ }
- } else {
- /* regular write of data into stack */
-- state->spilled_regs[(MAX_BPF_STACK + off) / BPF_REG_SIZE] =
-- (struct reg_state) {};
-+ state->spilled_regs[spi] = (struct reg_state) {};
-
- for (i = 0; i < size; i++)
- state->stack_slot_type[MAX_BPF_STACK + off + i] = STACK_MISC;
-@@ -696,7 +720,7 @@ static bool is_ctx_reg(struct verifier_env *env, int regno)
- * if t==write && value_regno==-1, some unknown value is stored into memory
- * if t==read && value_regno==-1, don't care what we read from memory
- */
--static int check_mem_access(struct verifier_env *env, u32 regno, int off,
-+static int check_mem_access(struct verifier_env *env, int insn_idx, u32 regno, int off,
- int bpf_size, enum bpf_access_type t,
- int value_regno)
- {
-@@ -748,7 +772,8 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
- verbose("attempt to corrupt spilled pointer on stack\n");
- return -EACCES;
- }
-- err = check_stack_write(state, off, size, value_regno);
-+ err = check_stack_write(env, state, off, size,
-+ value_regno, insn_idx);
- } else {
- err = check_stack_read(state, off, size, value_regno);
- }
-@@ -760,7 +785,7 @@ static int check_mem_access(struct verifier_env *env, u32 regno, int off,
- return err;
- }
-
--static int check_xadd(struct verifier_env *env, struct bpf_insn *insn)
-+static int check_xadd(struct verifier_env *env, int insn_idx, struct bpf_insn *insn)
- {
- struct reg_state *regs = env->cur_state.regs;
- int err;
-@@ -793,13 +818,13 @@ static int check_xadd(struct verifier_env *env, struct bpf_insn *insn)
- }
-
- /* check whether atomic_add can read the memory */
-- err = check_mem_access(env, insn->dst_reg, insn->off,
-+ err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
- BPF_SIZE(insn->code), BPF_READ, -1);
- if (err)
- return err;
-
- /* check whether atomic_add can write into the same memory */
-- return check_mem_access(env, insn->dst_reg, insn->off,
-+ return check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
- BPF_SIZE(insn->code), BPF_WRITE, -1);
- }
-
-@@ -1838,13 +1863,14 @@ static int do_check(struct verifier_env *env)
- /* check that memory (src_reg + off) is readable,
- * the state of dst_reg will be updated by this func
- */
-- err = check_mem_access(env, insn->src_reg, insn->off,
-+ err = check_mem_access(env, insn_idx, insn->src_reg, insn->off,
- BPF_SIZE(insn->code), BPF_READ,
- insn->dst_reg);
- if (err)
- return err;
-
-- if (BPF_SIZE(insn->code) != BPF_W) {
-+ if (BPF_SIZE(insn->code) != BPF_W &&
-+ BPF_SIZE(insn->code) != BPF_DW) {
- insn_idx++;
- continue;
- }
-@@ -1876,7 +1902,7 @@ static int do_check(struct verifier_env *env)
- enum bpf_reg_type *prev_dst_type, dst_reg_type;
-
- if (BPF_MODE(insn->code) == BPF_XADD) {
-- err = check_xadd(env, insn);
-+ err = check_xadd(env, insn_idx, insn);
- if (err)
- return err;
- insn_idx++;
-@@ -1895,7 +1921,7 @@ static int do_check(struct verifier_env *env)
- dst_reg_type = regs[insn->dst_reg].type;
-
- /* check that memory (dst_reg + off) is writeable */
-- err = check_mem_access(env, insn->dst_reg, insn->off,
-+ err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
- BPF_SIZE(insn->code), BPF_WRITE,
- insn->src_reg);
- if (err)
-@@ -1930,7 +1956,7 @@ static int do_check(struct verifier_env *env)
- }
-
- /* check that memory (dst_reg + off) is writeable */
-- err = check_mem_access(env, insn->dst_reg, insn->off,
-+ err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,
- BPF_SIZE(insn->code), BPF_WRITE,
- -1);
- if (err)
-@@ -2220,13 +2246,43 @@ static int convert_ctx_accesses(struct verifier_env *env)
- for (i = 0; i < insn_cnt; i++, insn++) {
- u32 cnt;
-
-- if (insn->code == (BPF_LDX | BPF_MEM | BPF_W))
-+ if (insn->code == (BPF_LDX | BPF_MEM | BPF_W) ||
-+ insn->code == (BPF_LDX | BPF_MEM | BPF_DW))
- type = BPF_READ;
-- else if (insn->code == (BPF_STX | BPF_MEM | BPF_W))
-+ else if (insn->code == (BPF_STX | BPF_MEM | BPF_W) ||
-+ insn->code == (BPF_STX | BPF_MEM | BPF_DW))
- type = BPF_WRITE;
- else
- continue;
-
-+ if (type == BPF_WRITE &&
-+ env->insn_aux_data[i + delta].sanitize_stack_off) {
-+ struct bpf_insn patch[] = {
-+ /* Sanitize suspicious stack slot with zero.
-+ * There are no memory dependencies for this store,
-+ * since it's only using frame pointer and immediate
-+ * constant of zero
-+ */
-+ BPF_ST_MEM(BPF_DW, BPF_REG_FP,
-+ env->insn_aux_data[i + delta].sanitize_stack_off,
-+ 0),
-+ /* the original STX instruction will immediately
-+ * overwrite the same stack slot with appropriate value
-+ */
-+ *insn,
-+ };
-+
-+ cnt = ARRAY_SIZE(patch);
-+ new_prog = bpf_patch_insn_data(env, i + delta, patch, cnt);
-+ if (!new_prog)
-+ return -ENOMEM;
-+
-+ delta += cnt - 1;
-+ env->prog = new_prog;
-+ insn = new_prog->insnsi + i + delta;
-+ continue;
-+ }
-+
- if (env->insn_aux_data[i + delta].ptr_type != PTR_TO_CTX)
- continue;
-
-diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
-index 7108097fa2f2..aad43c88a668 100644
---- a/kernel/events/uprobes.c
-+++ b/kernel/events/uprobes.c
-@@ -299,7 +299,7 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
-
- retry:
- /* Read the page with vaddr into memory */
-- ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
-+ ret = get_user_pages(NULL, mm, vaddr, 1, FOLL_FORCE, &old_page, &vma);
- if (ret <= 0)
- return ret;
-
-@@ -1700,7 +1700,7 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
- if (likely(result == 0))
- goto out;
-
-- result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
-+ result = get_user_pages(NULL, mm, vaddr, 1, FOLL_FORCE, &page, NULL);
- if (result < 0)
- return result;
-
-diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
-index 80016b329d94..8fc68e60c795 100644
---- a/kernel/time/posix-cpu-timers.c
-+++ b/kernel/time/posix-cpu-timers.c
-@@ -103,7 +103,7 @@ static void bump_cpu_timer(struct k_itimer *timer,
- continue;
-
- timer->it.cpu.expires += incr;
-- timer->it_overrun += 1 << i;
-+ timer->it_overrun += 1LL << i;
- delta -= incr;
- }
- }
-diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
-index fc7c37ad90a0..0e6ed2e7d066 100644
---- a/kernel/time/posix-timers.c
-+++ b/kernel/time/posix-timers.c
-@@ -355,6 +355,17 @@ static __init int init_posix_timers(void)
-
- __initcall(init_posix_timers);
-
-+/*
-+ * The siginfo si_overrun field and the return value of timer_getoverrun(2)
-+ * are of type int. Clamp the overrun value to INT_MAX
-+ */
-+static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval)
-+{
-+ s64 sum = timr->it_overrun_last + (s64)baseval;
-+
-+ return sum > (s64)INT_MAX ? INT_MAX : (int)sum;
-+}
-+
- static void schedule_next_timer(struct k_itimer *timr)
- {
- struct hrtimer *timer = &timr->it.real.timer;
-@@ -362,12 +373,11 @@ static void schedule_next_timer(struct k_itimer *timr)
- if (timr->it.real.interval.tv64 == 0)
- return;
-
-- timr->it_overrun += (unsigned int) hrtimer_forward(timer,
-- timer->base->get_time(),
-- timr->it.real.interval);
-+ timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
-+ timr->it.real.interval);
-
- timr->it_overrun_last = timr->it_overrun;
-- timr->it_overrun = -1;
-+ timr->it_overrun = -1LL;
- ++timr->it_requeue_pending;
- hrtimer_restart(timer);
- }
-@@ -396,7 +406,7 @@ void do_schedule_next_timer(struct siginfo *info)
- else
- schedule_next_timer(timr);
-
-- info->si_overrun += timr->it_overrun_last;
-+ info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
- }
-
- if (timr)
-@@ -491,8 +501,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
- now = ktime_add(now, kj);
- }
- #endif
-- timr->it_overrun += (unsigned int)
-- hrtimer_forward(timer, now,
-+ timr->it_overrun += hrtimer_forward(timer, now,
- timr->it.real.interval);
- ret = HRTIMER_RESTART;
- ++timr->it_requeue_pending;
-@@ -633,7 +642,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
- it_id_set = IT_ID_SET;
- new_timer->it_id = (timer_t) new_timer_id;
- new_timer->it_clock = which_clock;
-- new_timer->it_overrun = -1;
-+ new_timer->it_overrun = -1LL;
-
- if (timer_event_spec) {
- if (copy_from_user(&event, timer_event_spec, sizeof (event))) {
-@@ -762,7 +771,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
- */
- if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
- timr->it_sigev_notify == SIGEV_NONE))
-- timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
-+ timr->it_overrun += hrtimer_forward(timer, now, iv);
-
- remaining = __hrtimer_expires_remaining_adjusted(timer, now);
- /* Return 0 only, when the timer is expired and not pending */
-@@ -824,7 +833,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
- if (!timr)
- return -EINVAL;
-
-- overrun = timr->it_overrun_last;
-+ overrun = timer_overrun_to_int(timr, 0);
- unlock_timer(timr, flags);
-
- return overrun;
-diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
-index 4228fd3682c3..3dd40c736067 100644
---- a/kernel/trace/bpf_trace.c
-+++ b/kernel/trace/bpf_trace.c
-@@ -119,11 +119,13 @@ static u64 bpf_trace_printk(u64 r1, u64 fmt_size, u64 r3, u64 r4, u64 r5)
- i++;
- } else if (fmt[i] == 'p' || fmt[i] == 's') {
- mod[fmt_cnt]++;
-- i++;
-- if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
-+ /* disallow any further format extensions */
-+ if (fmt[i + 1] != 0 &&
-+ !isspace(fmt[i + 1]) &&
-+ !ispunct(fmt[i + 1]))
- return -EINVAL;
- fmt_cnt++;
-- if (fmt[i - 1] == 's') {
-+ if (fmt[i] == 's') {
- if (str_seen)
- /* allow only one '%s' per fmt string */
- return -EINVAL;
-diff --git a/lib/debugobjects.c b/lib/debugobjects.c
-index a26328ec39f1..bb37541cd441 100644
---- a/lib/debugobjects.c
-+++ b/lib/debugobjects.c
-@@ -1088,7 +1088,8 @@ void __init debug_objects_mem_init(void)
-
- obj_cache = kmem_cache_create("debug_objects_cache",
- sizeof (struct debug_obj), 0,
-- SLAB_DEBUG_OBJECTS, NULL);
-+ SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE,
-+ NULL);
-
- if (!obj_cache || debug_objects_replace_static_objects()) {
- debug_objects_enabled = 0;
-diff --git a/lib/swiotlb.c b/lib/swiotlb.c
-index 771234d050c7..6bc452b33b76 100644
---- a/lib/swiotlb.c
-+++ b/lib/swiotlb.c
-@@ -17,6 +17,8 @@
- * 08/12/11 beckyb Add highmem support
- */
-
-+#define pr_fmt(fmt) "software IO TLB: " fmt
-+
- #include
- #include
- #include
-@@ -143,20 +145,16 @@ static bool no_iotlb_memory;
- void swiotlb_print_info(void)
- {
- unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
-- unsigned char *vstart, *vend;
-
- if (no_iotlb_memory) {
-- pr_warn("software IO TLB: No low mem\n");
-+ pr_warn("No low mem\n");
- return;
- }
-
-- vstart = phys_to_virt(io_tlb_start);
-- vend = phys_to_virt(io_tlb_end);
--
-- printk(KERN_INFO "software IO TLB [mem %#010llx-%#010llx] (%luMB) mapped at [%p-%p]\n",
-+ pr_info("mapped [mem %#010llx-%#010llx] (%luMB)\n",
- (unsigned long long)io_tlb_start,
- (unsigned long long)io_tlb_end,
-- bytes >> 20, vstart, vend - 1);
-+ bytes >> 20);
- }
-
- int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
-@@ -230,7 +228,7 @@ swiotlb_init(int verbose)
- if (io_tlb_start)
- memblock_free_early(io_tlb_start,
- PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
-- pr_warn("Cannot allocate SWIOTLB buffer");
-+ pr_warn("Cannot allocate buffer");
- no_iotlb_memory = true;
- }
-
-@@ -272,8 +270,8 @@ swiotlb_late_init_with_default_size(size_t default_size)
- return -ENOMEM;
- }
- if (order != get_order(bytes)) {
-- printk(KERN_WARNING "Warning: only able to allocate %ld MB "
-- "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
-+ pr_warn("only able to allocate %ld MB\n",
-+ (PAGE_SIZE << order) >> 20);
- io_tlb_nslabs = SLABS_PER_PAGE << order;
- }
- rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
-@@ -680,7 +678,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- return ret;
-
- err_warn:
-- pr_warn("swiotlb: coherent allocation failed for device %s size=%zu\n",
-+ pr_warn("coherent allocation failed for device %s size=%zu\n",
- dev_name(hwdev), size);
- dump_stack();
-
-diff --git a/mm/frame_vector.c b/mm/frame_vector.c
-index 7cf2b7163222..c1e7926a41c4 100644
---- a/mm/frame_vector.c
-+++ b/mm/frame_vector.c
-@@ -11,10 +11,7 @@
- * get_vaddr_frames() - map virtual addresses to pfns
- * @start: starting user address
- * @nr_frames: number of pages / pfns from start to map
-- * @write: whether pages will be written to by the caller
-- * @force: whether to force write access even if user mapping is
-- * readonly. See description of the same argument of
-- get_user_pages().
-+ * @gup_flags: flags modifying lookup behaviour
- * @vec: structure which receives pages / pfns of the addresses mapped.
- * It should have space for at least nr_frames entries.
- *
-@@ -34,7 +31,7 @@
- * This function takes care of grabbing mmap_sem as necessary.
- */
- int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
-- bool write, bool force, struct frame_vector *vec)
-+ unsigned int gup_flags, struct frame_vector *vec)
- {
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
-@@ -59,7 +56,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
- vec->got_ref = true;
- vec->is_pfns = false;
- ret = get_user_pages_locked(current, mm, start, nr_frames,
-- write, force, (struct page **)(vec->ptrs), &locked);
-+ gup_flags, (struct page **)(vec->ptrs), &locked);
- goto out;
- }
-
-diff --git a/mm/gup.c b/mm/gup.c
-index 018144c4b9ec..2cd3b31e3666 100644
---- a/mm/gup.c
-+++ b/mm/gup.c
-@@ -368,6 +368,9 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
- if (vm_flags & (VM_IO | VM_PFNMAP))
- return -EFAULT;
-
-+ if (gup_flags & FOLL_ANON && !vma_is_anonymous(vma))
-+ return -EFAULT;
-+
- if (gup_flags & FOLL_WRITE) {
- if (!(vm_flags & VM_WRITE)) {
- if (!(gup_flags & FOLL_FORCE))
-@@ -627,7 +630,6 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
- struct mm_struct *mm,
- unsigned long start,
- unsigned long nr_pages,
-- int write, int force,
- struct page **pages,
- struct vm_area_struct **vmas,
- int *locked, bool notify_drop,
-@@ -645,10 +647,6 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
-
- if (pages)
- flags |= FOLL_GET;
-- if (write)
-- flags |= FOLL_WRITE;
-- if (force)
-- flags |= FOLL_FORCE;
-
- pages_done = 0;
- lock_dropped = false;
-@@ -742,11 +740,12 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
- */
- long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-+ unsigned int gup_flags, struct page **pages,
- int *locked)
- {
-- return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
-- pages, NULL, locked, true, FOLL_TOUCH);
-+ return __get_user_pages_locked(tsk, mm, start, nr_pages,
-+ pages, NULL, locked, true,
-+ gup_flags | FOLL_TOUCH);
- }
- EXPORT_SYMBOL(get_user_pages_locked);
-
-@@ -762,14 +761,14 @@ EXPORT_SYMBOL(get_user_pages_locked);
- */
- __always_inline long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-- unsigned int gup_flags)
-+ struct page **pages, unsigned int gup_flags)
- {
- long ret;
- int locked = 1;
-+
- down_read(&mm->mmap_sem);
-- ret = __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
-- pages, NULL, &locked, false, gup_flags);
-+ ret = __get_user_pages_locked(tsk, mm, start, nr_pages, pages, NULL,
-+ &locked, false, gup_flags);
- if (locked)
- up_read(&mm->mmap_sem);
- return ret;
-@@ -795,10 +794,10 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
- */
- long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages)
-+ struct page **pages, unsigned int gup_flags)
- {
-- return __get_user_pages_unlocked(tsk, mm, start, nr_pages, write,
-- force, pages, FOLL_TOUCH);
-+ return __get_user_pages_unlocked(tsk, mm, start, nr_pages,
-+ pages, gup_flags | FOLL_TOUCH);
- }
- EXPORT_SYMBOL(get_user_pages_unlocked);
-
-@@ -858,11 +857,13 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
- * FAULT_FLAG_ALLOW_RETRY to handle_mm_fault.
- */
- long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-- unsigned long start, unsigned long nr_pages, int write,
-- int force, struct page **pages, struct vm_area_struct **vmas)
-+ unsigned long start, unsigned long nr_pages,
-+ unsigned int gup_flags, struct page **pages,
-+ struct vm_area_struct **vmas)
- {
-- return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
-- pages, vmas, NULL, false, FOLL_TOUCH);
-+ return __get_user_pages_locked(tsk, mm, start, nr_pages,
-+ pages, vmas, NULL, false,
-+ gup_flags | FOLL_TOUCH);
- }
- EXPORT_SYMBOL(get_user_pages);
-
-@@ -1411,7 +1412,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
- pages += nr;
-
- ret = get_user_pages_unlocked(current, mm, start,
-- nr_pages - nr, write, 0, pages);
-+ nr_pages - nr, pages,
-+ write ? FOLL_WRITE : 0);
-
- /* Have to be a bit careful with return values */
- if (nr > 0) {
-diff --git a/mm/hugetlb.c b/mm/hugetlb.c
-index 6f99a0f906bb..f1a45f5077fe 100644
---- a/mm/hugetlb.c
-+++ b/mm/hugetlb.c
-@@ -4053,6 +4053,14 @@ int hugetlb_reserve_pages(struct inode *inode,
- struct resv_map *resv_map;
- long gbl_reserve;
-
-+ /* This should never happen */
-+ if (from > to) {
-+#ifdef CONFIG_DEBUG_VM
-+ WARN(1, "%s called with a negative range\n", __func__);
-+#endif
-+ return -EINVAL;
-+ }
-+
- /*
- * Only apply hugepage reservation if asked. At fault time, an
- * attempt will be made for VM_NORESERVE to allocate a page
-@@ -4142,7 +4150,9 @@ int hugetlb_reserve_pages(struct inode *inode,
- return 0;
- out_err:
- if (!vma || vma->vm_flags & VM_MAYSHARE)
-- region_abort(resv_map, from, to);
-+ /* Don't call region_abort if region_chg failed */
-+ if (chg >= 0)
-+ region_abort(resv_map, from, to);
- if (vma && is_vma_resv_set(vma, HPAGE_RESV_OWNER))
- kref_put(&resv_map->refs, resv_map_release);
- return ret;
-diff --git a/mm/memory.c b/mm/memory.c
-index 5aee9ec8b8c6..fa752df6dc85 100644
---- a/mm/memory.c
-+++ b/mm/memory.c
-@@ -3711,10 +3711,11 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
- * given task for page fault accounting.
- */
- static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-- unsigned long addr, void *buf, int len, int write)
-+ unsigned long addr, void *buf, int len, unsigned int gup_flags)
- {
- struct vm_area_struct *vma;
- void *old_buf = buf;
-+ int write = gup_flags & FOLL_WRITE;
-
- down_read(&mm->mmap_sem);
- /* ignore errors, just check how much was successfully transferred */
-@@ -3724,7 +3725,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
- struct page *page = NULL;
-
- ret = get_user_pages(tsk, mm, addr, 1,
-- write, 1, &page, &vma);
-+ gup_flags, &page, &vma);
- if (ret <= 0) {
- #ifndef CONFIG_HAVE_IOREMAP_PROT
- break;
-@@ -3776,14 +3777,14 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
- * @addr: start address to access
- * @buf: source or destination buffer
- * @len: number of bytes to transfer
-- * @write: whether the access is a write
-+ * @gup_flags: flags modifying lookup behaviour
- *
- * The caller must hold a reference on @mm.
- */
- int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-- void *buf, int len, int write)
-+ void *buf, int len, unsigned int gup_flags)
- {
-- return __access_remote_vm(NULL, mm, addr, buf, len, write);
-+ return __access_remote_vm(NULL, mm, addr, buf, len, gup_flags);
- }
-
- /*
-@@ -3796,12 +3797,17 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr,
- {
- struct mm_struct *mm;
- int ret;
-+ unsigned int flags = FOLL_FORCE;
-
- mm = get_task_mm(tsk);
- if (!mm)
- return 0;
-
-- ret = __access_remote_vm(tsk, mm, addr, buf, len, write);
-+ if (write)
-+ flags |= FOLL_WRITE;
-+
-+ ret = __access_remote_vm(tsk, mm, addr, buf, len, flags);
-+
- mmput(mm);
-
- return ret;
-diff --git a/mm/mempolicy.c b/mm/mempolicy.c
-index be9840bf11d1..44134ba6fb53 100644
---- a/mm/mempolicy.c
-+++ b/mm/mempolicy.c
-@@ -818,7 +818,7 @@ static int lookup_node(struct mm_struct *mm, unsigned long addr)
- struct page *p;
- int err;
-
-- err = get_user_pages(current, mm, addr & PAGE_MASK, 1, 0, 0, &p, NULL);
-+ err = get_user_pages(current, mm, addr & PAGE_MASK, 1, 0, &p, NULL);
- if (err >= 0) {
- err = page_to_nid(p);
- put_page(p);
-diff --git a/mm/nommu.c b/mm/nommu.c
-index 92be862c859b..2360546db065 100644
---- a/mm/nommu.c
-+++ b/mm/nommu.c
-@@ -184,40 +184,32 @@ finish_or_fault:
- */
- long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-+ unsigned int gup_flags, struct page **pages,
- struct vm_area_struct **vmas)
- {
-- int flags = 0;
--
-- if (write)
-- flags |= FOLL_WRITE;
-- if (force)
-- flags |= FOLL_FORCE;
--
-- return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas,
-- NULL);
-+ return __get_user_pages(tsk, mm, start, nr_pages,
-+ gup_flags, pages, vmas, NULL);
- }
- EXPORT_SYMBOL(get_user_pages);
-
- long get_user_pages_locked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-+ unsigned int gup_flags, struct page **pages,
- int *locked)
- {
-- return get_user_pages(tsk, mm, start, nr_pages, write, force,
-+ return get_user_pages(tsk, mm, start, nr_pages, gup_flags,
- pages, NULL);
- }
- EXPORT_SYMBOL(get_user_pages_locked);
-
- long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages,
-- unsigned int gup_flags)
-+ struct page **pages, unsigned int gup_flags)
- {
- long ret;
- down_read(&mm->mmap_sem);
-- ret = get_user_pages(tsk, mm, start, nr_pages, write, force,
-- pages, NULL);
-+ ret = __get_user_pages(tsk, mm, start, nr_pages, gup_flags, pages,
-+ NULL, NULL);
- up_read(&mm->mmap_sem);
- return ret;
- }
-@@ -225,10 +217,10 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
-
- long get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long start, unsigned long nr_pages,
-- int write, int force, struct page **pages)
-+ struct page **pages, unsigned int gup_flags)
- {
-- return __get_user_pages_unlocked(tsk, mm, start, nr_pages, write,
-- force, pages, 0);
-+ return __get_user_pages_unlocked(tsk, mm, start, nr_pages,
-+ pages, gup_flags);
- }
- EXPORT_SYMBOL(get_user_pages_unlocked);
-
-@@ -1937,9 +1929,10 @@ void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf)
- EXPORT_SYMBOL(filemap_map_pages);
-
- static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-- unsigned long addr, void *buf, int len, int write)
-+ unsigned long addr, void *buf, int len, unsigned int gup_flags)
- {
- struct vm_area_struct *vma;
-+ int write = gup_flags & FOLL_WRITE;
-
- down_read(&mm->mmap_sem);
-
-@@ -1974,14 +1967,14 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
- * @addr: start address to access
- * @buf: source or destination buffer
- * @len: number of bytes to transfer
-- * @write: whether the access is a write
-+ * @gup_flags: flags modifying lookup behaviour
- *
- * The caller must hold a reference on @mm.
- */
- int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-- void *buf, int len, int write)
-+ void *buf, int len, unsigned int gup_flags)
- {
-- return __access_remote_vm(NULL, mm, addr, buf, len, write);
-+ return __access_remote_vm(NULL, mm, addr, buf, len, gup_flags);
- }
-
- /*
-@@ -1999,7 +1992,8 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
- if (!mm)
- return 0;
-
-- len = __access_remote_vm(tsk, mm, addr, buf, len, write);
-+ len = __access_remote_vm(tsk, mm, addr, buf, len,
-+ write ? FOLL_WRITE : 0);
-
- mmput(mm);
- return len;
-diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
-index 5d453e58ddbf..1b5a6104c5fc 100644
---- a/mm/process_vm_access.c
-+++ b/mm/process_vm_access.c
-@@ -88,19 +88,23 @@ static int process_vm_rw_single_vec(unsigned long addr,
- ssize_t rc = 0;
- unsigned long max_pages_per_loop = PVM_MAX_KMALLOC_PAGES
- / sizeof(struct pages *);
-+ unsigned int flags = 0;
-
- /* Work out address and page range required */
- if (len == 0)
- return 0;
- nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1;
-
-+ if (vm_write)
-+ flags |= FOLL_WRITE;
-+
- while (!rc && nr_pages && iov_iter_count(iter)) {
- int pages = min(nr_pages, max_pages_per_loop);
- size_t bytes;
-
- /* Get the pages we're interested in */
- pages = get_user_pages_unlocked(task, mm, pa, pages,
-- vm_write, 0, process_pages);
-+ process_pages, flags);
- if (pages <= 0)
- return -EFAULT;
-
-diff --git a/mm/util.c b/mm/util.c
-index 5fae5b9c2885..db39235970c6 100644
---- a/mm/util.c
-+++ b/mm/util.c
-@@ -278,7 +278,7 @@ int __weak get_user_pages_fast(unsigned long start,
- {
- struct mm_struct *mm = current->mm;
- return get_user_pages_unlocked(current, mm, start, nr_pages,
-- write, 0, pages);
-+ pages, write ? FOLL_WRITE : 0);
- }
- EXPORT_SYMBOL_GPL(get_user_pages_fast);
-
-diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
-index d4f5f220a8e5..28453d698d86 100644
---- a/net/ceph/pagevec.c
-+++ b/net/ceph/pagevec.c
-@@ -26,7 +26,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
- while (got < num_pages) {
- rc = get_user_pages_unlocked(current, current->mm,
- (unsigned long)data + ((unsigned long)got * PAGE_SIZE),
-- num_pages - got, write_page, 0, pages + got);
-+ num_pages - got, pages + got, write_page ? FOLL_WRITE : 0);
- if (rc < 0)
- break;
- BUG_ON(rc == 0);
-diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
-index d2a46ffe6382..d52b633164c9 100644
---- a/net/core/rtnetlink.c
-+++ b/net/core/rtnetlink.c
-@@ -2931,6 +2931,9 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb,
- {
- int err;
-
-+ if (dev->type != ARPHRD_ETHER)
-+ return -EINVAL;
-+
- netif_addr_lock_bh(dev);
- err = nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->uc);
- if (err)
-diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
-index 2d3c9df8d75c..b55b8954dae5 100644
---- a/net/ipv4/tcp_output.c
-+++ b/net/ipv4/tcp_output.c
-@@ -2263,14 +2263,18 @@ void tcp_send_loss_probe(struct sock *sk)
- skb = tcp_write_queue_tail(sk);
- }
-
-+ if (unlikely(!skb)) {
-+ WARN_ONCE(tp->packets_out,
-+ "invalid inflight: %u state %u cwnd %u mss %d\n",
-+ tp->packets_out, sk->sk_state, tp->snd_cwnd, mss);
-+ inet_csk(sk)->icsk_pending = 0;
-+ return;
-+ }
-+
- /* At most one outstanding TLP retransmission. */
- if (tp->tlp_high_seq)
- goto rearm_timer;
-
-- /* Retransmit last segment. */
-- if (WARN_ON(!skb))
-- goto rearm_timer;
--
- if (skb_still_in_host_queue(sk, skb))
- goto rearm_timer;
-
-diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
-index 530b62fd6b64..f8cca81d66f2 100644
---- a/net/ipv6/ip6_output.c
-+++ b/net/ipv6/ip6_output.c
-@@ -169,37 +169,37 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
- const struct ipv6_pinfo *np = inet6_sk(sk);
- struct in6_addr *first_hop = &fl6->daddr;
- struct dst_entry *dst = skb_dst(skb);
-+ unsigned int head_room;
- struct ipv6hdr *hdr;
- u8 proto = fl6->flowi6_proto;
- int seg_len = skb->len;
- int hlimit = -1;
- u32 mtu;
-
-- if (opt) {
-- unsigned int head_room;
-+ head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev);
-+ if (opt)
-+ head_room += opt->opt_nflen + opt->opt_flen;
-
-- /* First: exthdrs may take lots of space (~8K for now)
-- MAX_HEADER is not enough.
-- */
-- head_room = opt->opt_nflen + opt->opt_flen;
-- seg_len += head_room;
-- head_room += sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev);
--
-- if (skb_headroom(skb) < head_room) {
-- struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
-- if (!skb2) {
-- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
-- IPSTATS_MIB_OUTDISCARDS);
-- kfree_skb(skb);
-- return -ENOBUFS;
-- }
-- if (skb->sk)
-- skb_set_owner_w(skb2, skb->sk);
-- consume_skb(skb);
-- skb = skb2;
-+ if (unlikely(skb_headroom(skb) < head_room)) {
-+ struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
-+ if (!skb2) {
-+ IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
-+ IPSTATS_MIB_OUTDISCARDS);
-+ kfree_skb(skb);
-+ return -ENOBUFS;
- }
-+ if (skb->sk)
-+ skb_set_owner_w(skb2, skb->sk);
-+ consume_skb(skb);
-+ skb = skb2;
-+ }
-+
-+ if (opt) {
-+ seg_len += opt->opt_nflen + opt->opt_flen;
-+
- if (opt->opt_flen)
- ipv6_push_frag_opts(skb, opt, &proto);
-+
- if (opt->opt_nflen)
- ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop);
- }
-diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
-index 743ff23885da..7acf1f2b8dfc 100644
---- a/net/sched/sch_netem.c
-+++ b/net/sched/sch_netem.c
-@@ -432,6 +432,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
- int count = 1;
- int rc = NET_XMIT_SUCCESS;
-
-+ /* Do not fool qdisc_drop_all() */
-+ skb->prev = NULL;
-+
- /* Random duplication */
- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
- ++count;
-diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
-index 38651454ed08..6f388e77999c 100644
---- a/security/tomoyo/domain.c
-+++ b/security/tomoyo/domain.c
-@@ -874,7 +874,8 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
- }
- /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
- #ifdef CONFIG_MMU
-- if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
-+ if (get_user_pages(current, bprm->mm, pos, 1,
-+ FOLL_FORCE, &page, NULL) <= 0)
- return false;
- #else
- page = bprm->page[pos / PAGE_SIZE];
-diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
-index 5bc7ddf8fc70..3ce2b8771762 100644
---- a/sound/core/pcm_lib.c
-+++ b/sound/core/pcm_lib.c
-@@ -1849,8 +1849,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
- {
- switch (cmd) {
-- case SNDRV_PCM_IOCTL1_INFO:
-- return 0;
- case SNDRV_PCM_IOCTL1_RESET:
- return snd_pcm_lib_ioctl_reset(substream, arg);
- case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
-diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
-index 0ad194002c0c..9b6dcdea4431 100644
---- a/sound/core/pcm_native.c
-+++ b/sound/core/pcm_native.c
-@@ -214,11 +214,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
- info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
- strlcpy(info->subname, substream->name, sizeof(info->subname));
- runtime = substream->runtime;
-- /* AB: FIXME!!! This is definitely nonsense */
-- if (runtime) {
-- info->sync = runtime->sync;
-- substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
-- }
-+
- return 0;
- }
-
-diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
-index 09db2aec12a3..776e809a8aab 100644
---- a/sound/soc/omap/omap-dmic.c
-+++ b/sound/soc/omap/omap-dmic.c
-@@ -48,6 +48,8 @@ struct omap_dmic {
- struct device *dev;
- void __iomem *io_base;
- struct clk *fclk;
-+ struct pm_qos_request pm_qos_req;
-+ int latency;
- int fclk_freq;
- int out_freq;
- int clk_div;
-@@ -124,6 +126,8 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
-
- mutex_lock(&dmic->mutex);
-
-+ pm_qos_remove_request(&dmic->pm_qos_req);
-+
- if (!dai->active)
- dmic->active = 0;
-
-@@ -226,6 +230,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
- /* packet size is threshold * channels */
- dma_data = snd_soc_dai_get_dma_data(dai, substream);
- dma_data->maxburst = dmic->threshold * channels;
-+ dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC /
-+ params_rate(params);
-
- return 0;
- }
-@@ -236,6 +242,9 @@ static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
- struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
- u32 ctrl;
-
-+ if (pm_qos_request_active(&dmic->pm_qos_req))
-+ pm_qos_update_request(&dmic->pm_qos_req, dmic->latency);
-+
- /* Configure uplink threshold */
- omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
-
-diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
-index 8d0d45d330e7..8eb2d12b6a34 100644
---- a/sound/soc/omap/omap-mcpdm.c
-+++ b/sound/soc/omap/omap-mcpdm.c
-@@ -54,6 +54,8 @@ struct omap_mcpdm {
- unsigned long phys_base;
- void __iomem *io_base;
- int irq;
-+ struct pm_qos_request pm_qos_req;
-+ int latency[2];
-
- struct mutex mutex;
-
-@@ -273,6 +275,9 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
- {
- struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
-+ int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-+ int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
-+ int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-
- mutex_lock(&mcpdm->mutex);
-
-@@ -285,6 +290,14 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
- }
- }
-
-+ if (mcpdm->latency[stream2])
-+ pm_qos_update_request(&mcpdm->pm_qos_req,
-+ mcpdm->latency[stream2]);
-+ else if (mcpdm->latency[stream1])
-+ pm_qos_remove_request(&mcpdm->pm_qos_req);
-+
-+ mcpdm->latency[stream1] = 0;
-+
- mutex_unlock(&mcpdm->mutex);
- }
-
-@@ -296,7 +309,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
- int stream = substream->stream;
- struct snd_dmaengine_dai_dma_data *dma_data;
- u32 threshold;
-- int channels;
-+ int channels, latency;
- int link_mask = 0;
-
- channels = params_channels(params);
-@@ -336,14 +349,25 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
-
- dma_data->maxburst =
- (MCPDM_DN_THRES_MAX - threshold) * channels;
-+ latency = threshold;
- } else {
- /* If playback is not running assume a stereo stream to come */
- if (!mcpdm->config[!stream].link_mask)
- mcpdm->config[!stream].link_mask = (0x3 << 3);
-
- dma_data->maxburst = threshold * channels;
-+ latency = (MCPDM_DN_THRES_MAX - threshold);
- }
-
-+ /*
-+ * The DMA must act to a DMA request within latency time (usec) to avoid
-+ * under/overflow
-+ */
-+ mcpdm->latency[stream] = latency * USEC_PER_SEC / params_rate(params);
-+
-+ if (!mcpdm->latency[stream])
-+ mcpdm->latency[stream] = 10;
-+
- /* Check if we need to restart McPDM with this stream */
- if (mcpdm->config[stream].link_mask &&
- mcpdm->config[stream].link_mask != link_mask)
-@@ -358,6 +382,20 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
- {
- struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
-+ struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req;
-+ int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
-+ int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
-+ int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-+ int latency = mcpdm->latency[stream2];
-+
-+ /* Prevent omap hardware from hitting off between FIFO fills */
-+ if (!latency || mcpdm->latency[stream1] < latency)
-+ latency = mcpdm->latency[stream1];
-+
-+ if (pm_qos_request_active(pm_qos_req))
-+ pm_qos_update_request(pm_qos_req, latency);
-+ else if (latency)
-+ pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency);
-
- if (!omap_mcpdm_active(mcpdm)) {
- omap_mcpdm_start(mcpdm);
-@@ -419,6 +457,9 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
- free_irq(mcpdm->irq, (void *)mcpdm);
- pm_runtime_disable(mcpdm->dev);
-
-+ if (pm_qos_request_active(&mcpdm->pm_qos_req))
-+ pm_qos_remove_request(&mcpdm->pm_qos_req);
-+
- return 0;
- }
-
-diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
-index fa6b74a304a7..b927f9c81d92 100644
---- a/sound/soc/soc-core.c
-+++ b/sound/soc/soc-core.c
-@@ -1711,6 +1711,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
- }
-
- card->instantiated = 1;
-+ dapm_mark_endpoints_dirty(card);
- snd_soc_dapm_sync(&card->dapm);
- mutex_unlock(&card->mutex);
- mutex_unlock(&client_mutex);
-diff --git a/tools/testing/selftests/networking/timestamping/.gitignore b/tools/testing/selftests/networking/timestamping/.gitignore
-new file mode 100644
-index 000000000000..9e69e982fb38
---- /dev/null
-+++ b/tools/testing/selftests/networking/timestamping/.gitignore
-@@ -0,0 +1,3 @@
-+timestamping
-+txtimestamp
-+hwtstamp_config
-diff --git a/tools/testing/selftests/networking/timestamping/Makefile b/tools/testing/selftests/networking/timestamping/Makefile
-new file mode 100644
-index 000000000000..ccbb9edbbbb9
---- /dev/null
-+++ b/tools/testing/selftests/networking/timestamping/Makefile
-@@ -0,0 +1,8 @@
-+TEST_PROGS := hwtstamp_config timestamping txtimestamp
-+
-+all: $(TEST_PROGS)
-+
-+include ../../lib.mk
-+
-+clean:
-+ rm -fr $(TEST_PROGS)
-diff --git a/tools/testing/selftests/networking/timestamping/hwtstamp_config.c b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
-new file mode 100644
-index 000000000000..e8b685a7f15f
---- /dev/null
-+++ b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
-@@ -0,0 +1,134 @@
-+/* Test program for SIOC{G,S}HWTSTAMP
-+ * Copyright 2013 Solarflare Communications
-+ * Author: Ben Hutchings
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+
-+static int
-+lookup_value(const char **names, int size, const char *name)
-+{
-+ int value;
-+
-+ for (value = 0; value < size; value++)
-+ if (names[value] && strcasecmp(names[value], name) == 0)
-+ return value;
-+
-+ return -1;
-+}
-+
-+static const char *
-+lookup_name(const char **names, int size, int value)
-+{
-+ return (value >= 0 && value < size) ? names[value] : NULL;
-+}
-+
-+static void list_names(FILE *f, const char **names, int size)
-+{
-+ int value;
-+
-+ for (value = 0; value < size; value++)
-+ if (names[value])
-+ fprintf(f, " %s\n", names[value]);
-+}
-+
-+static const char *tx_types[] = {
-+#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
-+ TX_TYPE(OFF),
-+ TX_TYPE(ON),
-+ TX_TYPE(ONESTEP_SYNC)
-+#undef TX_TYPE
-+};
-+#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
-+
-+static const char *rx_filters[] = {
-+#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
-+ RX_FILTER(NONE),
-+ RX_FILTER(ALL),
-+ RX_FILTER(SOME),
-+ RX_FILTER(PTP_V1_L4_EVENT),
-+ RX_FILTER(PTP_V1_L4_SYNC),
-+ RX_FILTER(PTP_V1_L4_DELAY_REQ),
-+ RX_FILTER(PTP_V2_L4_EVENT),
-+ RX_FILTER(PTP_V2_L4_SYNC),
-+ RX_FILTER(PTP_V2_L4_DELAY_REQ),
-+ RX_FILTER(PTP_V2_L2_EVENT),
-+ RX_FILTER(PTP_V2_L2_SYNC),
-+ RX_FILTER(PTP_V2_L2_DELAY_REQ),
-+ RX_FILTER(PTP_V2_EVENT),
-+ RX_FILTER(PTP_V2_SYNC),
-+ RX_FILTER(PTP_V2_DELAY_REQ),
-+#undef RX_FILTER
-+};
-+#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
-+
-+static void usage(void)
-+{
-+ fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
-+ "tx_type is any of (case-insensitive):\n",
-+ stderr);
-+ list_names(stderr, tx_types, N_TX_TYPES);
-+ fputs("rx_filter is any of (case-insensitive):\n", stderr);
-+ list_names(stderr, rx_filters, N_RX_FILTERS);
-+}
-+
-+int main(int argc, char **argv)
-+{
-+ struct ifreq ifr;
-+ struct hwtstamp_config config;
-+ const char *name;
-+ int sock;
-+
-+ if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
-+ usage();
-+ return 2;
-+ }
-+
-+ if (argc == 4) {
-+ config.flags = 0;
-+ config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
-+ config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
-+ if (config.tx_type < 0 || config.rx_filter < 0) {
-+ usage();
-+ return 2;
-+ }
-+ }
-+
-+ sock = socket(AF_INET, SOCK_DGRAM, 0);
-+ if (sock < 0) {
-+ perror("socket");
-+ return 1;
-+ }
-+
-+ strcpy(ifr.ifr_name, argv[1]);
-+ ifr.ifr_data = (caddr_t)&config;
-+
-+ if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
-+ perror("ioctl");
-+ return 1;
-+ }
-+
-+ printf("flags = %#x\n", config.flags);
-+ name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
-+ if (name)
-+ printf("tx_type = %s\n", name);
-+ else
-+ printf("tx_type = %d\n", config.tx_type);
-+ name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
-+ if (name)
-+ printf("rx_filter = %s\n", name);
-+ else
-+ printf("rx_filter = %d\n", config.rx_filter);
-+
-+ return 0;
-+}
-diff --git a/tools/testing/selftests/networking/timestamping/timestamping.c b/tools/testing/selftests/networking/timestamping/timestamping.c
-new file mode 100644
-index 000000000000..5cdfd743447b
---- /dev/null
-+++ b/tools/testing/selftests/networking/timestamping/timestamping.c
-@@ -0,0 +1,528 @@
-+/*
-+ * This program demonstrates how the various time stamping features in
-+ * the Linux kernel work. It emulates the behavior of a PTP
-+ * implementation in stand-alone master mode by sending PTPv1 Sync
-+ * multicasts once every second. It looks for similar packets, but
-+ * beyond that doesn't actually implement PTP.
-+ *
-+ * Outgoing packets are time stamped with SO_TIMESTAMPING with or
-+ * without hardware support.
-+ *
-+ * Incoming packets are time stamped with SO_TIMESTAMPING with or
-+ * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
-+ * SO_TIMESTAMP[NS].
-+ *
-+ * Copyright (C) 2009 Intel Corporation.
-+ * Author: Patrick Ohly
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+
-+#ifndef SO_TIMESTAMPING
-+# define SO_TIMESTAMPING 37
-+# define SCM_TIMESTAMPING SO_TIMESTAMPING
-+#endif
-+
-+#ifndef SO_TIMESTAMPNS
-+# define SO_TIMESTAMPNS 35
-+#endif
-+
-+#ifndef SIOCGSTAMPNS
-+# define SIOCGSTAMPNS 0x8907
-+#endif
-+
-+#ifndef SIOCSHWTSTAMP
-+# define SIOCSHWTSTAMP 0x89b0
-+#endif
-+
-+static void usage(const char *error)
-+{
-+ if (error)
-+ printf("invalid option: %s\n", error);
-+ printf("timestamping interface option*\n\n"
-+ "Options:\n"
-+ " IP_MULTICAST_LOOP - looping outgoing multicasts\n"
-+ " SO_TIMESTAMP - normal software time stamping, ms resolution\n"
-+ " SO_TIMESTAMPNS - more accurate software time stamping\n"
-+ " SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
-+ " SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
-+ " SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
-+ " SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
-+ " SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
-+ " SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
-+ " SIOCGSTAMP - check last socket time stamp\n"
-+ " SIOCGSTAMPNS - more accurate socket time stamp\n");
-+ exit(1);
-+}
-+
-+static void bail(const char *error)
-+{
-+ printf("%s: %s\n", error, strerror(errno));
-+ exit(1);
-+}
-+
-+static const unsigned char sync[] = {
-+ 0x00, 0x01, 0x00, 0x01,
-+ 0x5f, 0x44, 0x46, 0x4c,
-+ 0x54, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x01, 0x01,
-+
-+ /* fake uuid */
-+ 0x00, 0x01,
-+ 0x02, 0x03, 0x04, 0x05,
-+
-+ 0x00, 0x01, 0x00, 0x37,
-+ 0x00, 0x00, 0x00, 0x08,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x49, 0x05, 0xcd, 0x01,
-+ 0x29, 0xb1, 0x8d, 0xb0,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x01,
-+
-+ /* fake uuid */
-+ 0x00, 0x01,
-+ 0x02, 0x03, 0x04, 0x05,
-+
-+ 0x00, 0x00, 0x00, 0x37,
-+ 0x00, 0x00, 0x00, 0x04,
-+ 0x44, 0x46, 0x4c, 0x54,
-+ 0x00, 0x00, 0xf0, 0x60,
-+ 0x00, 0x01, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x01,
-+ 0x00, 0x00, 0xf0, 0x60,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x04,
-+ 0x44, 0x46, 0x4c, 0x54,
-+ 0x00, 0x01,
-+
-+ /* fake uuid */
-+ 0x00, 0x01,
-+ 0x02, 0x03, 0x04, 0x05,
-+
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00,
-+ 0x00, 0x00, 0x00, 0x00
-+};
-+
-+static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
-+{
-+ struct timeval now;
-+ int res;
-+
-+ res = sendto(sock, sync, sizeof(sync), 0,
-+ addr, addr_len);
-+ gettimeofday(&now, 0);
-+ if (res < 0)
-+ printf("%s: %s\n", "send", strerror(errno));
-+ else
-+ printf("%ld.%06ld: sent %d bytes\n",
-+ (long)now.tv_sec, (long)now.tv_usec,
-+ res);
-+}
-+
-+static void printpacket(struct msghdr *msg, int res,
-+ char *data,
-+ int sock, int recvmsg_flags,
-+ int siocgstamp, int siocgstampns)
-+{
-+ struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
-+ struct cmsghdr *cmsg;
-+ struct timeval tv;
-+ struct timespec ts;
-+ struct timeval now;
-+
-+ gettimeofday(&now, 0);
-+
-+ printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
-+ (long)now.tv_sec, (long)now.tv_usec,
-+ (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
-+ res,
-+ inet_ntoa(from_addr->sin_addr),
-+ msg->msg_controllen);
-+ for (cmsg = CMSG_FIRSTHDR(msg);
-+ cmsg;
-+ cmsg = CMSG_NXTHDR(msg, cmsg)) {
-+ printf(" cmsg len %zu: ", cmsg->cmsg_len);
-+ switch (cmsg->cmsg_level) {
-+ case SOL_SOCKET:
-+ printf("SOL_SOCKET ");
-+ switch (cmsg->cmsg_type) {
-+ case SO_TIMESTAMP: {
-+ struct timeval *stamp =
-+ (struct timeval *)CMSG_DATA(cmsg);
-+ printf("SO_TIMESTAMP %ld.%06ld",
-+ (long)stamp->tv_sec,
-+ (long)stamp->tv_usec);
-+ break;
-+ }
-+ case SO_TIMESTAMPNS: {
-+ struct timespec *stamp =
-+ (struct timespec *)CMSG_DATA(cmsg);
-+ printf("SO_TIMESTAMPNS %ld.%09ld",
-+ (long)stamp->tv_sec,
-+ (long)stamp->tv_nsec);
-+ break;
-+ }
-+ case SO_TIMESTAMPING: {
-+ struct timespec *stamp =
-+ (struct timespec *)CMSG_DATA(cmsg);
-+ printf("SO_TIMESTAMPING ");
-+ printf("SW %ld.%09ld ",
-+ (long)stamp->tv_sec,
-+ (long)stamp->tv_nsec);
-+ stamp++;
-+ /* skip deprecated HW transformed */
-+ stamp++;
-+ printf("HW raw %ld.%09ld",
-+ (long)stamp->tv_sec,
-+ (long)stamp->tv_nsec);
-+ break;
-+ }
-+ default:
-+ printf("type %d", cmsg->cmsg_type);
-+ break;
-+ }
-+ break;
-+ case IPPROTO_IP:
-+ printf("IPPROTO_IP ");
-+ switch (cmsg->cmsg_type) {
-+ case IP_RECVERR: {
-+ struct sock_extended_err *err =
-+ (struct sock_extended_err *)CMSG_DATA(cmsg);
-+ printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
-+ strerror(err->ee_errno),
-+ err->ee_origin,
-+#ifdef SO_EE_ORIGIN_TIMESTAMPING
-+ err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
-+ "bounced packet" : "unexpected origin"
-+#else
-+ "probably SO_EE_ORIGIN_TIMESTAMPING"
-+#endif
-+ );
-+ if (res < sizeof(sync))
-+ printf(" => truncated data?!");
-+ else if (!memcmp(sync, data + res - sizeof(sync),
-+ sizeof(sync)))
-+ printf(" => GOT OUR DATA BACK (HURRAY!)");
-+ break;
-+ }
-+ case IP_PKTINFO: {
-+ struct in_pktinfo *pktinfo =
-+ (struct in_pktinfo *)CMSG_DATA(cmsg);
-+ printf("IP_PKTINFO interface index %u",
-+ pktinfo->ipi_ifindex);
-+ break;
-+ }
-+ default:
-+ printf("type %d", cmsg->cmsg_type);
-+ break;
-+ }
-+ break;
-+ default:
-+ printf("level %d type %d",
-+ cmsg->cmsg_level,
-+ cmsg->cmsg_type);
-+ break;
-+ }
-+ printf("\n");
-+ }
-+
-+ if (siocgstamp) {
-+ if (ioctl(sock, SIOCGSTAMP, &tv))
-+ printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
-+ else
-+ printf("SIOCGSTAMP %ld.%06ld\n",
-+ (long)tv.tv_sec,
-+ (long)tv.tv_usec);
-+ }
-+ if (siocgstampns) {
-+ if (ioctl(sock, SIOCGSTAMPNS, &ts))
-+ printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
-+ else
-+ printf("SIOCGSTAMPNS %ld.%09ld\n",
-+ (long)ts.tv_sec,
-+ (long)ts.tv_nsec);
-+ }
-+}
-+
-+static void recvpacket(int sock, int recvmsg_flags,
-+ int siocgstamp, int siocgstampns)
-+{
-+ char data[256];
-+ struct msghdr msg;
-+ struct iovec entry;
-+ struct sockaddr_in from_addr;
-+ struct {
-+ struct cmsghdr cm;
-+ char control[512];
-+ } control;
-+ int res;
-+
-+ memset(&msg, 0, sizeof(msg));
-+ msg.msg_iov = &entry;
-+ msg.msg_iovlen = 1;
-+ entry.iov_base = data;
-+ entry.iov_len = sizeof(data);
-+ msg.msg_name = (caddr_t)&from_addr;
-+ msg.msg_namelen = sizeof(from_addr);
-+ msg.msg_control = &control;
-+ msg.msg_controllen = sizeof(control);
-+
-+ res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
-+ if (res < 0) {
-+ printf("%s %s: %s\n",
-+ "recvmsg",
-+ (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
-+ strerror(errno));
-+ } else {
-+ printpacket(&msg, res, data,
-+ sock, recvmsg_flags,
-+ siocgstamp, siocgstampns);
-+ }
-+}
-+
-+int main(int argc, char **argv)
-+{
-+ int so_timestamping_flags = 0;
-+ int so_timestamp = 0;
-+ int so_timestampns = 0;
-+ int siocgstamp = 0;
-+ int siocgstampns = 0;
-+ int ip_multicast_loop = 0;
-+ char *interface;
-+ int i;
-+ int enabled = 1;
-+ int sock;
-+ struct ifreq device;
-+ struct ifreq hwtstamp;
-+ struct hwtstamp_config hwconfig, hwconfig_requested;
-+ struct sockaddr_in addr;
-+ struct ip_mreq imr;
-+ struct in_addr iaddr;
-+ int val;
-+ socklen_t len;
-+ struct timeval next;
-+
-+ if (argc < 2)
-+ usage(0);
-+ interface = argv[1];
-+
-+ for (i = 2; i < argc; i++) {
-+ if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
-+ so_timestamp = 1;
-+ else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
-+ so_timestampns = 1;
-+ else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
-+ siocgstamp = 1;
-+ else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
-+ siocgstampns = 1;
-+ else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
-+ ip_multicast_loop = 1;
-+ else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
-+ so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
-+ else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
-+ so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
-+ else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
-+ so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
-+ else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
-+ so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
-+ else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
-+ so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
-+ else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
-+ so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
-+ else
-+ usage(argv[i]);
-+ }
-+
-+ sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-+ if (sock < 0)
-+ bail("socket");
-+
-+ memset(&device, 0, sizeof(device));
-+ strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
-+ if (ioctl(sock, SIOCGIFADDR, &device) < 0)
-+ bail("getting interface IP address");
-+
-+ memset(&hwtstamp, 0, sizeof(hwtstamp));
-+ strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
-+ hwtstamp.ifr_data = (void *)&hwconfig;
-+ memset(&hwconfig, 0, sizeof(hwconfig));
-+ hwconfig.tx_type =
-+ (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
-+ HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
-+ hwconfig.rx_filter =
-+ (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
-+ HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
-+ hwconfig_requested = hwconfig;
-+ if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
-+ if ((errno == EINVAL || errno == ENOTSUP) &&
-+ hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
-+ hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
-+ printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
-+ else
-+ bail("SIOCSHWTSTAMP");
-+ }
-+ printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
-+ hwconfig_requested.tx_type, hwconfig.tx_type,
-+ hwconfig_requested.rx_filter, hwconfig.rx_filter);
-+
-+ /* bind to PTP port */
-+ addr.sin_family = AF_INET;
-+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ addr.sin_port = htons(319 /* PTP event port */);
-+ if (bind(sock,
-+ (struct sockaddr *)&addr,
-+ sizeof(struct sockaddr_in)) < 0)
-+ bail("bind");
-+
-+ /* set multicast group for outgoing packets */
-+ inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
-+ addr.sin_addr = iaddr;
-+ imr.imr_multiaddr.s_addr = iaddr.s_addr;
-+ imr.imr_interface.s_addr =
-+ ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
-+ if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
-+ &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
-+ bail("set multicast");
-+
-+ /* join multicast group, loop our own packet */
-+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-+ &imr, sizeof(struct ip_mreq)) < 0)
-+ bail("join multicast group");
-+
-+ if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
-+ &ip_multicast_loop, sizeof(enabled)) < 0) {
-+ bail("loop multicast");
-+ }
-+
-+ /* set socket options for time stamping */
-+ if (so_timestamp &&
-+ setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
-+ &enabled, sizeof(enabled)) < 0)
-+ bail("setsockopt SO_TIMESTAMP");
-+
-+ if (so_timestampns &&
-+ setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
-+ &enabled, sizeof(enabled)) < 0)
-+ bail("setsockopt SO_TIMESTAMPNS");
-+
-+ if (so_timestamping_flags &&
-+ setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
-+ &so_timestamping_flags,
-+ sizeof(so_timestamping_flags)) < 0)
-+ bail("setsockopt SO_TIMESTAMPING");
-+
-+ /* request IP_PKTINFO for debugging purposes */
-+ if (setsockopt(sock, SOL_IP, IP_PKTINFO,
-+ &enabled, sizeof(enabled)) < 0)
-+ printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
-+
-+ /* verify socket options */
-+ len = sizeof(val);
-+ if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
-+ printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
-+ else
-+ printf("SO_TIMESTAMP %d\n", val);
-+
-+ if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
-+ printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
-+ strerror(errno));
-+ else
-+ printf("SO_TIMESTAMPNS %d\n", val);
-+
-+ if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
-+ printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
-+ strerror(errno));
-+ } else {
-+ printf("SO_TIMESTAMPING %d\n", val);
-+ if (val != so_timestamping_flags)
-+ printf(" not the expected value %d\n",
-+ so_timestamping_flags);
-+ }
-+
-+ /* send packets forever every five seconds */
-+ gettimeofday(&next, 0);
-+ next.tv_sec = (next.tv_sec + 1) / 5 * 5;
-+ next.tv_usec = 0;
-+ while (1) {
-+ struct timeval now;
-+ struct timeval delta;
-+ long delta_us;
-+ int res;
-+ fd_set readfs, errorfs;
-+
-+ gettimeofday(&now, 0);
-+ delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
-+ (long)(next.tv_usec - now.tv_usec);
-+ if (delta_us > 0) {
-+ /* continue waiting for timeout or data */
-+ delta.tv_sec = delta_us / 1000000;
-+ delta.tv_usec = delta_us % 1000000;
-+
-+ FD_ZERO(&readfs);
-+ FD_ZERO(&errorfs);
-+ FD_SET(sock, &readfs);
-+ FD_SET(sock, &errorfs);
-+ printf("%ld.%06ld: select %ldus\n",
-+ (long)now.tv_sec, (long)now.tv_usec,
-+ delta_us);
-+ res = select(sock + 1, &readfs, 0, &errorfs, &delta);
-+ gettimeofday(&now, 0);
-+ printf("%ld.%06ld: select returned: %d, %s\n",
-+ (long)now.tv_sec, (long)now.tv_usec,
-+ res,
-+ res < 0 ? strerror(errno) : "success");
-+ if (res > 0) {
-+ if (FD_ISSET(sock, &readfs))
-+ printf("ready for reading\n");
-+ if (FD_ISSET(sock, &errorfs))
-+ printf("has error\n");
-+ recvpacket(sock, 0,
-+ siocgstamp,
-+ siocgstampns);
-+ recvpacket(sock, MSG_ERRQUEUE,
-+ siocgstamp,
-+ siocgstampns);
-+ }
-+ } else {
-+ /* write one packet */
-+ sendpacket(sock,
-+ (struct sockaddr *)&addr,
-+ sizeof(addr));
-+ next.tv_sec += 5;
-+ continue;
-+ }
-+ }
-+
-+ return 0;
-+}
-diff --git a/tools/testing/selftests/networking/timestamping/txtimestamp.c b/tools/testing/selftests/networking/timestamping/txtimestamp.c
-new file mode 100644
-index 000000000000..5df07047ca86
---- /dev/null
-+++ b/tools/testing/selftests/networking/timestamping/txtimestamp.c
-@@ -0,0 +1,549 @@
-+/*
-+ * Copyright 2014 Google Inc.
-+ * Author: willemb@google.com (Willem de Bruijn)
-+ *
-+ * Test software tx timestamping, including
-+ *
-+ * - SCHED, SND and ACK timestamps
-+ * - RAW, UDP and TCP
-+ * - IPv4 and IPv6
-+ * - various packet sizes (to test GSO and TSO)
-+ *
-+ * Consult the command line arguments for help on running
-+ * the various testcases.
-+ *
-+ * This test requires a dummy TCP server.
-+ * A simple `nc6 [-u] -l -p $DESTPORT` will do
-+ *
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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, Inc.,
-+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-+ */
-+
-+#define _GNU_SOURCE
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+/* command line parameters */
-+static int cfg_proto = SOCK_STREAM;
-+static int cfg_ipproto = IPPROTO_TCP;
-+static int cfg_num_pkts = 4;
-+static int do_ipv4 = 1;
-+static int do_ipv6 = 1;
-+static int cfg_payload_len = 10;
-+static bool cfg_show_payload;
-+static bool cfg_do_pktinfo;
-+static bool cfg_loop_nodata;
-+static uint16_t dest_port = 9000;
-+
-+static struct sockaddr_in daddr;
-+static struct sockaddr_in6 daddr6;
-+static struct timespec ts_prev;
-+
-+static void __print_timestamp(const char *name, struct timespec *cur,
-+ uint32_t key, int payload_len)
-+{
-+ if (!(cur->tv_sec | cur->tv_nsec))
-+ return;
-+
-+ fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)",
-+ name, cur->tv_sec, cur->tv_nsec / 1000,
-+ key, payload_len);
-+
-+ if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
-+ int64_t cur_ms, prev_ms;
-+
-+ cur_ms = (long) cur->tv_sec * 1000 * 1000;
-+ cur_ms += cur->tv_nsec / 1000;
-+
-+ prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
-+ prev_ms += ts_prev.tv_nsec / 1000;
-+
-+ fprintf(stderr, " (%+" PRId64 " us)", cur_ms - prev_ms);
-+ }
-+
-+ ts_prev = *cur;
-+ fprintf(stderr, "\n");
-+}
-+
-+static void print_timestamp_usr(void)
-+{
-+ struct timespec ts;
-+ struct timeval tv; /* avoid dependency on -lrt */
-+
-+ gettimeofday(&tv, NULL);
-+ ts.tv_sec = tv.tv_sec;
-+ ts.tv_nsec = tv.tv_usec * 1000;
-+
-+ __print_timestamp(" USR", &ts, 0, 0);
-+}
-+
-+static void print_timestamp(struct scm_timestamping *tss, int tstype,
-+ int tskey, int payload_len)
-+{
-+ const char *tsname;
-+
-+ switch (tstype) {
-+ case SCM_TSTAMP_SCHED:
-+ tsname = " ENQ";
-+ break;
-+ case SCM_TSTAMP_SND:
-+ tsname = " SND";
-+ break;
-+ case SCM_TSTAMP_ACK:
-+ tsname = " ACK";
-+ break;
-+ default:
-+ error(1, 0, "unknown timestamp type: %u",
-+ tstype);
-+ }
-+ __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
-+}
-+
-+/* TODO: convert to check_and_print payload once API is stable */
-+static void print_payload(char *data, int len)
-+{
-+ int i;
-+
-+ if (!len)
-+ return;
-+
-+ if (len > 70)
-+ len = 70;
-+
-+ fprintf(stderr, "payload: ");
-+ for (i = 0; i < len; i++)
-+ fprintf(stderr, "%02hhx ", data[i]);
-+ fprintf(stderr, "\n");
-+}
-+
-+static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
-+{
-+ char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
-+
-+ fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n",
-+ ifindex,
-+ saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
-+ daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
-+}
-+
-+static void __poll(int fd)
-+{
-+ struct pollfd pollfd;
-+ int ret;
-+
-+ memset(&pollfd, 0, sizeof(pollfd));
-+ pollfd.fd = fd;
-+ ret = poll(&pollfd, 1, 100);
-+ if (ret != 1)
-+ error(1, errno, "poll");
-+}
-+
-+static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
-+{
-+ struct sock_extended_err *serr = NULL;
-+ struct scm_timestamping *tss = NULL;
-+ struct cmsghdr *cm;
-+ int batch = 0;
-+
-+ for (cm = CMSG_FIRSTHDR(msg);
-+ cm && cm->cmsg_len;
-+ cm = CMSG_NXTHDR(msg, cm)) {
-+ if (cm->cmsg_level == SOL_SOCKET &&
-+ cm->cmsg_type == SCM_TIMESTAMPING) {
-+ tss = (void *) CMSG_DATA(cm);
-+ } else if ((cm->cmsg_level == SOL_IP &&
-+ cm->cmsg_type == IP_RECVERR) ||
-+ (cm->cmsg_level == SOL_IPV6 &&
-+ cm->cmsg_type == IPV6_RECVERR)) {
-+ serr = (void *) CMSG_DATA(cm);
-+ if (serr->ee_errno != ENOMSG ||
-+ serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
-+ fprintf(stderr, "unknown ip error %d %d\n",
-+ serr->ee_errno,
-+ serr->ee_origin);
-+ serr = NULL;
-+ }
-+ } else if (cm->cmsg_level == SOL_IP &&
-+ cm->cmsg_type == IP_PKTINFO) {
-+ struct in_pktinfo *info = (void *) CMSG_DATA(cm);
-+ print_pktinfo(AF_INET, info->ipi_ifindex,
-+ &info->ipi_spec_dst, &info->ipi_addr);
-+ } else if (cm->cmsg_level == SOL_IPV6 &&
-+ cm->cmsg_type == IPV6_PKTINFO) {
-+ struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
-+ print_pktinfo(AF_INET6, info6->ipi6_ifindex,
-+ NULL, &info6->ipi6_addr);
-+ } else
-+ fprintf(stderr, "unknown cmsg %d,%d\n",
-+ cm->cmsg_level, cm->cmsg_type);
-+
-+ if (serr && tss) {
-+ print_timestamp(tss, serr->ee_info, serr->ee_data,
-+ payload_len);
-+ serr = NULL;
-+ tss = NULL;
-+ batch++;
-+ }
-+ }
-+
-+ if (batch > 1)
-+ fprintf(stderr, "batched %d timestamps\n", batch);
-+}
-+
-+static int recv_errmsg(int fd)
-+{
-+ static char ctrl[1024 /* overprovision*/];
-+ static struct msghdr msg;
-+ struct iovec entry;
-+ static char *data;
-+ int ret = 0;
-+
-+ data = malloc(cfg_payload_len);
-+ if (!data)
-+ error(1, 0, "malloc");
-+
-+ memset(&msg, 0, sizeof(msg));
-+ memset(&entry, 0, sizeof(entry));
-+ memset(ctrl, 0, sizeof(ctrl));
-+
-+ entry.iov_base = data;
-+ entry.iov_len = cfg_payload_len;
-+ msg.msg_iov = &entry;
-+ msg.msg_iovlen = 1;
-+ msg.msg_name = NULL;
-+ msg.msg_namelen = 0;
-+ msg.msg_control = ctrl;
-+ msg.msg_controllen = sizeof(ctrl);
-+
-+ ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
-+ if (ret == -1 && errno != EAGAIN)
-+ error(1, errno, "recvmsg");
-+
-+ if (ret >= 0) {
-+ __recv_errmsg_cmsg(&msg, ret);
-+ if (cfg_show_payload)
-+ print_payload(data, cfg_payload_len);
-+ }
-+
-+ free(data);
-+ return ret == -1;
-+}
-+
-+static void do_test(int family, unsigned int opt)
-+{
-+ char *buf;
-+ int fd, i, val = 1, total_len;
-+
-+ if (family == AF_INET6 && cfg_proto != SOCK_STREAM) {
-+ /* due to lack of checksum generation code */
-+ fprintf(stderr, "test: skipping datagram over IPv6\n");
-+ return;
-+ }
-+
-+ total_len = cfg_payload_len;
-+ if (cfg_proto == SOCK_RAW) {
-+ total_len += sizeof(struct udphdr);
-+ if (cfg_ipproto == IPPROTO_RAW)
-+ total_len += sizeof(struct iphdr);
-+ }
-+
-+ buf = malloc(total_len);
-+ if (!buf)
-+ error(1, 0, "malloc");
-+
-+ fd = socket(family, cfg_proto, cfg_ipproto);
-+ if (fd < 0)
-+ error(1, errno, "socket");
-+
-+ if (cfg_proto == SOCK_STREAM) {
-+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
-+ (char*) &val, sizeof(val)))
-+ error(1, 0, "setsockopt no nagle");
-+
-+ if (family == PF_INET) {
-+ if (connect(fd, (void *) &daddr, sizeof(daddr)))
-+ error(1, errno, "connect ipv4");
-+ } else {
-+ if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
-+ error(1, errno, "connect ipv6");
-+ }
-+ }
-+
-+ if (cfg_do_pktinfo) {
-+ if (family == AF_INET6) {
-+ if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
-+ &val, sizeof(val)))
-+ error(1, errno, "setsockopt pktinfo ipv6");
-+ } else {
-+ if (setsockopt(fd, SOL_IP, IP_PKTINFO,
-+ &val, sizeof(val)))
-+ error(1, errno, "setsockopt pktinfo ipv4");
-+ }
-+ }
-+
-+ opt |= SOF_TIMESTAMPING_SOFTWARE |
-+ SOF_TIMESTAMPING_OPT_CMSG |
-+ SOF_TIMESTAMPING_OPT_ID;
-+ if (cfg_loop_nodata)
-+ opt |= SOF_TIMESTAMPING_OPT_TSONLY;
-+
-+ if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
-+ (char *) &opt, sizeof(opt)))
-+ error(1, 0, "setsockopt timestamping");
-+
-+ for (i = 0; i < cfg_num_pkts; i++) {
-+ memset(&ts_prev, 0, sizeof(ts_prev));
-+ memset(buf, 'a' + i, total_len);
-+
-+ if (cfg_proto == SOCK_RAW) {
-+ struct udphdr *udph;
-+ int off = 0;
-+
-+ if (cfg_ipproto == IPPROTO_RAW) {
-+ struct iphdr *iph = (void *) buf;
-+
-+ memset(iph, 0, sizeof(*iph));
-+ iph->ihl = 5;
-+ iph->version = 4;
-+ iph->ttl = 2;
-+ iph->daddr = daddr.sin_addr.s_addr;
-+ iph->protocol = IPPROTO_UDP;
-+ /* kernel writes saddr, csum, len */
-+
-+ off = sizeof(*iph);
-+ }
-+
-+ udph = (void *) buf + off;
-+ udph->source = ntohs(9000); /* random spoof */
-+ udph->dest = ntohs(dest_port);
-+ udph->len = ntohs(sizeof(*udph) + cfg_payload_len);
-+ udph->check = 0; /* not allowed for IPv6 */
-+ }
-+
-+ print_timestamp_usr();
-+ if (cfg_proto != SOCK_STREAM) {
-+ if (family == PF_INET)
-+ val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
-+ else
-+ val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
-+ } else {
-+ val = send(fd, buf, cfg_payload_len, 0);
-+ }
-+ if (val != total_len)
-+ error(1, errno, "send");
-+
-+ /* wait for all errors to be queued, else ACKs arrive OOO */
-+ usleep(50 * 1000);
-+
-+ __poll(fd);
-+
-+ while (!recv_errmsg(fd)) {}
-+ }
-+
-+ if (close(fd))
-+ error(1, errno, "close");
-+
-+ free(buf);
-+ usleep(400 * 1000);
-+}
-+
-+static void __attribute__((noreturn)) usage(const char *filepath)
-+{
-+ fprintf(stderr, "\nUsage: %s [options] hostname\n"
-+ "\nwhere options are:\n"
-+ " -4: only IPv4\n"
-+ " -6: only IPv6\n"
-+ " -h: show this message\n"
-+ " -I: request PKTINFO\n"
-+ " -l N: send N bytes at a time\n"
-+ " -n: set no-payload option\n"
-+ " -r: use raw\n"
-+ " -R: use raw (IP_HDRINCL)\n"
-+ " -p N: connect to port N\n"
-+ " -u: use udp\n"
-+ " -x: show payload (up to 70 bytes)\n",
-+ filepath);
-+ exit(1);
-+}
-+
-+static void parse_opt(int argc, char **argv)
-+{
-+ int proto_count = 0;
-+ char c;
-+
-+ while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) {
-+ switch (c) {
-+ case '4':
-+ do_ipv6 = 0;
-+ break;
-+ case '6':
-+ do_ipv4 = 0;
-+ break;
-+ case 'I':
-+ cfg_do_pktinfo = true;
-+ break;
-+ case 'n':
-+ cfg_loop_nodata = true;
-+ break;
-+ case 'r':
-+ proto_count++;
-+ cfg_proto = SOCK_RAW;
-+ cfg_ipproto = IPPROTO_UDP;
-+ break;
-+ case 'R':
-+ proto_count++;
-+ cfg_proto = SOCK_RAW;
-+ cfg_ipproto = IPPROTO_RAW;
-+ break;
-+ case 'u':
-+ proto_count++;
-+ cfg_proto = SOCK_DGRAM;
-+ cfg_ipproto = IPPROTO_UDP;
-+ break;
-+ case 'l':
-+ cfg_payload_len = strtoul(optarg, NULL, 10);
-+ break;
-+ case 'p':
-+ dest_port = strtoul(optarg, NULL, 10);
-+ break;
-+ case 'x':
-+ cfg_show_payload = true;
-+ break;
-+ case 'h':
-+ default:
-+ usage(argv[0]);
-+ }
-+ }
-+
-+ if (!cfg_payload_len)
-+ error(1, 0, "payload may not be nonzero");
-+ if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
-+ error(1, 0, "udp packet might exceed expected MTU");
-+ if (!do_ipv4 && !do_ipv6)
-+ error(1, 0, "pass -4 or -6, not both");
-+ if (proto_count > 1)
-+ error(1, 0, "pass -r, -R or -u, not multiple");
-+
-+ if (optind != argc - 1)
-+ error(1, 0, "missing required hostname argument");
-+}
-+
-+static void resolve_hostname(const char *hostname)
-+{
-+ struct addrinfo *addrs, *cur;
-+ int have_ipv4 = 0, have_ipv6 = 0;
-+
-+ if (getaddrinfo(hostname, NULL, NULL, &addrs))
-+ error(1, errno, "getaddrinfo");
-+
-+ cur = addrs;
-+ while (cur && !have_ipv4 && !have_ipv6) {
-+ if (!have_ipv4 && cur->ai_family == AF_INET) {
-+ memcpy(&daddr, cur->ai_addr, sizeof(daddr));
-+ daddr.sin_port = htons(dest_port);
-+ have_ipv4 = 1;
-+ }
-+ else if (!have_ipv6 && cur->ai_family == AF_INET6) {
-+ memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
-+ daddr6.sin6_port = htons(dest_port);
-+ have_ipv6 = 1;
-+ }
-+ cur = cur->ai_next;
-+ }
-+ if (addrs)
-+ freeaddrinfo(addrs);
-+
-+ do_ipv4 &= have_ipv4;
-+ do_ipv6 &= have_ipv6;
-+}
-+
-+static void do_main(int family)
-+{
-+ fprintf(stderr, "family: %s\n",
-+ family == PF_INET ? "INET" : "INET6");
-+
-+ fprintf(stderr, "test SND\n");
-+ do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
-+
-+ fprintf(stderr, "test ENQ\n");
-+ do_test(family, SOF_TIMESTAMPING_TX_SCHED);
-+
-+ fprintf(stderr, "test ENQ + SND\n");
-+ do_test(family, SOF_TIMESTAMPING_TX_SCHED |
-+ SOF_TIMESTAMPING_TX_SOFTWARE);
-+
-+ if (cfg_proto == SOCK_STREAM) {
-+ fprintf(stderr, "\ntest ACK\n");
-+ do_test(family, SOF_TIMESTAMPING_TX_ACK);
-+
-+ fprintf(stderr, "\ntest SND + ACK\n");
-+ do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
-+ SOF_TIMESTAMPING_TX_ACK);
-+
-+ fprintf(stderr, "\ntest ENQ + SND + ACK\n");
-+ do_test(family, SOF_TIMESTAMPING_TX_SCHED |
-+ SOF_TIMESTAMPING_TX_SOFTWARE |
-+ SOF_TIMESTAMPING_TX_ACK);
-+ }
-+}
-+
-+const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
-+
-+int main(int argc, char **argv)
-+{
-+ if (argc == 1)
-+ usage(argv[0]);
-+
-+ parse_opt(argc, argv);
-+ resolve_hostname(argv[argc - 1]);
-+
-+ fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]);
-+ fprintf(stderr, "payload: %u\n", cfg_payload_len);
-+ fprintf(stderr, "server port: %u\n", dest_port);
-+ fprintf(stderr, "\n");
-+
-+ if (do_ipv4)
-+ do_main(PF_INET);
-+ if (do_ipv6)
-+ do_main(PF_INET6);
-+
-+ return 0;
-+}
-diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
-index 4f70d12e392d..eddce59986ee 100644
---- a/virt/kvm/async_pf.c
-+++ b/virt/kvm/async_pf.c
-@@ -80,7 +80,7 @@ static void async_pf_execute(struct work_struct *work)
-
- might_sleep();
-
-- get_user_pages_unlocked(NULL, mm, addr, 1, 1, 0, NULL);
-+ get_user_pages_unlocked(NULL, mm, addr, 1, NULL, FOLL_WRITE);
- kvm_async_page_present_sync(vcpu, apf);
-
- spin_lock(&vcpu->async_pf.lock);
-diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
-index b814ae6822b6..e4be695eb789 100644
---- a/virt/kvm/kvm_main.c
-+++ b/virt/kvm/kvm_main.c
-@@ -1352,10 +1352,15 @@ static int hva_to_pfn_slow(unsigned long addr, bool *async, bool write_fault,
- npages = get_user_page_nowait(current, current->mm,
- addr, write_fault, page);
- up_read(¤t->mm->mmap_sem);
-- } else
-+ } else {
-+ unsigned int flags = FOLL_TOUCH | FOLL_HWPOISON;
-+
-+ if (write_fault)
-+ flags |= FOLL_WRITE;
-+
- npages = __get_user_pages_unlocked(current, current->mm, addr, 1,
-- write_fault, 0, page,
-- FOLL_TOUCH|FOLL_HWPOISON);
-+ page, flags);
-+ }
- if (npages != 1)
- return npages;
-
-diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
-index a83798cc448b..611bf28851c6 100644
---- a/fs/proc/task_mmu.c
-+++ b/fs/proc/task_mmu.c
-@@ -141,7 +141,7 @@ static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma)
- struct page *page;
-
- pages_pinned = get_user_pages(current, mm, page_start_vaddr,
-- 1, 0, 0, &page, NULL);
-+ 1, 0, &page, NULL);
- if (pages_pinned < 1) {
- seq_puts(m, "]");
- return;
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.167-168_mali.patch b/patch/kernel/rk3399-default/04-patch-4.4.167-168_mali.patch
deleted file mode 100644
index bf70fe892..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.167-168_mali.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-diff --git a/drivers/gpu/arm/midgard/mali_kbase_mem.c b/drivers/gpu/arm/midgard/mali_kbase_mem.c
-index 4a223e8ee..56e0ae4cf 100644
---- a/drivers/gpu/arm/midgard/mali_kbase_mem.c
-+++ b/drivers/gpu/arm/midgard/mali_kbase_mem.c
-@@ -2182,14 +2182,14 @@ static int kbase_jd_user_buf_map(struct kbase_context *kctx,
- pinned_pages = get_user_pages(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
-- reg->flags & KBASE_REG_GPU_WR,
-- 0, pages, NULL);
-+ reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-+ pages, NULL);
- #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
-- reg->flags & KBASE_REG_GPU_WR,
-- 0, pages, NULL);
-+ reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-+ pages, NULL);
- #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
-diff --git a/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c b/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
-index eea429a8d..f48286121 100644
---- a/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
-+++ b/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
-@@ -1161,10 +1161,12 @@ static struct kbase_va_region *kbase_mem_from_user_buffer(
-
- #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
- faulted_pages = get_user_pages(current, current->mm, address, *va_pages,
-- reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL);
-+ reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-+ pages, NULL);
- #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
- faulted_pages = get_user_pages(address, *va_pages,
-- reg->flags & KBASE_REG_GPU_WR, 0, pages, NULL);
-+ reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-+ pages, NULL);
- #else
- faulted_pages = get_user_pages(address, *va_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
-diff --git a/drivers/video/rockchip/rga2/rga2_mmu_info.c b/drivers/video/rockchip/rga2/rga2_mmu_info.c
-index 61673e196..ede87e47f 100644
---- a/drivers/video/rockchip/rga2/rga2_mmu_info.c
-+++ b/drivers/video/rockchip/rga2/rga2_mmu_info.c
-@@ -386,7 +386,7 @@ static int rga2_MapUserMemory(struct page **pages, uint32_t *pageTable,
- down_read(¤t->mm->mmap_sem);
- #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
- result = get_user_pages(current, current->mm, Memory << PAGE_SHIFT,
-- pageCount, writeFlag, 0, pages, NULL);
-+ pageCount, writeFlag, pages, NULL);
- #else
- result = get_user_pages_remote(current, current->mm,
- Memory << PAGE_SHIFT,
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.168-169.patch b/patch/kernel/rk3399-default/04-patch-4.4.168-169.patch
deleted file mode 100644
index b0ece2fd1..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.168-169.patch
+++ /dev/null
@@ -1,1260 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 082f82471b51..0d41b0626c0c 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 168
-+SUBLEVEL = 169
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
-index cb69299a492e..f120d823e8c2 100644
---- a/arch/arc/include/asm/io.h
-+++ b/arch/arc/include/asm/io.h
-@@ -12,6 +12,7 @@
- #include
- #include
- #include
-+#include
-
- #ifdef CONFIG_ISA_ARCV2
- #include
-@@ -85,6 +86,42 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
- return w;
- }
-
-+/*
-+ * {read,write}s{b,w,l}() repeatedly access the same IO address in
-+ * native endianness in 8-, 16-, 32-bit chunks {into,from} memory,
-+ * @count times
-+ */
-+#define __raw_readsx(t,f) \
-+static inline void __raw_reads##f(const volatile void __iomem *addr, \
-+ void *ptr, unsigned int count) \
-+{ \
-+ bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0; \
-+ u##t *buf = ptr; \
-+ \
-+ if (!count) \
-+ return; \
-+ \
-+ /* Some ARC CPU's don't support unaligned accesses */ \
-+ if (is_aligned) { \
-+ do { \
-+ u##t x = __raw_read##f(addr); \
-+ *buf++ = x; \
-+ } while (--count); \
-+ } else { \
-+ do { \
-+ u##t x = __raw_read##f(addr); \
-+ put_unaligned(x, buf++); \
-+ } while (--count); \
-+ } \
-+}
-+
-+#define __raw_readsb __raw_readsb
-+__raw_readsx(8, b)
-+#define __raw_readsw __raw_readsw
-+__raw_readsx(16, w)
-+#define __raw_readsl __raw_readsl
-+__raw_readsx(32, l)
-+
- #define __raw_writeb __raw_writeb
- static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
- {
-@@ -117,6 +154,35 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
-
- }
-
-+#define __raw_writesx(t,f) \
-+static inline void __raw_writes##f(volatile void __iomem *addr, \
-+ const void *ptr, unsigned int count) \
-+{ \
-+ bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0; \
-+ const u##t *buf = ptr; \
-+ \
-+ if (!count) \
-+ return; \
-+ \
-+ /* Some ARC CPU's don't support unaligned accesses */ \
-+ if (is_aligned) { \
-+ do { \
-+ __raw_write##f(*buf++, addr); \
-+ } while (--count); \
-+ } else { \
-+ do { \
-+ __raw_write##f(get_unaligned(buf++), addr); \
-+ } while (--count); \
-+ } \
-+}
-+
-+#define __raw_writesb __raw_writesb
-+__raw_writesx(8, b)
-+#define __raw_writesw __raw_writesw
-+__raw_writesx(16, w)
-+#define __raw_writesl __raw_writesl
-+__raw_writesx(32, l)
-+
- /*
- * MMIO can also get buffered/optimized in micro-arch, so barriers needed
- * Based on ARM model for the typical use case
-@@ -132,10 +198,16 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
- #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
- #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
- #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
-+#define readsb(p,d,l) ({ __raw_readsb(p,d,l); __iormb(); })
-+#define readsw(p,d,l) ({ __raw_readsw(p,d,l); __iormb(); })
-+#define readsl(p,d,l) ({ __raw_readsl(p,d,l); __iormb(); })
-
- #define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); })
- #define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); })
- #define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); })
-+#define writesb(p,d,l) ({ __iowmb(); __raw_writesb(p,d,l); })
-+#define writesw(p,d,l) ({ __iowmb(); __raw_writesw(p,d,l); })
-+#define writesl(p,d,l) ({ __iowmb(); __raw_writesl(p,d,l); })
-
- /*
- * Relaxed API for drivers which can handle barrier ordering themselves
-diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
-index a134d8a13d00..11d699af30ed 100644
---- a/arch/arm/mm/cache-v7.S
-+++ b/arch/arm/mm/cache-v7.S
-@@ -359,14 +359,16 @@ v7_dma_inv_range:
- ALT_UP(W(nop))
- #endif
- mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
-+ addne r0, r0, r2
-
- tst r1, r3
- bic r1, r1, r3
- mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line
--1:
-- mcr p15, 0, r0, c7, c6, 1 @ invalidate D / U line
-- add r0, r0, r2
- cmp r0, r1
-+1:
-+ mcrlo p15, 0, r0, c7, c6, 1 @ invalidate D / U line
-+ addlo r0, r0, r2
-+ cmplo r0, r1
- blo 1b
- dsb st
- ret lr
-diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
-index 99e4487248ff..57003d1bd243 100644
---- a/arch/powerpc/boot/Makefile
-+++ b/arch/powerpc/boot/Makefile
-@@ -70,7 +70,8 @@ $(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o): \
- libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
- libfdtheader := fdt.h libfdt.h libfdt_internal.h
-
--$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
-+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o \
-+ treeboot-akebono.o treeboot-currituck.o treeboot-iss4xx.o): \
- $(addprefix $(obj)/,$(libfdtheader))
-
- src-wlib-y := string.S crt0.S crtsavres.S stdio.c main.c \
-diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
-index dab616a33b8d..f2197654be07 100644
---- a/arch/powerpc/kernel/msi.c
-+++ b/arch/powerpc/kernel/msi.c
-@@ -34,5 +34,10 @@ void arch_teardown_msi_irqs(struct pci_dev *dev)
- {
- struct pci_controller *phb = pci_bus_to_host(dev->bus);
-
-- phb->controller_ops.teardown_msi_irqs(dev);
-+ /*
-+ * We can be called even when arch_setup_msi_irqs() returns -ENOSYS,
-+ * so check the pointer again.
-+ */
-+ if (phb->controller_ops.teardown_msi_irqs)
-+ phb->controller_ops.teardown_msi_irqs(dev);
- }
-diff --git a/arch/x86/platform/efi/early_printk.c b/arch/x86/platform/efi/early_printk.c
-index 524142117296..82324fc25d5e 100644
---- a/arch/x86/platform/efi/early_printk.c
-+++ b/arch/x86/platform/efi/early_printk.c
-@@ -179,7 +179,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
- num--;
- }
-
-- if (efi_x >= si->lfb_width) {
-+ if (efi_x + font->width > si->lfb_width) {
- efi_x = 0;
- efi_y += font->height;
- }
-diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index ba514fa733de..d543172b20b3 100644
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -4297,6 +4297,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
- { "SSD*INTEL*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
- { "Samsung*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
- { "SAMSUNG*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
-+ { "SAMSUNG*MZ7KM*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
- { "ST[1248][0248]0[FH]*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
-
- /*
-diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c
-index 61893fe73251..18b6c9b55b95 100644
---- a/drivers/clk/mmp/clk.c
-+++ b/drivers/clk/mmp/clk.c
-@@ -182,7 +182,7 @@ void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
- pr_err("CLK %d has invalid pointer %p\n", id, clk);
- return;
- }
-- if (id > unit->nr_clks) {
-+ if (id >= unit->nr_clks) {
- pr_err("CLK %d is invalid\n", id);
- return;
- }
-diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
-index 7eb253bc24df..221eaea651d4 100644
---- a/drivers/gpu/drm/msm/msm_atomic.c
-+++ b/drivers/gpu/drm/msm/msm_atomic.c
-@@ -107,7 +107,12 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
- if (old_state->legacy_cursor_update)
- continue;
-
-+ if (drm_crtc_vblank_get(crtc))
-+ continue;
-+
- kms->funcs->wait_for_crtc_commit_done(kms, crtc);
-+
-+ drm_crtc_vblank_put(crtc);
- }
- }
-
-diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
-index c335cc7852f9..9c9fd2e87a4b 100644
---- a/drivers/i2c/busses/i2c-axxia.c
-+++ b/drivers/i2c/busses/i2c-axxia.c
-@@ -74,8 +74,7 @@
- MST_STATUS_ND)
- #define MST_STATUS_ERR (MST_STATUS_NAK | \
- MST_STATUS_AL | \
-- MST_STATUS_IP | \
-- MST_STATUS_TSS)
-+ MST_STATUS_IP)
- #define MST_TX_BYTES_XFRD 0x50
- #define MST_RX_BYTES_XFRD 0x54
- #define SCL_HIGH_PERIOD 0x80
-@@ -241,7 +240,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
- */
- if (c <= 0 || c > I2C_SMBUS_BLOCK_MAX) {
- idev->msg_err = -EPROTO;
-- i2c_int_disable(idev, ~0);
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
- complete(&idev->msg_complete);
- break;
- }
-@@ -299,14 +298,19 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
-
- if (status & MST_STATUS_SCC) {
- /* Stop completed */
-- i2c_int_disable(idev, ~0);
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
- complete(&idev->msg_complete);
- } else if (status & MST_STATUS_SNS) {
- /* Transfer done */
-- i2c_int_disable(idev, ~0);
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
- if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
- axxia_i2c_empty_rx_fifo(idev);
- complete(&idev->msg_complete);
-+ } else if (status & MST_STATUS_TSS) {
-+ /* Transfer timeout */
-+ idev->msg_err = -ETIMEDOUT;
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
-+ complete(&idev->msg_complete);
- } else if (unlikely(status & MST_STATUS_ERR)) {
- /* Transfer error */
- i2c_int_disable(idev, ~0);
-@@ -339,10 +343,10 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
- u32 rx_xfer, tx_xfer;
- u32 addr_1, addr_2;
- unsigned long time_left;
-+ unsigned int wt_value;
-
- idev->msg = msg;
- idev->msg_xfrd = 0;
-- idev->msg_err = 0;
- reinit_completion(&idev->msg_complete);
-
- if (i2c_m_ten(msg)) {
-@@ -382,9 +386,18 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
- else if (axxia_i2c_fill_tx_fifo(idev) != 0)
- int_mask |= MST_STATUS_TFL;
-
-+ wt_value = WT_VALUE(readl(idev->base + WAIT_TIMER_CONTROL));
-+ /* Disable wait timer temporarly */
-+ writel(wt_value, idev->base + WAIT_TIMER_CONTROL);
-+ /* Check if timeout error happened */
-+ if (idev->msg_err)
-+ goto out;
-+
- /* Start manual mode */
- writel(CMD_MANUAL, idev->base + MST_COMMAND);
-
-+ writel(WT_EN | wt_value, idev->base + WAIT_TIMER_CONTROL);
-+
- i2c_int_enable(idev, int_mask);
-
- time_left = wait_for_completion_timeout(&idev->msg_complete,
-@@ -395,13 +408,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
- if (readl(idev->base + MST_COMMAND) & CMD_BUSY)
- dev_warn(idev->dev, "busy after xfer\n");
-
-- if (time_left == 0)
-+ if (time_left == 0) {
- idev->msg_err = -ETIMEDOUT;
--
-- if (idev->msg_err == -ETIMEDOUT)
- i2c_recover_bus(&idev->adapter);
-+ axxia_i2c_init(idev);
-+ }
-
-- if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO)
-+out:
-+ if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO &&
-+ idev->msg_err != -ETIMEDOUT)
- axxia_i2c_init(idev);
-
- return idev->msg_err;
-@@ -409,7 +424,7 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
-
- static int axxia_i2c_stop(struct axxia_i2c_dev *idev)
- {
-- u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC;
-+ u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC | MST_STATUS_TSS;
- unsigned long time_left;
-
- reinit_completion(&idev->msg_complete);
-@@ -436,6 +451,9 @@ axxia_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
- int i;
- int ret = 0;
-
-+ idev->msg_err = 0;
-+ i2c_int_enable(idev, MST_STATUS_TSS);
-+
- for (i = 0; ret == 0 && i < num; ++i)
- ret = axxia_i2c_xfer_msg(idev, &msgs[i]);
-
-diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c
-index efefcfa24a4c..d2178f701b41 100644
---- a/drivers/i2c/busses/i2c-scmi.c
-+++ b/drivers/i2c/busses/i2c-scmi.c
-@@ -364,6 +364,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
- {
- struct acpi_smbus_cmi *smbus_cmi;
- const struct acpi_device_id *id;
-+ int ret;
-
- smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
- if (!smbus_cmi)
-@@ -385,8 +386,10 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
- acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
- acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
-
-- if (smbus_cmi->cap_info == 0)
-+ if (smbus_cmi->cap_info == 0) {
-+ ret = -ENODEV;
- goto err;
-+ }
-
- snprintf(smbus_cmi->adapter.name, sizeof(smbus_cmi->adapter.name),
- "SMBus CMI adapter %s",
-@@ -397,7 +400,8 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
- smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
- smbus_cmi->adapter.dev.parent = &device->dev;
-
-- if (i2c_add_adapter(&smbus_cmi->adapter)) {
-+ ret = i2c_add_adapter(&smbus_cmi->adapter);
-+ if (ret) {
- dev_err(&device->dev, "Couldn't register adapter!\n");
- goto err;
- }
-@@ -407,7 +411,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
- err:
- kfree(smbus_cmi);
- device->driver_data = NULL;
-- return -EIO;
-+ return ret;
- }
-
- static int acpi_smbus_cmi_remove(struct acpi_device *device)
-diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
-index 96a345248224..0add5bb3cee8 100644
---- a/drivers/ide/pmac.c
-+++ b/drivers/ide/pmac.c
-@@ -920,6 +920,7 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
- struct device_node *root = of_find_node_by_path("/");
- const char *model = of_get_property(root, "model", NULL);
-
-+ of_node_put(root);
- /* Get cable type from device-tree. */
- if (cable && !strncmp(cable, "80-", 3)) {
- /* Some drives fail to detect 80c cable in PowerBook */
-diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
-index 6639b2b8528a..f78c464899db 100644
---- a/drivers/input/keyboard/omap4-keypad.c
-+++ b/drivers/input/keyboard/omap4-keypad.c
-@@ -60,8 +60,18 @@
-
- /* OMAP4 values */
- #define OMAP4_VAL_IRQDISABLE 0x0
--#define OMAP4_VAL_DEBOUNCINGTIME 0x7
--#define OMAP4_VAL_PVT 0x7
-+
-+/*
-+ * Errata i689: If a key is released for a time shorter than debounce time,
-+ * the keyboard will idle and never detect the key release. The workaround
-+ * is to use at least a 12ms debounce time. See omap5432 TRM chapter
-+ * "26.4.6.2 Keyboard Controller Timer" for more information.
-+ */
-+#define OMAP4_KEYPAD_PTV_DIV_128 0x6
-+#define OMAP4_KEYPAD_DEBOUNCINGTIME_MS(dbms, ptv) \
-+ ((((dbms) * 1000) / ((1 << ((ptv) + 1)) * (1000000 / 32768))) - 1)
-+#define OMAP4_VAL_DEBOUNCINGTIME_16MS \
-+ OMAP4_KEYPAD_DEBOUNCINGTIME_MS(16, OMAP4_KEYPAD_PTV_DIV_128)
-
- enum {
- KBD_REVISION_OMAP4 = 0,
-@@ -181,9 +191,9 @@ static int omap4_keypad_open(struct input_dev *input)
-
- kbd_writel(keypad_data, OMAP4_KBD_CTRL,
- OMAP4_DEF_CTRL_NOSOFTMODE |
-- (OMAP4_VAL_PVT << OMAP4_DEF_CTRL_PTV_SHIFT));
-+ (OMAP4_KEYPAD_PTV_DIV_128 << OMAP4_DEF_CTRL_PTV_SHIFT));
- kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
-- OMAP4_VAL_DEBOUNCINGTIME);
-+ OMAP4_VAL_DEBOUNCINGTIME_16MS);
- /* clear pending interrupts */
- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
- kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
-diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
-index b9958a123594..5bcf4f45f8b4 100644
---- a/drivers/mmc/host/omap.c
-+++ b/drivers/mmc/host/omap.c
-@@ -105,6 +105,7 @@ struct mmc_omap_slot {
- unsigned int vdd;
- u16 saved_con;
- u16 bus_mode;
-+ u16 power_mode;
- unsigned int fclk_freq;
-
- struct tasklet_struct cover_tasklet;
-@@ -1156,7 +1157,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- struct mmc_omap_slot *slot = mmc_priv(mmc);
- struct mmc_omap_host *host = slot->host;
- int i, dsor;
-- int clk_enabled;
-+ int clk_enabled, init_stream;
-
- mmc_omap_select_slot(slot, 0);
-
-@@ -1166,6 +1167,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- slot->vdd = ios->vdd;
-
- clk_enabled = 0;
-+ init_stream = 0;
- switch (ios->power_mode) {
- case MMC_POWER_OFF:
- mmc_omap_set_power(slot, 0, ios->vdd);
-@@ -1173,13 +1175,17 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- case MMC_POWER_UP:
- /* Cannot touch dsor yet, just power up MMC */
- mmc_omap_set_power(slot, 1, ios->vdd);
-+ slot->power_mode = ios->power_mode;
- goto exit;
- case MMC_POWER_ON:
- mmc_omap_fclk_enable(host, 1);
- clk_enabled = 1;
- dsor |= 1 << 11;
-+ if (slot->power_mode != MMC_POWER_ON)
-+ init_stream = 1;
- break;
- }
-+ slot->power_mode = ios->power_mode;
-
- if (slot->bus_mode != ios->bus_mode) {
- if (slot->pdata->set_bus_mode != NULL)
-@@ -1195,7 +1201,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
- for (i = 0; i < 2; i++)
- OMAP_MMC_WRITE(host, CON, dsor);
- slot->saved_con = dsor;
-- if (ios->power_mode == MMC_POWER_ON) {
-+ if (init_stream) {
- /* worst case at 400kHz, 80 cycles makes 200 microsecs */
- int usecs = 250;
-
-@@ -1233,6 +1239,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
- slot->host = host;
- slot->mmc = mmc;
- slot->id = id;
-+ slot->power_mode = MMC_POWER_UNDEFINED;
- slot->pdata = &host->pdata->slots[id];
-
- host->slots[id] = slot;
-diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
-index 940e2ebbdea8..399c627b15cc 100644
---- a/drivers/net/bonding/bond_3ad.c
-+++ b/drivers/net/bonding/bond_3ad.c
-@@ -2011,6 +2011,9 @@ void bond_3ad_unbind_slave(struct slave *slave)
- aggregator->aggregator_identifier);
-
- /* Tell the partner that this port is not suitable for aggregation */
-+ port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
-+ port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
-+ port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
- port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
- __update_lacpdu_from_port(port);
- ad_lacpdu_send(port);
-diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
-index 0527f485c3dc..973fcd442aea 100644
---- a/drivers/net/dsa/mv88e6060.c
-+++ b/drivers/net/dsa/mv88e6060.c
-@@ -98,8 +98,7 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds)
- /* Reset the switch. */
- REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
- GLOBAL_ATU_CONTROL_SWRESET |
-- GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
-- GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
-+ GLOBAL_ATU_CONTROL_LEARNDIS);
-
- /* Wait up to one second for reset to complete. */
- timeout = jiffies + 1 * HZ;
-@@ -124,13 +123,10 @@ static int mv88e6060_setup_global(struct dsa_switch *ds)
- */
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, GLOBAL_CONTROL_MAX_FRAME_1536);
-
-- /* Enable automatic address learning, set the address
-- * database size to 1024 entries, and set the default aging
-- * time to 5 minutes.
-+ /* Disable automatic address learning.
- */
- REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
-- GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
-- GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
-+ GLOBAL_ATU_CONTROL_LEARNDIS);
-
- return 0;
- }
-diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
-index ab480ea6d95a..0d1abcfec003 100644
---- a/drivers/net/wireless/mac80211_hwsim.c
-+++ b/drivers/net/wireless/mac80211_hwsim.c
-@@ -3195,16 +3195,16 @@ static int __init init_mac80211_hwsim(void)
- if (err)
- return err;
-
-+ err = hwsim_init_netlink();
-+ if (err)
-+ goto out_unregister_driver;
-+
- hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
- if (IS_ERR(hwsim_class)) {
- err = PTR_ERR(hwsim_class);
-- goto out_unregister_driver;
-+ goto out_exit_netlink;
- }
-
-- err = hwsim_init_netlink();
-- if (err < 0)
-- goto out_unregister_driver;
--
- for (i = 0; i < radios; i++) {
- struct hwsim_new_radio_params param = { 0 };
-
-@@ -3310,6 +3310,8 @@ out_free_mon:
- free_netdev(hwsim_mon);
- out_free_radios:
- mac80211_hwsim_free();
-+out_exit_netlink:
-+ hwsim_exit_netlink();
- out_unregister_driver:
- platform_driver_unregister(&mac80211_hwsim_driver);
- return err;
-diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
-index a7c81e988656..383977ea3a3c 100644
---- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
-+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
-@@ -568,7 +568,7 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = {
- SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
- SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
-- SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)), /* PH_EINT11 */
-+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)), /* PH_EINT11 */
- };
-
- static const struct sunxi_pinctrl_desc sun8i_a83t_pinctrl_data = {
-diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
-index a161fbf6f172..63ad5b543f14 100644
---- a/drivers/rtc/rtc-snvs.c
-+++ b/drivers/rtc/rtc-snvs.c
-@@ -47,49 +47,83 @@ struct snvs_rtc_data {
- struct clk *clk;
- };
-
-+/* Read 64 bit timer register, which could be in inconsistent state */
-+static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
-+{
-+ u32 msb, lsb;
-+
-+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
-+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
-+ return (u64)msb << 32 | lsb;
-+}
-+
-+/* Read the secure real time counter, taking care to deal with the cases of the
-+ * counter updating while being read.
-+ */
- static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
- {
- u64 read1, read2;
-- u32 val;
-+ unsigned int timeout = 100;
-
-+ /* As expected, the registers might update between the read of the LSB
-+ * reg and the MSB reg. It's also possible that one register might be
-+ * in partially modified state as well.
-+ */
-+ read1 = rtc_read_lpsrt(data);
- do {
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
-- read1 = val;
-- read1 <<= 32;
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
-- read1 |= val;
--
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
-- read2 = val;
-- read2 <<= 32;
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
-- read2 |= val;
-- } while (read1 != read2);
-+ read2 = read1;
-+ read1 = rtc_read_lpsrt(data);
-+ } while (read1 != read2 && --timeout);
-+ if (!timeout)
-+ dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
-
- /* Convert 47-bit counter to 32-bit raw second count */
- return (u32) (read1 >> CNTR_TO_SECS_SH);
- }
-
--static void rtc_write_sync_lp(struct snvs_rtc_data *data)
-+/* Just read the lsb from the counter, dealing with inconsistent state */
-+static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
- {
-- u32 count1, count2, count3;
-- int i;
--
-- /* Wait for 3 CKIL cycles */
-- for (i = 0; i < 3; i++) {
-- do {
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
-- } while (count1 != count2);
--
-- /* Now wait until counter value changes */
-- do {
-- do {
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
-- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
-- } while (count2 != count3);
-- } while (count3 == count1);
-+ u32 count1, count2;
-+ unsigned int timeout = 100;
-+
-+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
-+ do {
-+ count2 = count1;
-+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
-+ } while (count1 != count2 && --timeout);
-+ if (!timeout) {
-+ dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
-+ return -ETIMEDOUT;
- }
-+
-+ *lsb = count1;
-+ return 0;
-+}
-+
-+static int rtc_write_sync_lp(struct snvs_rtc_data *data)
-+{
-+ u32 count1, count2;
-+ u32 elapsed;
-+ unsigned int timeout = 1000;
-+ int ret;
-+
-+ ret = rtc_read_lp_counter_lsb(data, &count1);
-+ if (ret)
-+ return ret;
-+
-+ /* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
-+ do {
-+ ret = rtc_read_lp_counter_lsb(data, &count2);
-+ if (ret)
-+ return ret;
-+ elapsed = count2 - count1; /* wrap around _is_ handled! */
-+ } while (elapsed < 3 && --timeout);
-+ if (!timeout) {
-+ dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
-+ return -ETIMEDOUT;
-+ }
-+ return 0;
- }
-
- static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
-@@ -173,9 +207,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
- (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
- enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
-
-- rtc_write_sync_lp(data);
--
-- return 0;
-+ return rtc_write_sync_lp(data);
- }
-
- static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-@@ -183,10 +215,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
- struct snvs_rtc_data *data = dev_get_drvdata(dev);
- struct rtc_time *alrm_tm = &alrm->time;
- unsigned long time;
-+ int ret;
-
- rtc_tm_to_time(alrm_tm, &time);
-
- regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
-+ ret = rtc_write_sync_lp(data);
-+ if (ret)
-+ return ret;
- regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
-
- /* Clear alarm interrupt status bit */
-diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
-index 33fbe8249fd5..044cffbc45e8 100644
---- a/drivers/sbus/char/display7seg.c
-+++ b/drivers/sbus/char/display7seg.c
-@@ -221,6 +221,7 @@ static int d7s_probe(struct platform_device *op)
- dev_set_drvdata(&op->dev, p);
- d7s_device = p;
- err = 0;
-+ of_node_put(opts);
-
- out:
- return err;
-diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
-index 5609b602c54d..baa9b322520b 100644
---- a/drivers/sbus/char/envctrl.c
-+++ b/drivers/sbus/char/envctrl.c
-@@ -910,8 +910,10 @@ static void envctrl_init_i2c_child(struct device_node *dp,
- for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
- pchild->mon_type[len] = ENVCTRL_NOMON;
- }
-+ of_node_put(root_node);
- return;
- }
-+ of_node_put(root_node);
- }
-
- /* Get the monitor channels. */
-diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
-index a74f8fbefd33..009a2ef829d6 100644
---- a/drivers/scsi/libiscsi.c
-+++ b/drivers/scsi/libiscsi.c
-@@ -2416,8 +2416,8 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc)
- failed:
- ISCSI_DBG_EH(session,
- "failing session reset: Could not log back into "
-- "%s, %s [age %d]\n", session->targetname,
-- conn->persistent_address, session->age);
-+ "%s [age %d]\n", session->targetname,
-+ session->age);
- spin_unlock_bh(&session->frwd_lock);
- mutex_unlock(&session->eh_mutex);
- return FAILED;
-diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
-index 0de2f9069e23..23081ed8f1e3 100644
---- a/drivers/scsi/vmw_pvscsi.c
-+++ b/drivers/scsi/vmw_pvscsi.c
-@@ -1199,8 +1199,6 @@ static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter)
-
- static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
- {
-- pvscsi_shutdown_intr(adapter);
--
- if (adapter->workqueue)
- destroy_workqueue(adapter->workqueue);
-
-@@ -1529,6 +1527,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
- out_reset_adapter:
- ll_adapter_reset(adapter);
- out_release_resources:
-+ pvscsi_shutdown_intr(adapter);
- pvscsi_release_resources(adapter);
- scsi_host_put(host);
- out_disable_device:
-@@ -1537,6 +1536,7 @@ out_disable_device:
- return error;
-
- out_release_resources_and_disable:
-+ pvscsi_shutdown_intr(adapter);
- pvscsi_release_resources(adapter);
- goto out_disable_device;
- }
-diff --git a/drivers/tty/serial/suncore.c b/drivers/tty/serial/suncore.c
-index 127472bd6a7c..209f314745ab 100644
---- a/drivers/tty/serial/suncore.c
-+++ b/drivers/tty/serial/suncore.c
-@@ -111,6 +111,7 @@ void sunserial_console_termios(struct console *con, struct device_node *uart_dp)
- mode = of_get_property(dp, mode_prop, NULL);
- if (!mode)
- mode = "9600,8,n,1,-";
-+ of_node_put(dp);
- }
-
- cflag = CREAD | HUPCL | CLOCAL;
-diff --git a/fs/aio.c b/fs/aio.c
-index c283eb03cb38..7187d03aa0bc 100644
---- a/fs/aio.c
-+++ b/fs/aio.c
-@@ -40,6 +40,7 @@
- #include
- #include
- #include
-+#include
-
- #include
- #include
-@@ -1063,6 +1064,7 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id)
- if (!table || id >= table->nr)
- goto out;
-
-+ id = array_index_nospec(id, table->nr);
- ctx = rcu_dereference(table->table[id]);
- if (ctx && ctx->user_id == ctx_id) {
- if (percpu_ref_tryget_live(&ctx->users))
-diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
-index e7b478b49985..8bef27b8f85d 100644
---- a/fs/cifs/Kconfig
-+++ b/fs/cifs/Kconfig
-@@ -111,7 +111,7 @@ config CIFS_XATTR
-
- config CIFS_POSIX
- bool "CIFS POSIX Extensions"
-- depends on CIFS_XATTR
-+ depends on CIFS && CIFS_ALLOW_INSECURE_LEGACY && CIFS_XATTR
- help
- Enabling this option will cause the cifs client to attempt to
- negotiate a newer dialect with servers, such as Samba 3.0.5
-diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
-index ef4f16e81283..1407ed20ea93 100644
---- a/kernel/time/timer_list.c
-+++ b/kernel/time/timer_list.c
-@@ -399,7 +399,7 @@ static int __init init_timer_list_procfs(void)
- {
- struct proc_dir_entry *pe;
-
-- pe = proc_create("timer_list", 0444, NULL, &timer_list_fops);
-+ pe = proc_create("timer_list", 0400, NULL, &timer_list_fops);
- if (!pe)
- return -ENOMEM;
- return 0;
-diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
-index ac758a53fcea..d90b42b39908 100644
---- a/kernel/trace/ftrace.c
-+++ b/kernel/trace/ftrace.c
-@@ -4767,6 +4767,7 @@ void ftrace_destroy_filter_files(struct ftrace_ops *ops)
- if (ops->flags & FTRACE_OPS_FL_ENABLED)
- ftrace_shutdown(ops, 0);
- ops->flags |= FTRACE_OPS_FL_DELETED;
-+ ftrace_free_filter(ops);
- mutex_unlock(&ftrace_lock);
- }
-
-diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
-index b8a894adab2c..8be66a2b0cac 100644
---- a/kernel/trace/trace_events_trigger.c
-+++ b/kernel/trace/trace_events_trigger.c
-@@ -727,8 +727,10 @@ static int set_trigger_filter(char *filter_str,
-
- /* The filter is for the 'trigger' event, not the triggered event */
- ret = create_event_filter(file->event_call, filter_str, false, &filter);
-- if (ret)
-- goto out;
-+ /*
-+ * If create_event_filter() fails, filter still needs to be freed.
-+ * Which the calling code will do with data->filter.
-+ */
- assign:
- tmp = rcu_access_pointer(data->filter);
-
-diff --git a/lib/interval_tree_test.c b/lib/interval_tree_test.c
-index 245900b98c8e..222c8010bda0 100644
---- a/lib/interval_tree_test.c
-+++ b/lib/interval_tree_test.c
-@@ -1,27 +1,38 @@
- #include
-+#include
- #include
- #include
-+#include
- #include
-
--#define NODES 100
--#define PERF_LOOPS 100000
--#define SEARCHES 100
--#define SEARCH_LOOPS 10000
-+#define __param(type, name, init, msg) \
-+ static type name = init; \
-+ module_param(name, type, 0444); \
-+ MODULE_PARM_DESC(name, msg);
-+
-+__param(int, nnodes, 100, "Number of nodes in the interval tree");
-+__param(int, perf_loops, 1000, "Number of iterations modifying the tree");
-+
-+__param(int, nsearches, 100, "Number of searches to the interval tree");
-+__param(int, search_loops, 1000, "Number of iterations searching the tree");
-+__param(bool, search_all, false, "Searches will iterate all nodes in the tree");
-+
-+__param(uint, max_endpoint, ~0, "Largest value for the interval's endpoint");
-
- static struct rb_root root = RB_ROOT;
--static struct interval_tree_node nodes[NODES];
--static u32 queries[SEARCHES];
-+static struct interval_tree_node *nodes = NULL;
-+static u32 *queries = NULL;
-
- static struct rnd_state rnd;
-
- static inline unsigned long
--search(unsigned long query, struct rb_root *root)
-+search(struct rb_root *root, unsigned long start, unsigned long last)
- {
- struct interval_tree_node *node;
- unsigned long results = 0;
-
-- for (node = interval_tree_iter_first(root, query, query); node;
-- node = interval_tree_iter_next(node, query, query))
-+ for (node = interval_tree_iter_first(root, start, last); node;
-+ node = interval_tree_iter_next(node, start, last))
- results++;
- return results;
- }
-@@ -29,19 +40,22 @@ search(unsigned long query, struct rb_root *root)
- static void init(void)
- {
- int i;
-- for (i = 0; i < NODES; i++) {
-- u32 a = prandom_u32_state(&rnd);
-- u32 b = prandom_u32_state(&rnd);
-- if (a <= b) {
-- nodes[i].start = a;
-- nodes[i].last = b;
-- } else {
-- nodes[i].start = b;
-- nodes[i].last = a;
-- }
-+
-+ for (i = 0; i < nnodes; i++) {
-+ u32 b = (prandom_u32_state(&rnd) >> 4) % max_endpoint;
-+ u32 a = (prandom_u32_state(&rnd) >> 4) % b;
-+
-+ nodes[i].start = a;
-+ nodes[i].last = b;
- }
-- for (i = 0; i < SEARCHES; i++)
-- queries[i] = prandom_u32_state(&rnd);
-+
-+ /*
-+ * Limit the search scope to what the user defined.
-+ * Otherwise we are merely measuring empty walks,
-+ * which is pointless.
-+ */
-+ for (i = 0; i < nsearches; i++)
-+ queries[i] = (prandom_u32_state(&rnd) >> 4) % max_endpoint;
- }
-
- static int interval_tree_test_init(void)
-@@ -50,6 +64,16 @@ static int interval_tree_test_init(void)
- unsigned long results;
- cycles_t time1, time2, time;
-
-+ nodes = kmalloc(nnodes * sizeof(struct interval_tree_node), GFP_KERNEL);
-+ if (!nodes)
-+ return -ENOMEM;
-+
-+ queries = kmalloc(nsearches * sizeof(int), GFP_KERNEL);
-+ if (!queries) {
-+ kfree(nodes);
-+ return -ENOMEM;
-+ }
-+
- printk(KERN_ALERT "interval tree insert/remove");
-
- prandom_seed_state(&rnd, 3141592653589793238ULL);
-@@ -57,39 +81,46 @@ static int interval_tree_test_init(void)
-
- time1 = get_cycles();
-
-- for (i = 0; i < PERF_LOOPS; i++) {
-- for (j = 0; j < NODES; j++)
-+ for (i = 0; i < perf_loops; i++) {
-+ for (j = 0; j < nnodes; j++)
- interval_tree_insert(nodes + j, &root);
-- for (j = 0; j < NODES; j++)
-+ for (j = 0; j < nnodes; j++)
- interval_tree_remove(nodes + j, &root);
- }
-
- time2 = get_cycles();
- time = time2 - time1;
-
-- time = div_u64(time, PERF_LOOPS);
-+ time = div_u64(time, perf_loops);
- printk(" -> %llu cycles\n", (unsigned long long)time);
-
- printk(KERN_ALERT "interval tree search");
-
-- for (j = 0; j < NODES; j++)
-+ for (j = 0; j < nnodes; j++)
- interval_tree_insert(nodes + j, &root);
-
- time1 = get_cycles();
-
- results = 0;
-- for (i = 0; i < SEARCH_LOOPS; i++)
-- for (j = 0; j < SEARCHES; j++)
-- results += search(queries[j], &root);
-+ for (i = 0; i < search_loops; i++)
-+ for (j = 0; j < nsearches; j++) {
-+ unsigned long start = search_all ? 0 : queries[j];
-+ unsigned long last = search_all ? max_endpoint : queries[j];
-+
-+ results += search(&root, start, last);
-+ }
-
- time2 = get_cycles();
- time = time2 - time1;
-
-- time = div_u64(time, SEARCH_LOOPS);
-- results = div_u64(results, SEARCH_LOOPS);
-+ time = div_u64(time, search_loops);
-+ results = div_u64(results, search_loops);
- printk(" -> %llu cycles (%lu results)\n",
- (unsigned long long)time, results);
-
-+ kfree(queries);
-+ kfree(nodes);
-+
- return -EAGAIN; /* Fail will directly unload the module */
- }
-
-diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c
-index 8b3c9dc88262..afedd3770562 100644
---- a/lib/rbtree_test.c
-+++ b/lib/rbtree_test.c
-@@ -1,11 +1,18 @@
- #include
-+#include
- #include
- #include
-+#include
- #include
-
--#define NODES 100
--#define PERF_LOOPS 100000
--#define CHECK_LOOPS 100
-+#define __param(type, name, init, msg) \
-+ static type name = init; \
-+ module_param(name, type, 0444); \
-+ MODULE_PARM_DESC(name, msg);
-+
-+__param(int, nnodes, 100, "Number of nodes in the rb-tree");
-+__param(int, perf_loops, 1000, "Number of iterations modifying the rb-tree");
-+__param(int, check_loops, 100, "Number of iterations modifying and verifying the rb-tree");
-
- struct test_node {
- u32 key;
-@@ -17,7 +24,7 @@ struct test_node {
- };
-
- static struct rb_root root = RB_ROOT;
--static struct test_node nodes[NODES];
-+static struct test_node *nodes = NULL;
-
- static struct rnd_state rnd;
-
-@@ -95,7 +102,7 @@ static void erase_augmented(struct test_node *node, struct rb_root *root)
- static void init(void)
- {
- int i;
-- for (i = 0; i < NODES; i++) {
-+ for (i = 0; i < nnodes; i++) {
- nodes[i].key = prandom_u32_state(&rnd);
- nodes[i].val = prandom_u32_state(&rnd);
- }
-@@ -177,6 +184,10 @@ static int __init rbtree_test_init(void)
- int i, j;
- cycles_t time1, time2, time;
-
-+ nodes = kmalloc(nnodes * sizeof(*nodes), GFP_KERNEL);
-+ if (!nodes)
-+ return -ENOMEM;
-+
- printk(KERN_ALERT "rbtree testing");
-
- prandom_seed_state(&rnd, 3141592653589793238ULL);
-@@ -184,27 +195,27 @@ static int __init rbtree_test_init(void)
-
- time1 = get_cycles();
-
-- for (i = 0; i < PERF_LOOPS; i++) {
-- for (j = 0; j < NODES; j++)
-+ for (i = 0; i < perf_loops; i++) {
-+ for (j = 0; j < nnodes; j++)
- insert(nodes + j, &root);
-- for (j = 0; j < NODES; j++)
-+ for (j = 0; j < nnodes; j++)
- erase(nodes + j, &root);
- }
-
- time2 = get_cycles();
- time = time2 - time1;
-
-- time = div_u64(time, PERF_LOOPS);
-+ time = div_u64(time, perf_loops);
- printk(" -> %llu cycles\n", (unsigned long long)time);
-
-- for (i = 0; i < CHECK_LOOPS; i++) {
-+ for (i = 0; i < check_loops; i++) {
- init();
-- for (j = 0; j < NODES; j++) {
-+ for (j = 0; j < nnodes; j++) {
- check(j);
- insert(nodes + j, &root);
- }
-- for (j = 0; j < NODES; j++) {
-- check(NODES - j);
-+ for (j = 0; j < nnodes; j++) {
-+ check(nnodes - j);
- erase(nodes + j, &root);
- }
- check(0);
-@@ -216,32 +227,34 @@ static int __init rbtree_test_init(void)
-
- time1 = get_cycles();
-
-- for (i = 0; i < PERF_LOOPS; i++) {
-- for (j = 0; j < NODES; j++)
-+ for (i = 0; i < perf_loops; i++) {
-+ for (j = 0; j < nnodes; j++)
- insert_augmented(nodes + j, &root);
-- for (j = 0; j < NODES; j++)
-+ for (j = 0; j < nnodes; j++)
- erase_augmented(nodes + j, &root);
- }
-
- time2 = get_cycles();
- time = time2 - time1;
-
-- time = div_u64(time, PERF_LOOPS);
-+ time = div_u64(time, perf_loops);
- printk(" -> %llu cycles\n", (unsigned long long)time);
-
-- for (i = 0; i < CHECK_LOOPS; i++) {
-+ for (i = 0; i < check_loops; i++) {
- init();
-- for (j = 0; j < NODES; j++) {
-+ for (j = 0; j < nnodes; j++) {
- check_augmented(j);
- insert_augmented(nodes + j, &root);
- }
-- for (j = 0; j < NODES; j++) {
-- check_augmented(NODES - j);
-+ for (j = 0; j < nnodes; j++) {
-+ check_augmented(nnodes - j);
- erase_augmented(nodes + j, &root);
- }
- check_augmented(0);
- }
-
-+ kfree(nodes);
-+
- return -EAGAIN; /* Fail will directly unload the module */
- }
-
-diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
-index a5e11280f405..ed4fef32b394 100644
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -1886,7 +1886,8 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
- params[ac].acm = acm;
- params[ac].uapsd = uapsd;
-
-- if (params[ac].cw_min > params[ac].cw_max) {
-+ if (params[ac].cw_min == 0 ||
-+ params[ac].cw_min > params[ac].cw_max) {
- sdata_info(sdata,
- "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n",
- params[ac].cw_min, params[ac].cw_max, aci);
-diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
-index 2e98f4a243e5..112c191b8336 100644
---- a/net/sunrpc/xprt.c
-+++ b/net/sunrpc/xprt.c
-@@ -758,8 +758,15 @@ void xprt_connect(struct rpc_task *task)
- return;
- if (xprt_test_and_set_connecting(xprt))
- return;
-- xprt->stat.connect_start = jiffies;
-- xprt->ops->connect(xprt, task);
-+ /* Race breaker */
-+ if (!xprt_connected(xprt)) {
-+ xprt->stat.connect_start = jiffies;
-+ xprt->ops->connect(xprt, task);
-+ } else {
-+ xprt_clear_connecting(xprt);
-+ task->tk_status = 0;
-+ rpc_wake_up_queued_task(&xprt->pending, task);
-+ }
- }
- xprt_release_write(xprt, task);
- }
-diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
-index 69f76ff5693d..718d5e3b7806 100644
---- a/sound/isa/wavefront/wavefront_synth.c
-+++ b/sound/isa/wavefront/wavefront_synth.c
-@@ -785,6 +785,9 @@ wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header)
- DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n",
- header->number);
-
-+ if (header->number >= ARRAY_SIZE(dev->patch_status))
-+ return -EINVAL;
-+
- dev->patch_status[header->number] |= WF_SLOT_FILLED;
-
- bptr = buf;
-@@ -809,6 +812,9 @@ wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header)
- DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n",
- header->number);
-
-+ if (header->number >= ARRAY_SIZE(dev->prog_status))
-+ return -EINVAL;
-+
- dev->prog_status[header->number] = WF_SLOT_USED;
-
- /* XXX need to zero existing SLOT_USED bit for program_status[i]
-@@ -898,6 +904,9 @@ wavefront_send_sample (snd_wavefront_t *dev,
- header->number = x;
- }
-
-+ if (header->number >= WF_MAX_SAMPLE)
-+ return -EINVAL;
-+
- if (header->size) {
-
- /* XXX it's a debatable point whether or not RDONLY semantics
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.169-170.patch b/patch/kernel/rk3399-default/04-patch-4.4.169-170.patch
deleted file mode 100644
index db38c6d6a..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.169-170.patch
+++ /dev/null
@@ -1,2154 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 0d41b0626c0c..bc58f206c0da 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 169
-+SUBLEVEL = 170
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
-index 3c6672b3796b..7f5df8992008 100644
---- a/arch/arm/mach-imx/cpuidle-imx6sx.c
-+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
-@@ -97,7 +97,7 @@ int __init imx6sx_cpuidle_init(void)
- * except for power up sw2iso which need to be
- * larger than LDO ramp up time.
- */
-- imx_gpc_set_arm_power_up_timing(2, 1);
-+ imx_gpc_set_arm_power_up_timing(0xf, 1);
- imx_gpc_set_arm_power_down_timing(1, 1);
-
- return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
-diff --git a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
-index 37fe58c19a90..542c3ede9722 100644
---- a/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
-+++ b/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
-@@ -13,6 +13,7 @@
- #include
- #include
- #include
-+#include "../../../../include/linux/sizes.h"
-
- int main(int argc, char *argv[])
- {
-@@ -45,11 +46,11 @@ int main(int argc, char *argv[])
- vmlinuz_load_addr = vmlinux_load_addr + vmlinux_size;
-
- /*
-- * Align with 16 bytes: "greater than that used for any standard data
-- * types by a MIPS compiler." -- See MIPS Run Linux (Second Edition).
-+ * Align with 64KB: KEXEC needs load sections to be aligned to PAGE_SIZE,
-+ * which may be as large as 64KB depending on the kernel configuration.
- */
-
-- vmlinuz_load_addr += (16 - vmlinux_size % 16);
-+ vmlinuz_load_addr += (SZ_64K - vmlinux_size % SZ_64K);
-
- printf("0x%llx\n", vmlinuz_load_addr);
-
-diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
-index cf661a2fb141..16fade4f49dd 100644
---- a/arch/mips/include/asm/pgtable-64.h
-+++ b/arch/mips/include/asm/pgtable-64.h
-@@ -189,6 +189,11 @@ static inline int pmd_bad(pmd_t pmd)
-
- static inline int pmd_present(pmd_t pmd)
- {
-+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
-+ if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
-+ return pmd_val(pmd) & _PAGE_PRESENT;
-+#endif
-+
- return pmd_val(pmd) != (unsigned long) invalid_pte_table;
- }
-
-diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
-index 5c2199857aa8..a3550e8f1a77 100644
---- a/arch/powerpc/boot/crt0.S
-+++ b/arch/powerpc/boot/crt0.S
-@@ -15,7 +15,7 @@
- RELA = 7
- RELACOUNT = 0x6ffffff9
-
-- .text
-+ .data
- /* A procedure descriptor used when booting this as a COFF file.
- * When making COFF, this comes first in the link and we're
- * linked at 0x500000.
-@@ -23,6 +23,8 @@ RELACOUNT = 0x6ffffff9
- .globl _zimage_start_opd
- _zimage_start_opd:
- .long 0x500000, 0, 0, 0
-+ .text
-+ b _zimage_start
-
- #ifdef __powerpc64__
- .balign 8
-diff --git a/arch/x86/crypto/chacha20_glue.c b/arch/x86/crypto/chacha20_glue.c
-index 8baaff5af0b5..75b9d43069f1 100644
---- a/arch/x86/crypto/chacha20_glue.c
-+++ b/arch/x86/crypto/chacha20_glue.c
-@@ -77,6 +77,7 @@ static int chacha20_simd(struct blkcipher_desc *desc, struct scatterlist *dst,
-
- blkcipher_walk_init(&walk, dst, src, nbytes);
- err = blkcipher_walk_virt_block(desc, &walk, CHACHA20_BLOCK_SIZE);
-+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-
- crypto_chacha20_init(state, crypto_blkcipher_ctx(desc->tfm), walk.iv);
-
-diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
-index c048d0d70cc4..2cb49ac1b2b2 100644
---- a/arch/x86/include/asm/kvm_host.h
-+++ b/arch/x86/include/asm/kvm_host.h
-@@ -1200,7 +1200,7 @@ asmlinkage void kvm_spurious_fault(void);
- "cmpb $0, kvm_rebooting \n\t" \
- "jne 668b \n\t" \
- __ASM_SIZE(push) " $666b \n\t" \
-- "call kvm_spurious_fault \n\t" \
-+ "jmp kvm_spurious_fault \n\t" \
- ".popsection \n\t" \
- _ASM_EXTABLE(666b, 667b)
-
-diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c
-index d76f13d6d8d6..ec894bf5eeb0 100644
---- a/arch/x86/kernel/cpu/mtrr/if.c
-+++ b/arch/x86/kernel/cpu/mtrr/if.c
-@@ -173,6 +173,8 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg)
- struct mtrr_gentry gentry;
- void __user *arg = (void __user *) __arg;
-
-+ memset(&gentry, 0, sizeof(gentry));
-+
- switch (cmd) {
- case MTRRIOC_ADD_ENTRY:
- case MTRRIOC_SET_ENTRY:
-diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
-index e4b5fd72ca24..3bdb2e747b89 100644
---- a/arch/x86/kvm/vmx.c
-+++ b/arch/x86/kvm/vmx.c
-@@ -6163,9 +6163,24 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
-
- gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
- if (!kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
-- skip_emulated_instruction(vcpu);
- trace_kvm_fast_mmio(gpa);
-- return 1;
-+ /*
-+ * Doing kvm_skip_emulated_instruction() depends on undefined
-+ * behavior: Intel's manual doesn't mandate
-+ * VM_EXIT_INSTRUCTION_LEN to be set in VMCS when EPT MISCONFIG
-+ * occurs and while on real hardware it was observed to be set,
-+ * other hypervisors (namely Hyper-V) don't set it, we end up
-+ * advancing IP with some random value. Disable fast mmio when
-+ * running nested and keep it for real hardware in hope that
-+ * VM_EXIT_INSTRUCTION_LEN will always be set correctly.
-+ */
-+ if (!static_cpu_has(X86_FEATURE_HYPERVISOR)) {
-+ skip_emulated_instruction(vcpu);
-+ return 1;
-+ }
-+ else
-+ return x86_emulate_instruction(vcpu, gpa, EMULTYPE_SKIP,
-+ NULL, 0) == EMULATE_DONE;
- }
-
- ret = handle_mmio_page_fault(vcpu, gpa, true);
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index aa1a0277a678..1a934bb8ed1c 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -5436,7 +5436,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
- * handle watchpoints yet, those would be handled in
- * the emulate_ops.
- */
-- if (kvm_vcpu_check_breakpoint(vcpu, &r))
-+ if (!(emulation_type & EMULTYPE_SKIP) &&
-+ kvm_vcpu_check_breakpoint(vcpu, &r))
- return r;
-
- ctxt->interruptibility = 0;
-diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
-index 05813fbf3daf..647dfbbc4e1c 100644
---- a/drivers/gpio/gpio-max7301.c
-+++ b/drivers/gpio/gpio-max7301.c
-@@ -25,7 +25,7 @@ static int max7301_spi_write(struct device *dev, unsigned int reg,
- struct spi_device *spi = to_spi_device(dev);
- u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
-
-- return spi_write(spi, (const u8 *)&word, sizeof(word));
-+ return spi_write_then_read(spi, &word, sizeof(word), NULL, 0);
- }
-
- /* A read from the MAX7301 means two transfers; here, one message each */
-@@ -37,14 +37,8 @@ static int max7301_spi_read(struct device *dev, unsigned int reg)
- struct spi_device *spi = to_spi_device(dev);
-
- word = 0x8000 | (reg << 8);
-- ret = spi_write(spi, (const u8 *)&word, sizeof(word));
-- if (ret)
-- return ret;
-- /*
-- * This relies on the fact, that a transfer with NULL tx_buf shifts out
-- * zero bytes (=NOOP for MAX7301)
-- */
-- ret = spi_read(spi, (u8 *)&word, sizeof(word));
-+ ret = spi_write_then_read(spi, &word, sizeof(word), &word,
-+ sizeof(word));
- if (ret)
- return ret;
- return word & 0xff;
-diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
-index 8ce2a0c59116..a7030ada81fd 100644
---- a/drivers/gpu/drm/drm_ioctl.c
-+++ b/drivers/gpu/drm/drm_ioctl.c
-@@ -36,6 +36,7 @@
-
- #include
- #include
-+#include
-
- static int drm_version(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-@@ -702,13 +703,17 @@ long drm_ioctl(struct file *filp,
-
- if (is_driver_ioctl) {
- /* driver ioctl */
-- if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
-+ unsigned int index = nr - DRM_COMMAND_BASE;
-+
-+ if (index >= dev->driver->num_ioctls)
- goto err_i1;
-- ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
-+ index = array_index_nospec(index, dev->driver->num_ioctls);
-+ ioctl = &dev->driver->ioctls[index];
- } else {
- /* core ioctl */
- if (nr >= DRM_CORE_IOCTL_COUNT)
- goto err_i1;
-+ nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT);
- ioctl = &drm_ioctls[nr];
- }
-
-@@ -810,6 +815,7 @@ bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
-
- if (nr >= DRM_CORE_IOCTL_COUNT)
- return false;
-+ nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT);
-
- *flags = drm_ioctls[nr].flags;
- return true;
-diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
-index 802dcb409030..b877cce0409b 100644
---- a/drivers/hv/vmbus_drv.c
-+++ b/drivers/hv/vmbus_drv.c
-@@ -316,6 +316,8 @@ static ssize_t out_intr_mask_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
- return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
- }
-@@ -329,6 +331,8 @@ static ssize_t out_read_index_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
- return sprintf(buf, "%d\n", outbound.current_read_index);
- }
-@@ -343,6 +347,8 @@ static ssize_t out_write_index_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
- return sprintf(buf, "%d\n", outbound.current_write_index);
- }
-@@ -357,6 +363,8 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
- return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
- }
-@@ -371,6 +379,8 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
- return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
- }
-@@ -384,6 +394,8 @@ static ssize_t in_intr_mask_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
- return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
- }
-@@ -397,6 +409,8 @@ static ssize_t in_read_index_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
- return sprintf(buf, "%d\n", inbound.current_read_index);
- }
-@@ -410,6 +424,8 @@ static ssize_t in_write_index_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
- return sprintf(buf, "%d\n", inbound.current_write_index);
- }
-@@ -424,6 +440,8 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
- return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
- }
-@@ -438,6 +456,8 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
-
- if (!hv_dev->channel)
- return -ENODEV;
-+ if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-+ return -EINVAL;
- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
- return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
- }
-diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c
-index 70ca27e45602..9d9e47eb0842 100644
---- a/drivers/hwtracing/intel_th/msu.c
-+++ b/drivers/hwtracing/intel_th/msu.c
-@@ -1418,7 +1418,8 @@ nr_pages_store(struct device *dev, struct device_attribute *attr,
- if (!end)
- break;
-
-- len -= end - p;
-+ /* consume the number and the following comma, hence +1 */
-+ len -= end - p + 1;
- p = end + 1;
- } while (len);
-
-diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
-index f78c464899db..3d2c60c8de83 100644
---- a/drivers/input/keyboard/omap4-keypad.c
-+++ b/drivers/input/keyboard/omap4-keypad.c
-@@ -126,12 +126,8 @@ static irqreturn_t omap4_keypad_irq_handler(int irq, void *dev_id)
- {
- struct omap4_keypad *keypad_data = dev_id;
-
-- if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)) {
-- /* Disable interrupts */
-- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
-- OMAP4_VAL_IRQDISABLE);
-+ if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS))
- return IRQ_WAKE_THREAD;
-- }
-
- return IRQ_NONE;
- }
-@@ -173,11 +169,6 @@ static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
- kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
-
-- /* enable interrupts */
-- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
-- OMAP4_DEF_IRQENABLE_EVENTEN |
-- OMAP4_DEF_IRQENABLE_LONGKEY);
--
- return IRQ_HANDLED;
- }
-
-@@ -214,9 +205,10 @@ static void omap4_keypad_close(struct input_dev *input)
-
- disable_irq(keypad_data->irq);
-
-- /* Disable interrupts */
-+ /* Disable interrupts and wake-up events */
- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
- OMAP4_VAL_IRQDISABLE);
-+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, 0);
-
- /* clear pending interrupts */
- kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
-@@ -364,7 +356,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
- }
-
- error = request_threaded_irq(keypad_data->irq, omap4_keypad_irq_handler,
-- omap4_keypad_irq_thread_fn, 0,
-+ omap4_keypad_irq_thread_fn, IRQF_ONESHOT,
- "omap4-keypad", keypad_data);
- if (error) {
- dev_err(&pdev->dev, "failed to register interrupt\n");
-diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
-index 471984ec2db0..30adc5745cba 100644
---- a/drivers/input/mouse/elan_i2c_core.c
-+++ b/drivers/input/mouse/elan_i2c_core.c
-@@ -1240,6 +1240,7 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
- static const struct acpi_device_id elan_acpi_id[] = {
- { "ELAN0000", 0 },
- { "ELAN0100", 0 },
-+ { "ELAN0501", 0 },
- { "ELAN0600", 0 },
- { "ELAN0602", 0 },
- { "ELAN0605", 0 },
-diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
-index 7feaa82f8c7c..8b4a4d95669a 100644
---- a/drivers/iommu/intel-iommu.c
-+++ b/drivers/iommu/intel-iommu.c
-@@ -2041,7 +2041,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
- * than default. Unnecessary for PT mode.
- */
- if (translation != CONTEXT_TT_PASS_THROUGH) {
-- for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
-+ for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
- ret = -ENOMEM;
- pgd = phys_to_virt(dma_pte_addr(pgd));
- if (!dma_pte_present(pgd))
-@@ -2055,7 +2055,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
- translation = CONTEXT_TT_MULTI_LEVEL;
-
- context_set_address_root(context, virt_to_phys(pgd));
-- context_set_address_width(context, iommu->agaw);
-+ context_set_address_width(context, agaw);
- } else {
- /*
- * In pass through mode, AW must be programmed to
-diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
-index dd7e38ac29bd..d15347de415a 100644
---- a/drivers/isdn/capi/kcapi.c
-+++ b/drivers/isdn/capi/kcapi.c
-@@ -851,7 +851,7 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf)
- u16 ret;
-
- if (contr == 0) {
-- strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
-+ strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
- return CAPI_NOERROR;
- }
-
-@@ -859,7 +859,7 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf)
-
- ctr = get_capi_ctr_by_nr(contr);
- if (ctr && ctr->state == CAPI_CTR_RUNNING) {
-- strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
-+ strncpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
- ret = CAPI_NOERROR;
- } else
- ret = CAPI_REGNOTINSTALLED;
-diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
-index ef5412311b2f..a84954f1be34 100644
---- a/drivers/media/platform/vivid/vivid-vid-cap.c
-+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
-@@ -461,6 +461,8 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
- tpg_s_rgb_range(&dev->tpg, v4l2_ctrl_g_ctrl(dev->rgb_range_cap));
- break;
- }
-+ vfree(dev->bitmap_cap);
-+ dev->bitmap_cap = NULL;
- vivid_update_quality(dev);
- tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
- dev->crop_cap = dev->src_rect;
-diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
-index 524660510599..0c15ba21fa54 100644
---- a/drivers/misc/genwqe/card_utils.c
-+++ b/drivers/misc/genwqe/card_utils.c
-@@ -217,7 +217,7 @@ u32 genwqe_crc32(u8 *buff, size_t len, u32 init)
- void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
- dma_addr_t *dma_handle)
- {
-- if (get_order(size) > MAX_ORDER)
-+ if (get_order(size) >= MAX_ORDER)
- return NULL;
-
- return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle,
-diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
-index 79a0c26e1419..a31789be0840 100644
---- a/drivers/mmc/core/mmc.c
-+++ b/drivers/mmc/core/mmc.c
-@@ -1608,9 +1608,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
- if (err) {
- pr_warn("%s: Enabling HPI failed\n",
- mmc_hostname(card->host));
-+ card->ext_csd.hpi_en = 0;
- err = 0;
-- } else
-+ } else {
- card->ext_csd.hpi_en = 1;
-+ }
- }
-
- /*
-diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
-index 6b814d7d6560..af937d3e8c3e 100644
---- a/drivers/mmc/host/omap_hsmmc.c
-+++ b/drivers/mmc/host/omap_hsmmc.c
-@@ -2117,7 +2117,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
- mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
- mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
- mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-- mmc->max_seg_size = mmc->max_req_size;
-
- mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
- MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
-@@ -2174,6 +2173,17 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
- goto err_irq;
- }
-
-+ /*
-+ * Limit the maximum segment size to the lower of the request size
-+ * and the DMA engine device segment size limits. In reality, with
-+ * 32-bit transfers, the DMA engine can do longer segments than this
-+ * but there is no way to represent that in the DMA model - if we
-+ * increase this figure here, we get warnings from the DMA API debug.
-+ */
-+ mmc->max_seg_size = min3(mmc->max_req_size,
-+ dma_get_max_seg_size(host->rx_chan->device->dev),
-+ dma_get_max_seg_size(host->tx_chan->device->dev));
-+
- /* Request IRQ for MMC operations */
- ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
- mmc_hostname(mmc), host);
-diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
-index 2f9b12cf9ee5..61a9ab4fe047 100644
---- a/drivers/net/ethernet/ibm/ibmveth.c
-+++ b/drivers/net/ethernet/ibm/ibmveth.c
-@@ -1163,11 +1163,15 @@ out:
-
- map_failed_frags:
- last = i+1;
-- for (i = 0; i < last; i++)
-+ for (i = 1; i < last; i++)
- dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
- descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
- DMA_TO_DEVICE);
-
-+ dma_unmap_single(&adapter->vdev->dev,
-+ descs[0].fields.address,
-+ descs[0].fields.flags_len & IBMVETH_BUF_LEN_MASK,
-+ DMA_TO_DEVICE);
- map_failed:
- if (!firmware_has_feature(FW_FEATURE_CMO))
- netdev_err(netdev, "tx: unable to map xmit buffer\n");
-diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
-index 111d907e0c11..79cede19e0c4 100644
---- a/drivers/net/usb/hso.c
-+++ b/drivers/net/usb/hso.c
-@@ -2825,6 +2825,12 @@ static int hso_get_config_data(struct usb_interface *interface)
- return -EIO;
- }
-
-+ /* check if we have a valid interface */
-+ if (if_num > 16) {
-+ kfree(config_data);
-+ return -EINVAL;
-+ }
-+
- switch (config_data[if_num]) {
- case 0x0:
- result = 0;
-@@ -2895,10 +2901,18 @@ static int hso_probe(struct usb_interface *interface,
-
- /* Get the interface/port specification from either driver_info or from
- * the device itself */
-- if (id->driver_info)
-+ if (id->driver_info) {
-+ /* if_num is controlled by the device, driver_info is a 0 terminated
-+ * array. Make sure, the access is in bounds! */
-+ for (i = 0; i <= if_num; ++i)
-+ if (((u32 *)(id->driver_info))[i] == 0)
-+ goto exit;
- port_spec = ((u32 *)(id->driver_info))[if_num];
-- else
-+ } else {
- port_spec = hso_get_config_data(interface);
-+ if (port_spec < 0)
-+ goto exit;
-+ }
-
- /* Check if we need to switch to alt interfaces prior to port
- * configuration */
-diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
-index ec2b9c577b90..3644c9edaf81 100644
---- a/drivers/net/wireless/b43/phy_common.c
-+++ b/drivers/net/wireless/b43/phy_common.c
-@@ -616,7 +616,7 @@ struct b43_c32 b43_cordic(int theta)
- u8 i;
- s32 tmp;
- s8 signx = 1;
-- u32 angle = 0;
-+ s32 angle = 0;
- struct b43_c32 ret = { .i = 39797, .q = 0, };
-
- while (theta > (180 << 16))
-diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
-index 0a4bd73caae5..6f55ab4f7959 100644
---- a/drivers/net/xen-netfront.c
-+++ b/drivers/net/xen-netfront.c
-@@ -889,7 +889,7 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
- if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) {
- unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
-
-- BUG_ON(pull_to <= skb_headlen(skb));
-+ BUG_ON(pull_to < skb_headlen(skb));
- __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
- }
- if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
-diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
-index 9e29b1321648..15783869e1a0 100644
---- a/drivers/power/olpc_battery.c
-+++ b/drivers/power/olpc_battery.c
-@@ -427,14 +427,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
- if (ret)
- return ret;
-
-- val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256;
-+ val->intval = (s16)be16_to_cpu(ec_word) * 10 / 256;
- break;
- case POWER_SUPPLY_PROP_TEMP_AMBIENT:
- ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
- if (ret)
- return ret;
-
-- val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
-+ val->intval = (int)be16_to_cpu(ec_word) * 10 / 256;
- break;
- case POWER_SUPPLY_PROP_CHARGE_COUNTER:
- ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
-diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
-index 38c8e308d4c8..a96c98e3fc73 100644
---- a/drivers/s390/scsi/zfcp_aux.c
-+++ b/drivers/s390/scsi/zfcp_aux.c
-@@ -275,16 +275,16 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
- */
- int zfcp_status_read_refill(struct zfcp_adapter *adapter)
- {
-- while (atomic_read(&adapter->stat_miss) > 0)
-+ while (atomic_add_unless(&adapter->stat_miss, -1, 0))
- if (zfcp_fsf_status_read(adapter->qdio)) {
-+ atomic_inc(&adapter->stat_miss); /* undo add -1 */
- if (atomic_read(&adapter->stat_miss) >=
- adapter->stat_read_buf_num) {
- zfcp_erp_adapter_reopen(adapter, 0, "axsref1");
- return 1;
- }
- break;
-- } else
-- atomic_dec(&adapter->stat_miss);
-+ }
- return 0;
- }
-
-diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
-index d0b227ffbd5f..573aeec7a02b 100644
---- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
-+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
-@@ -2279,7 +2279,7 @@ static int _bnx2fc_create(struct net_device *netdev,
- if (!interface) {
- printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
- rc = -ENOMEM;
-- goto ifput_err;
-+ goto netdev_err;
- }
-
- if (netdev->priv_flags & IFF_802_1Q_VLAN) {
-diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
-index cf04960cc3e6..1a1368f5863c 100644
---- a/drivers/spi/spi-bcm2835.c
-+++ b/drivers/spi/spi-bcm2835.c
-@@ -88,7 +88,7 @@ struct bcm2835_spi {
- u8 *rx_buf;
- int tx_len;
- int rx_len;
-- bool dma_pending;
-+ unsigned int dma_pending;
- };
-
- static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned reg)
-@@ -155,8 +155,7 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
- /* Write as many bytes as possible to FIFO */
- bcm2835_wr_fifo(bs);
-
-- /* based on flags decide if we can finish the transfer */
-- if (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE) {
-+ if (!bs->rx_len) {
- /* Transfer complete - reset SPI HW */
- bcm2835_spi_reset_hw(master);
- /* wake up the framework */
-@@ -233,10 +232,9 @@ static void bcm2835_spi_dma_done(void *data)
- * is called the tx-dma must have finished - can't get to this
- * situation otherwise...
- */
-- dmaengine_terminate_all(master->dma_tx);
--
-- /* mark as no longer pending */
-- bs->dma_pending = 0;
-+ if (cmpxchg(&bs->dma_pending, true, false)) {
-+ dmaengine_terminate_all(master->dma_tx);
-+ }
-
- /* and mark as completed */;
- complete(&master->xfer_completion);
-@@ -342,6 +340,7 @@ static int bcm2835_spi_transfer_one_dma(struct spi_master *master,
- if (ret) {
- /* need to reset on errors */
- dmaengine_terminate_all(master->dma_tx);
-+ bs->dma_pending = false;
- bcm2835_spi_reset_hw(master);
- return ret;
- }
-@@ -617,10 +616,9 @@ static void bcm2835_spi_handle_err(struct spi_master *master,
- struct bcm2835_spi *bs = spi_master_get_devdata(master);
-
- /* if an error occurred and we have an active dma, then terminate */
-- if (bs->dma_pending) {
-+ if (cmpxchg(&bs->dma_pending, true, false)) {
- dmaengine_terminate_all(master->dma_tx);
- dmaengine_terminate_all(master->dma_rx);
-- bs->dma_pending = 0;
- }
- /* and reset */
- bcm2835_spi_reset_hw(master);
-diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
-index 0a8e5ac891d4..3919ea066bf9 100644
---- a/drivers/usb/class/cdc-acm.c
-+++ b/drivers/usb/class/cdc-acm.c
-@@ -507,6 +507,13 @@ static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
- if (retval)
- goto error_init_termios;
-
-+ /*
-+ * Suppress initial echoing for some devices which might send data
-+ * immediately after acm driver has been installed.
-+ */
-+ if (acm->quirks & DISABLE_ECHO)
-+ tty->termios.c_lflag &= ~ECHO;
-+
- tty->driver_data = acm;
-
- return 0;
-@@ -1677,6 +1684,9 @@ static const struct usb_device_id acm_ids[] = {
- { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
- .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
- },
-+ { USB_DEVICE(0x0e8d, 0x2000), /* MediaTek Inc Preloader */
-+ .driver_info = DISABLE_ECHO, /* DISABLE ECHO in termios flag */
-+ },
- { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */
- .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
- },
-diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
-index b30ac5fcde68..1ad9ff9f493d 100644
---- a/drivers/usb/class/cdc-acm.h
-+++ b/drivers/usb/class/cdc-acm.h
-@@ -134,3 +134,4 @@ struct acm {
- #define QUIRK_CONTROL_LINE_STATE BIT(6)
- #define CLEAR_HALT_CONDITIONS BIT(7)
- #define SEND_ZERO_PACKET BIT(8)
-+#define DISABLE_ECHO BIT(9)
-diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
-index a11c2c8bda53..a217f71b45c6 100644
---- a/drivers/usb/host/r8a66597-hcd.c
-+++ b/drivers/usb/host/r8a66597-hcd.c
-@@ -1990,6 +1990,8 @@ static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
-
- static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
- struct usb_host_endpoint *hep)
-+__acquires(r8a66597->lock)
-+__releases(r8a66597->lock)
- {
- struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
- struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv;
-@@ -2002,13 +2004,14 @@ static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
- return;
- pipenum = pipe->info.pipenum;
-
-+ spin_lock_irqsave(&r8a66597->lock, flags);
- if (pipenum == 0) {
- kfree(hep->hcpriv);
- hep->hcpriv = NULL;
-+ spin_unlock_irqrestore(&r8a66597->lock, flags);
- return;
- }
-
-- spin_lock_irqsave(&r8a66597->lock, flags);
- pipe_stop(r8a66597, pipe);
- pipe_irq_disable(r8a66597, pipenum);
- disable_irq_empty(r8a66597, pipenum);
-diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
-index 5d21cd8359d4..421825b44202 100644
---- a/drivers/usb/host/xhci-hub.c
-+++ b/drivers/usb/host/xhci-hub.c
-@@ -1329,7 +1329,8 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
- portsc_buf[port_index] = 0;
-
- /* Bail out if a USB3 port has a new device in link training */
-- if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) {
-+ if ((hcd->speed >= HCD_USB3) &&
-+ (t1 & PORT_PLS_MASK) == XDEV_POLLING) {
- bus_state->bus_suspended = 0;
- spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "Bus suspend bailout, port in polling\n");
-diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
-index 2b81939fecd7..7bc2c9fef605 100644
---- a/drivers/usb/serial/option.c
-+++ b/drivers/usb/serial/option.c
-@@ -1163,6 +1163,10 @@ static const struct usb_device_id option_ids[] = {
- { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1213, 0xff) },
- { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1214),
- .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) },
-+ { USB_DEVICE(TELIT_VENDOR_ID, 0x1900), /* Telit LN940 (QMI) */
-+ .driver_info = NCTRL(0) | RSVD(1) },
-+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff), /* Telit LN940 (MBIM) */
-+ .driver_info = NCTRL(0) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
- .driver_info = RSVD(1) },
-@@ -1327,6 +1331,7 @@ static const struct usb_device_id option_ids[] = {
- .driver_info = RSVD(4) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) },
-+ { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0602, 0xff) }, /* GosunCn ZTE WeLink ME3630 (MBIM mode) */
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
- .driver_info = RSVD(4) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
-@@ -1530,6 +1535,7 @@ static const struct usb_device_id option_ids[] = {
- .driver_info = RSVD(2) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G v2 */
- .driver_info = RSVD(2) },
-+ { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) }, /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
-@@ -1757,6 +1763,7 @@ static const struct usb_device_id option_ids[] = {
- { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
- { USB_DEVICE(ALINK_VENDOR_ID, SIMCOM_PRODUCT_SIM7100E),
- .driver_info = RSVD(5) | RSVD(6) },
-+ { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9003, 0xff) }, /* Simcom SIM7500/SIM7600 MBIM mode */
- { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
- .driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) },
- { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D),
-@@ -1941,7 +1948,18 @@ static const struct usb_device_id option_ids[] = {
- { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) },
-- { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
-+ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
-+ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x10) }, /* HP lt4132 (Huawei ME906s-158) */
-+ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x12) },
-+ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x13) },
-+ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x14) },
-+ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0xa31d, 0xff, 0x06, 0x1b) },
-+ { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 */
-+ .driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
-+ { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
-+ .driver_info = RSVD(4) | RSVD(5) },
-+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
-+ .driver_info = RSVD(6) },
- { } /* Terminating entry */
- };
- MODULE_DEVICE_TABLE(usb, option_ids);
-diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
-index 3da25ad267a2..4966768d3c98 100644
---- a/drivers/usb/serial/pl2303.c
-+++ b/drivers/usb/serial/pl2303.c
-@@ -86,9 +86,14 @@ static const struct usb_device_id id_table[] = {
- { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
- { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
- { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
-+ { USB_DEVICE(HP_VENDOR_ID, HP_LD220TA_PRODUCT_ID) },
- { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) },
-+ { USB_DEVICE(HP_VENDOR_ID, HP_LD960TA_PRODUCT_ID) },
- { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
- { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
-+ { USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) },
-+ { USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) },
-+ { USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) },
- { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
- { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
- { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
-diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
-index 123289085ee2..a84f0959ab34 100644
---- a/drivers/usb/serial/pl2303.h
-+++ b/drivers/usb/serial/pl2303.h
-@@ -123,10 +123,15 @@
-
- /* Hewlett-Packard POS Pole Displays */
- #define HP_VENDOR_ID 0x03f0
-+#define HP_LM920_PRODUCT_ID 0x026b
-+#define HP_TD620_PRODUCT_ID 0x0956
- #define HP_LD960_PRODUCT_ID 0x0b39
- #define HP_LCM220_PRODUCT_ID 0x3139
- #define HP_LCM960_PRODUCT_ID 0x3239
- #define HP_LD220_PRODUCT_ID 0x3524
-+#define HP_LD220TA_PRODUCT_ID 0x4349
-+#define HP_LD960TA_PRODUCT_ID 0x4439
-+#define HP_LM940_PRODUCT_ID 0x5039
-
- /* Cressi Edy (diving computer) PC interface */
- #define CRESSI_VENDOR_ID 0x04b8
-diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
-index c54d388310f0..2ed0a356d1d3 100644
---- a/drivers/vhost/vhost.c
-+++ b/drivers/vhost/vhost.c
-@@ -1550,6 +1550,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
- return -EFAULT;
- }
- if (unlikely(vq->log_used)) {
-+ /* Make sure used idx is seen before log. */
-+ smp_wmb();
- /* Log used index update. */
- log_write(vq->log_base,
- vq->log_addr + offsetof(struct vring_used, idx),
-diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
-index 0e3de1bb6500..e7b54514d99a 100644
---- a/fs/ceph/caps.c
-+++ b/fs/ceph/caps.c
-@@ -3243,7 +3243,6 @@ retry:
- tcap->cap_id = t_cap_id;
- tcap->seq = t_seq - 1;
- tcap->issue_seq = t_seq - 1;
-- tcap->mseq = t_mseq;
- tcap->issued |= issued;
- tcap->implemented |= issued;
- if (cap == ci->i_auth_cap)
-diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
-index 8257a5a97cc0..98c25b969ab8 100644
---- a/fs/cifs/smb2maperror.c
-+++ b/fs/cifs/smb2maperror.c
-@@ -377,8 +377,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
- {STATUS_NONEXISTENT_EA_ENTRY, -EIO, "STATUS_NONEXISTENT_EA_ENTRY"},
- {STATUS_NO_EAS_ON_FILE, -ENODATA, "STATUS_NO_EAS_ON_FILE"},
- {STATUS_EA_CORRUPT_ERROR, -EIO, "STATUS_EA_CORRUPT_ERROR"},
-- {STATUS_FILE_LOCK_CONFLICT, -EIO, "STATUS_FILE_LOCK_CONFLICT"},
-- {STATUS_LOCK_NOT_GRANTED, -EIO, "STATUS_LOCK_NOT_GRANTED"},
-+ {STATUS_FILE_LOCK_CONFLICT, -EACCES, "STATUS_FILE_LOCK_CONFLICT"},
-+ {STATUS_LOCK_NOT_GRANTED, -EACCES, "STATUS_LOCK_NOT_GRANTED"},
- {STATUS_DELETE_PENDING, -ENOENT, "STATUS_DELETE_PENDING"},
- {STATUS_CTL_FILE_NOT_SUPPORTED, -ENOSYS,
- "STATUS_CTL_FILE_NOT_SUPPORTED"},
-diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
-index 35502d4046f5..3a7f401e943c 100644
---- a/fs/dlm/lock.c
-+++ b/fs/dlm/lock.c
-@@ -1210,6 +1210,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
-
- if (rv < 0) {
- log_error(ls, "create_lkb idr error %d", rv);
-+ dlm_free_lkb(lkb);
- return rv;
- }
-
-@@ -4177,6 +4178,7 @@ static int receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
- (unsigned long long)lkb->lkb_recover_seq,
- ms->m_header.h_nodeid, ms->m_lkid);
- error = -ENOENT;
-+ dlm_put_lkb(lkb);
- goto fail;
- }
-
-@@ -4230,6 +4232,7 @@ static int receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
- lkb->lkb_id, lkb->lkb_remid,
- ms->m_header.h_nodeid, ms->m_lkid);
- error = -ENOENT;
-+ dlm_put_lkb(lkb);
- goto fail;
- }
-
-@@ -5792,20 +5795,20 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
- goto out;
- }
- }
--
-- /* After ua is attached to lkb it will be freed by dlm_free_lkb().
-- When DLM_IFL_USER is set, the dlm knows that this is a userspace
-- lock and that lkb_astparam is the dlm_user_args structure. */
--
- error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
- fake_astfn, ua, fake_bastfn, &args);
-- lkb->lkb_flags |= DLM_IFL_USER;
--
- if (error) {
-+ kfree(ua->lksb.sb_lvbptr);
-+ ua->lksb.sb_lvbptr = NULL;
-+ kfree(ua);
- __put_lkb(ls, lkb);
- goto out;
- }
-
-+ /* After ua is attached to lkb it will be freed by dlm_free_lkb().
-+ When DLM_IFL_USER is set, the dlm knows that this is a userspace
-+ lock and that lkb_astparam is the dlm_user_args structure. */
-+ lkb->lkb_flags |= DLM_IFL_USER;
- error = request_lock(ls, lkb, name, namelen, &args);
-
- switch (error) {
-diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
-index f3e72787e7f9..30e4e01db35a 100644
---- a/fs/dlm/lockspace.c
-+++ b/fs/dlm/lockspace.c
-@@ -673,11 +673,11 @@ static int new_lockspace(const char *name, const char *cluster,
- kfree(ls->ls_recover_buf);
- out_lkbidr:
- idr_destroy(&ls->ls_lkbidr);
-+ out_rsbtbl:
- for (i = 0; i < DLM_REMOVE_NAMES_MAX; i++) {
- if (ls->ls_remove_names[i])
- kfree(ls->ls_remove_names[i]);
- }
-- out_rsbtbl:
- vfree(ls->ls_rsbtbl);
- out_lsfree:
- if (do_unreg)
-diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
-index 1aec46733ef8..46d4fac48cf4 100644
---- a/fs/ext4/inline.c
-+++ b/fs/ext4/inline.c
-@@ -701,8 +701,11 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
-
- if (!PageUptodate(page)) {
- ret = ext4_read_inline_page(inode, page);
-- if (ret < 0)
-+ if (ret < 0) {
-+ unlock_page(page);
-+ put_page(page);
- goto out_up_read;
-+ }
- }
-
- ret = 1;
-diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
-index bad13f049fb0..2fc1564f62dd 100644
---- a/fs/ext4/resize.c
-+++ b/fs/ext4/resize.c
-@@ -1600,7 +1600,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
- }
-
- if (reserved_gdb || gdb_off == 0) {
-- if (ext4_has_feature_resize_inode(sb) ||
-+ if (!ext4_has_feature_resize_inode(sb) ||
- !le16_to_cpu(es->s_reserved_gdt_blocks)) {
- ext4_warning(sb,
- "No reserved GDT blocks, can't resize");
-diff --git a/fs/ext4/super.c b/fs/ext4/super.c
-index cd9cd581fd92..6a7df72cb3da 100644
---- a/fs/ext4/super.c
-+++ b/fs/ext4/super.c
-@@ -1049,6 +1049,16 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
- ext4_nfs_get_inode);
- }
-
-+static int ext4_nfs_commit_metadata(struct inode *inode)
-+{
-+ struct writeback_control wbc = {
-+ .sync_mode = WB_SYNC_ALL
-+ };
-+
-+ trace_ext4_nfs_commit_metadata(inode);
-+ return ext4_write_inode(inode, &wbc);
-+}
-+
- /*
- * Try to release metadata pages (indirect blocks, directories) which are
- * mapped via the block device. Since these pages could have journal heads
-@@ -1143,6 +1153,7 @@ static const struct export_operations ext4_export_ops = {
- .fh_to_dentry = ext4_fh_to_dentry,
- .fh_to_parent = ext4_fh_to_parent,
- .get_parent = ext4_get_parent,
-+ .commit_metadata = ext4_nfs_commit_metadata,
- };
-
- enum {
-@@ -5184,9 +5195,9 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
- qf_inode->i_flags |= S_NOQUOTA;
- lockdep_set_quota_inode(qf_inode, I_DATA_SEM_QUOTA);
- err = dquot_enable(qf_inode, type, format_id, flags);
-- iput(qf_inode);
- if (err)
- lockdep_set_quota_inode(qf_inode, I_DATA_SEM_NORMAL);
-+ iput(qf_inode);
-
- return err;
- }
-diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
-index ef24894edecc..763fe7737065 100644
---- a/fs/gfs2/rgrp.c
-+++ b/fs/gfs2/rgrp.c
-@@ -1720,9 +1720,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
- goto next_iter;
- }
- if (ret == -E2BIG) {
-+ n += rbm->bii - initial_bii;
- rbm->bii = 0;
- rbm->offset = 0;
-- n += (rbm->bii - initial_bii);
- goto res_covered_end_of_rgrp;
- }
- return ret;
-diff --git a/include/net/gro_cells.h b/include/net/gro_cells.h
-index cf6c74550baa..86316f90ea1e 100644
---- a/include/net/gro_cells.h
-+++ b/include/net/gro_cells.h
-@@ -84,6 +84,7 @@ static inline void gro_cells_destroy(struct gro_cells *gcells)
- for_each_possible_cpu(i) {
- struct gro_cell *cell = per_cpu_ptr(gcells->cells, i);
-
-+ napi_disable(&cell->napi);
- netif_napi_del(&cell->napi);
- __skb_queue_purge(&cell->napi_skbs);
- }
-diff --git a/include/net/sock.h b/include/net/sock.h
-index 577075713ad5..7420299c31f5 100644
---- a/include/net/sock.h
-+++ b/include/net/sock.h
-@@ -299,6 +299,7 @@ struct cg_proto;
- * @sk_filter: socket filtering instructions
- * @sk_timer: sock cleanup timer
- * @sk_stamp: time stamp of last packet received
-+ * @sk_stamp_seq: lock for accessing sk_stamp on 32 bit architectures only
- * @sk_tsflags: SO_TIMESTAMPING socket options
- * @sk_tskey: counter to disambiguate concurrent tstamp requests
- * @sk_socket: Identd and reporting IO signals
-@@ -434,6 +435,9 @@ struct sock {
- long sk_sndtimeo;
- struct timer_list sk_timer;
- ktime_t sk_stamp;
-+#if BITS_PER_LONG==32
-+ seqlock_t sk_stamp_seq;
-+#endif
- u16 sk_tsflags;
- u32 sk_tskey;
- struct socket *sk_socket;
-@@ -2146,6 +2150,34 @@ static inline void sk_drops_add(struct sock *sk, const struct sk_buff *skb)
- atomic_add(segs, &sk->sk_drops);
- }
-
-+static inline ktime_t sock_read_timestamp(struct sock *sk)
-+{
-+#if BITS_PER_LONG==32
-+ unsigned int seq;
-+ ktime_t kt;
-+
-+ do {
-+ seq = read_seqbegin(&sk->sk_stamp_seq);
-+ kt = sk->sk_stamp;
-+ } while (read_seqretry(&sk->sk_stamp_seq, seq));
-+
-+ return kt;
-+#else
-+ return sk->sk_stamp;
-+#endif
-+}
-+
-+static inline void sock_write_timestamp(struct sock *sk, ktime_t kt)
-+{
-+#if BITS_PER_LONG==32
-+ write_seqlock(&sk->sk_stamp_seq);
-+ sk->sk_stamp = kt;
-+ write_sequnlock(&sk->sk_stamp_seq);
-+#else
-+ sk->sk_stamp = kt;
-+#endif
-+}
-+
- void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
- struct sk_buff *skb);
- void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
-@@ -2170,7 +2202,7 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
- (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
- __sock_recv_timestamp(msg, sk, skb);
- else
-- sk->sk_stamp = kt;
-+ sock_write_timestamp(sk, kt);
-
- if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
- __sock_recv_wifi_status(msg, sk, skb);
-@@ -2190,7 +2222,7 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
- if (sk->sk_flags & FLAGS_TS_OR_DROPS || sk->sk_tsflags & TSFLAGS_ANY)
- __sock_recv_ts_and_drops(msg, sk, skb);
- else
-- sk->sk_stamp = skb->tstamp;
-+ sock_write_timestamp(sk, skb->tstamp);
- }
-
- void __sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags);
-diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
-index 594b4b29a224..7ef11b97cb2a 100644
---- a/include/trace/events/ext4.h
-+++ b/include/trace/events/ext4.h
-@@ -223,6 +223,26 @@ TRACE_EVENT(ext4_drop_inode,
- (unsigned long) __entry->ino, __entry->drop)
- );
-
-+TRACE_EVENT(ext4_nfs_commit_metadata,
-+ TP_PROTO(struct inode *inode),
-+
-+ TP_ARGS(inode),
-+
-+ TP_STRUCT__entry(
-+ __field( dev_t, dev )
-+ __field( ino_t, ino )
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->dev = inode->i_sb->s_dev;
-+ __entry->ino = inode->i_ino;
-+ ),
-+
-+ TP_printk("dev %d,%d ino %lu",
-+ MAJOR(__entry->dev), MINOR(__entry->dev),
-+ (unsigned long) __entry->ino)
-+);
-+
- TRACE_EVENT(ext4_mark_inode_dirty,
- TP_PROTO(struct inode *inode, unsigned long IP),
-
-diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
-index 87cf351bab03..9e07bf4259e1 100644
---- a/include/uapi/linux/input-event-codes.h
-+++ b/include/uapi/linux/input-event-codes.h
-@@ -708,6 +708,15 @@
-
- #define ABS_MISC 0x28
-
-+/*
-+ * 0x2e is reserved and should not be used in input drivers.
-+ * It was used by HID as ABS_MISC+6 and userspace needs to detect if
-+ * the next ABS_* event is correct or is just ABS_MISC + n.
-+ * We define here ABS_RESERVED so userspace can rely on it and detect
-+ * the situation described above.
-+ */
-+#define ABS_RESERVED 0x2e
-+
- #define ABS_MT_SLOT 0x2f /* MT slot being modified */
- #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
- #define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
-diff --git a/kernel/fork.c b/kernel/fork.c
-index dd2f79ac0771..e4b81913a998 100644
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -1411,8 +1411,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
-
- posix_cpu_timers_init(p);
-
-- p->start_time = ktime_get_ns();
-- p->real_start_time = ktime_get_boot_ns();
- p->io_context = NULL;
- p->audit_context = NULL;
- cgroup_fork(p);
-@@ -1572,6 +1570,17 @@ static struct task_struct *copy_process(unsigned long clone_flags,
- if (retval)
- goto bad_fork_free_pid;
-
-+ /*
-+ * From this point on we must avoid any synchronous user-space
-+ * communication until we take the tasklist-lock. In particular, we do
-+ * not want user-space to be able to predict the process start-time by
-+ * stalling fork(2) after we recorded the start_time but before it is
-+ * visible to the system.
-+ */
-+
-+ p->start_time = ktime_get_ns();
-+ p->real_start_time = ktime_get_boot_ns();
-+
- /*
- * Make it visible to the rest of the system, but dont wake it up yet.
- * Need tasklist lock for parent etc handling!
-diff --git a/kernel/memremap.c b/kernel/memremap.c
-index f719c925cb54..1be42f9b3e00 100644
---- a/kernel/memremap.c
-+++ b/kernel/memremap.c
-@@ -171,15 +171,12 @@ void *devm_memremap_pages(struct device *dev, struct resource *res)
- struct page_map *page_map;
- int error, nid;
-
-- if (is_ram == REGION_MIXED) {
-- WARN_ONCE(1, "%s attempted on mixed region %pr\n",
-- __func__, res);
-+ if (is_ram != REGION_DISJOINT) {
-+ WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
-+ is_ram == REGION_MIXED ? "mixed" : "ram", res);
- return ERR_PTR(-ENXIO);
- }
-
-- if (is_ram == REGION_INTERSECTS)
-- return __va(res->start);
--
- page_map = devres_alloc_node(devm_memremap_pages_release,
- sizeof(*page_map), GFP_KERNEL, dev_to_node(dev));
- if (!page_map)
-@@ -202,5 +199,5 @@ void *devm_memremap_pages(struct device *dev, struct resource *res)
- devres_add(dev, page_map);
- return __va(res->start);
- }
--EXPORT_SYMBOL(devm_memremap_pages);
-+EXPORT_SYMBOL_GPL(devm_memremap_pages);
- #endif /* CONFIG_ZONE_DEVICE */
-diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
-index a18923e4359d..0addef5f8aa3 100644
---- a/mm/memory_hotplug.c
-+++ b/mm/memory_hotplug.c
-@@ -32,6 +32,7 @@
- #include
- #include
- #include
-+#include
-
- #include
-
-@@ -1471,6 +1472,21 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
- continue;
- }
-
-+ /*
-+ * HWPoison pages have elevated reference counts so the migration would
-+ * fail on them. It also doesn't make any sense to migrate them in the
-+ * first place. Still try to unmap such a page in case it is still mapped
-+ * (e.g. current hwpoison implementation doesn't unmap KSM pages but keep
-+ * the unmap as the catch all safety net).
-+ */
-+ if (PageHWPoison(page)) {
-+ if (WARN_ON(PageLRU(page)))
-+ isolate_lru_page(page);
-+ if (page_mapped(page))
-+ try_to_unmap(page, TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS);
-+ continue;
-+ }
-+
- if (!get_page_unless_zero(page))
- continue;
- /*
-diff --git a/net/9p/client.c b/net/9p/client.c
-index ed8738c4dc09..8fba9cd973c1 100644
---- a/net/9p/client.c
-+++ b/net/9p/client.c
-@@ -156,6 +156,12 @@ static int parse_opts(char *opts, struct p9_client *clnt)
- ret = r;
- continue;
- }
-+ if (option < 4096) {
-+ p9_debug(P9_DEBUG_ERROR,
-+ "msize should be at least 4k\n");
-+ ret = -EINVAL;
-+ continue;
-+ }
- clnt->msize = option;
- break;
- case Opt_trans:
-@@ -972,10 +978,18 @@ static int p9_client_version(struct p9_client *c)
- else if (!strncmp(version, "9P2000", 6))
- c->proto_version = p9_proto_legacy;
- else {
-+ p9_debug(P9_DEBUG_ERROR,
-+ "server returned an unknown version: %s\n", version);
- err = -EREMOTEIO;
- goto error;
- }
-
-+ if (msize < 4096) {
-+ p9_debug(P9_DEBUG_ERROR,
-+ "server returned a msize < 4096: %d\n", msize);
-+ err = -EREMOTEIO;
-+ goto error;
-+ }
- if (msize < c->msize)
- c->msize = msize;
-
-@@ -1040,6 +1054,13 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
- if (clnt->msize > clnt->trans_mod->maxsize)
- clnt->msize = clnt->trans_mod->maxsize;
-
-+ if (clnt->msize < 4096) {
-+ p9_debug(P9_DEBUG_ERROR,
-+ "Please specify a msize of at least 4k\n");
-+ err = -EINVAL;
-+ goto free_client;
-+ }
-+
- err = p9_client_version(clnt);
- if (err)
- goto close_trans;
-diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
-index 2fdebabbfacd..2772f6a13fcb 100644
---- a/net/ax25/af_ax25.c
-+++ b/net/ax25/af_ax25.c
-@@ -654,15 +654,22 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
- break;
- }
-
-- dev = dev_get_by_name(&init_net, devname);
-+ rtnl_lock();
-+ dev = __dev_get_by_name(&init_net, devname);
- if (!dev) {
-+ rtnl_unlock();
- res = -ENODEV;
- break;
- }
-
- ax25->ax25_dev = ax25_dev_ax25dev(dev);
-+ if (!ax25->ax25_dev) {
-+ rtnl_unlock();
-+ res = -ENODEV;
-+ break;
-+ }
- ax25_fillin_cb(ax25, ax25->ax25_dev);
-- dev_put(dev);
-+ rtnl_unlock();
- break;
-
- default:
-diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
-index 3d106767b272..5faca5db6385 100644
---- a/net/ax25/ax25_dev.c
-+++ b/net/ax25/ax25_dev.c
-@@ -116,6 +116,7 @@ void ax25_dev_device_down(struct net_device *dev)
- if ((s = ax25_dev_list) == ax25_dev) {
- ax25_dev_list = s->next;
- spin_unlock_bh(&ax25_dev_lock);
-+ dev->ax25_ptr = NULL;
- dev_put(dev);
- kfree(ax25_dev);
- return;
-@@ -125,6 +126,7 @@ void ax25_dev_device_down(struct net_device *dev)
- if (s->next == ax25_dev) {
- s->next = ax25_dev->next;
- spin_unlock_bh(&ax25_dev_lock);
-+ dev->ax25_ptr = NULL;
- dev_put(dev);
- kfree(ax25_dev);
- return;
-diff --git a/net/compat.c b/net/compat.c
-index 17e97b106458..d67684010455 100644
---- a/net/compat.c
-+++ b/net/compat.c
-@@ -443,12 +443,14 @@ int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp)
- err = -ENOENT;
- if (!sock_flag(sk, SOCK_TIMESTAMP))
- sock_enable_timestamp(sk, SOCK_TIMESTAMP);
-- tv = ktime_to_timeval(sk->sk_stamp);
-+ tv = ktime_to_timeval(sock_read_timestamp(sk));
-+
- if (tv.tv_sec == -1)
- return err;
- if (tv.tv_sec == 0) {
-- sk->sk_stamp = ktime_get_real();
-- tv = ktime_to_timeval(sk->sk_stamp);
-+ ktime_t kt = ktime_get_real();
-+ sock_write_timestamp(sk, kt);
-+ tv = ktime_to_timeval(kt);
- }
- err = 0;
- if (put_user(tv.tv_sec, &ctv->tv_sec) ||
-@@ -471,12 +473,13 @@ int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *usersta
- err = -ENOENT;
- if (!sock_flag(sk, SOCK_TIMESTAMP))
- sock_enable_timestamp(sk, SOCK_TIMESTAMP);
-- ts = ktime_to_timespec(sk->sk_stamp);
-+ ts = ktime_to_timespec(sock_read_timestamp(sk));
- if (ts.tv_sec == -1)
- return err;
- if (ts.tv_sec == 0) {
-- sk->sk_stamp = ktime_get_real();
-- ts = ktime_to_timespec(sk->sk_stamp);
-+ ktime_t kt = ktime_get_real();
-+ sock_write_timestamp(sk, kt);
-+ ts = ktime_to_timespec(kt);
- }
- err = 0;
- if (put_user(ts.tv_sec, &ctv->tv_sec) ||
-diff --git a/net/core/sock.c b/net/core/sock.c
-index 4238835a0e4e..9fb1c073d0c4 100644
---- a/net/core/sock.c
-+++ b/net/core/sock.c
-@@ -2423,6 +2423,9 @@ void sock_init_data(struct socket *sock, struct sock *sk)
- sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
-
- sk->sk_stamp = ktime_set(-1L, 0);
-+#if BITS_PER_LONG==32
-+ seqlock_init(&sk->sk_stamp_seq);
-+#endif
-
- #ifdef CONFIG_NET_RX_BUSY_POLL
- sk->sk_napi_id = 0;
-diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
-index a10db45b2e1e..df32134da924 100644
---- a/net/ieee802154/6lowpan/tx.c
-+++ b/net/ieee802154/6lowpan/tx.c
-@@ -55,6 +55,9 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev,
- const u8 *daddr = _daddr;
- struct lowpan_addr_info *info;
-
-+ if (!daddr)
-+ return -EINVAL;
-+
- /* TODO:
- * if this package isn't ipv6 one, where should it be routed?
- */
-diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
-index 8e77786549c6..1cb865fcc91b 100644
---- a/net/ipv4/ipmr.c
-+++ b/net/ipv4/ipmr.c
-@@ -66,6 +66,7 @@
- #include
- #include
- #include
-+#include
-
- #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
- #define CONFIG_IP_PIMSM 1
-@@ -1574,6 +1575,7 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
- return -EFAULT;
- if (vr.vifi >= mrt->maxvif)
- return -EINVAL;
-+ vr.vifi = array_index_nospec(vr.vifi, mrt->maxvif);
- read_lock(&mrt_lock);
- vif = &mrt->vif_table[vr.vifi];
- if (VIF_EXISTS(mrt, vr.vifi)) {
-diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c
-index 14dacf1df529..30b03d8e321a 100644
---- a/net/ipv6/ip6_udp_tunnel.c
-+++ b/net/ipv6/ip6_udp_tunnel.c
-@@ -15,7 +15,7 @@
- int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
- struct socket **sockp)
- {
-- struct sockaddr_in6 udp6_addr;
-+ struct sockaddr_in6 udp6_addr = {};
- int err;
- struct socket *sock = NULL;
-
-@@ -42,6 +42,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
- goto error;
-
- if (cfg->peer_udp_port) {
-+ memset(&udp6_addr, 0, sizeof(udp6_addr));
- udp6_addr.sin6_family = AF_INET6;
- memcpy(&udp6_addr.sin6_addr, &cfg->peer_ip6,
- sizeof(udp6_addr.sin6_addr));
-diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
-index 9b92960f024d..74b3e9718e84 100644
---- a/net/ipv6/ip6mr.c
-+++ b/net/ipv6/ip6mr.c
-@@ -72,6 +72,8 @@ struct mr6_table {
- #endif
- };
-
-+#include
-+
- struct ip6mr_rule {
- struct fib_rule common;
- };
-@@ -1871,6 +1873,7 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
- return -EFAULT;
- if (vr.mifi >= mrt->maxvif)
- return -EINVAL;
-+ vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
- read_lock(&mrt_lock);
- vif = &mrt->vif6_table[vr.mifi];
- if (MIF_EXISTS(mrt, vr.mifi)) {
-@@ -1945,6 +1948,7 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
- return -EFAULT;
- if (vr.mifi >= mrt->maxvif)
- return -EINVAL;
-+ vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
- read_lock(&mrt_lock);
- vif = &mrt->vif6_table[vr.mifi];
- if (MIF_EXISTS(mrt, vr.mifi)) {
-diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
-index ed212ffc1d9d..046ae1caecea 100644
---- a/net/netrom/af_netrom.c
-+++ b/net/netrom/af_netrom.c
-@@ -153,7 +153,7 @@ static struct sock *nr_find_listener(ax25_address *addr)
- sk_for_each(s, &nr_list)
- if (!ax25cmp(&nr_sk(s)->source_addr, addr) &&
- s->sk_state == TCP_LISTEN) {
-- bh_lock_sock(s);
-+ sock_hold(s);
- goto found;
- }
- s = NULL;
-@@ -174,7 +174,7 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id)
- struct nr_sock *nr = nr_sk(s);
-
- if (nr->my_index == index && nr->my_id == id) {
-- bh_lock_sock(s);
-+ sock_hold(s);
- goto found;
- }
- }
-@@ -198,7 +198,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id,
-
- if (nr->your_index == index && nr->your_id == id &&
- !ax25cmp(&nr->dest_addr, dest)) {
-- bh_lock_sock(s);
-+ sock_hold(s);
- goto found;
- }
- }
-@@ -224,7 +224,7 @@ static unsigned short nr_find_next_circuit(void)
- if (i != 0 && j != 0) {
- if ((sk=nr_find_socket(i, j)) == NULL)
- break;
-- bh_unlock_sock(sk);
-+ sock_put(sk);
- }
-
- id++;
-@@ -918,6 +918,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
- }
-
- if (sk != NULL) {
-+ bh_lock_sock(sk);
- skb_reset_transport_header(skb);
-
- if (frametype == NR_CONNACK && skb->len == 22)
-@@ -927,6 +928,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
-
- ret = nr_process_rx_frame(sk, skb);
- bh_unlock_sock(sk);
-+ sock_put(sk);
- return ret;
- }
-
-@@ -958,10 +960,12 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
- (make = nr_make_new(sk)) == NULL) {
- nr_transmit_refusal(skb, 0);
- if (sk)
-- bh_unlock_sock(sk);
-+ sock_put(sk);
- return 0;
- }
-
-+ bh_lock_sock(sk);
-+
- window = skb->data[20];
-
- skb->sk = make;
-@@ -1014,6 +1018,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
- sk->sk_data_ready(sk);
-
- bh_unlock_sock(sk);
-+ sock_put(sk);
-
- nr_insert_socket(make);
-
-diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
-index 07668f152a3a..0f50977ed53b 100644
---- a/net/packet/af_packet.c
-+++ b/net/packet/af_packet.c
-@@ -2511,8 +2511,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
- sll_addr)))
- goto out;
- proto = saddr->sll_protocol;
-- addr = saddr->sll_addr;
-+ addr = saddr->sll_halen ? saddr->sll_addr : NULL;
- dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
-+ if (addr && dev && saddr->sll_halen < dev->addr_len)
-+ goto out;
- }
-
- err = -ENXIO;
-@@ -2678,8 +2680,10 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
- if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
- goto out;
- proto = saddr->sll_protocol;
-- addr = saddr->sll_addr;
-+ addr = saddr->sll_halen ? saddr->sll_addr : NULL;
- dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
-+ if (addr && dev && saddr->sll_halen < dev->addr_len)
-+ goto out;
- }
-
- err = -ENXIO;
-diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
-index 5ca8309ea7b1..7dffc97a953c 100644
---- a/net/sctp/ipv6.c
-+++ b/net/sctp/ipv6.c
-@@ -101,6 +101,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
- if (addr) {
- addr->a.v6.sin6_family = AF_INET6;
- addr->a.v6.sin6_port = 0;
-+ addr->a.v6.sin6_flowinfo = 0;
- addr->a.v6.sin6_addr = ifa->addr;
- addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
- addr->valid = 1;
-diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
-index 036bbf2b44c1..b5291ea54a3d 100644
---- a/net/sunrpc/auth_gss/svcauth_gss.c
-+++ b/net/sunrpc/auth_gss/svcauth_gss.c
-@@ -1105,7 +1105,7 @@ static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
- struct kvec *resv = &rqstp->rq_res.head[0];
- struct rsi *rsip, rsikey;
- int ret;
-- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
-+ struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
-
- memset(&rsikey, 0, sizeof(rsikey));
- ret = gss_read_verf(gc, argv, authp,
-@@ -1216,7 +1216,7 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
- uint64_t handle;
- int status;
- int ret;
-- struct net *net = rqstp->rq_xprt->xpt_net;
-+ struct net *net = SVC_NET(rqstp);
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-
- memset(&ud, 0, sizeof(ud));
-@@ -1406,7 +1406,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
- __be32 *rpcstart;
- __be32 *reject_stat = resv->iov_base + resv->iov_len;
- int ret;
-- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
-+ struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
-
- dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n",
- argv->iov_len);
-@@ -1694,7 +1694,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
- struct rpc_gss_wire_cred *gc = &gsd->clcred;
- struct xdr_buf *resbuf = &rqstp->rq_res;
- int stat = -EINVAL;
-- struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
-+ struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
-
- if (gc->gc_proc != RPC_GSS_PROC_DATA)
- goto out;
-diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
-index 63fb5ee212cf..af17b00145e1 100644
---- a/net/sunrpc/cache.c
-+++ b/net/sunrpc/cache.c
-@@ -54,6 +54,11 @@ static void cache_init(struct cache_head *h, struct cache_detail *detail)
- h->last_refresh = now;
- }
-
-+static void cache_fresh_locked(struct cache_head *head, time_t expiry,
-+ struct cache_detail *detail);
-+static void cache_fresh_unlocked(struct cache_head *head,
-+ struct cache_detail *detail);
-+
- struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
- struct cache_head *key, int hash)
- {
-@@ -95,6 +100,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
- if (cache_is_expired(detail, tmp)) {
- hlist_del_init(&tmp->cache_list);
- detail->entries --;
-+ cache_fresh_locked(tmp, 0, detail);
- freeme = tmp;
- break;
- }
-@@ -110,8 +116,10 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
- cache_get(new);
- write_unlock(&detail->hash_lock);
-
-- if (freeme)
-+ if (freeme) {
-+ cache_fresh_unlocked(freeme, detail);
- cache_put(freeme, detail);
-+ }
- return new;
- }
- EXPORT_SYMBOL_GPL(sunrpc_cache_lookup);
-diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
-index 1413cdcc131c..9701fcca002c 100644
---- a/net/sunrpc/svcsock.c
-+++ b/net/sunrpc/svcsock.c
-@@ -614,7 +614,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
- /* Don't enable netstamp, sunrpc doesn't
- need that much accuracy */
- }
-- svsk->sk_sk->sk_stamp = skb->tstamp;
-+ sock_write_timestamp(svsk->sk_sk, skb->tstamp);
- set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); /* there may be more data... */
-
- len = skb->len - sizeof(struct udphdr);
-diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
-index 589c8b9908a5..d24773552b64 100644
---- a/net/vmw_vsock/vmci_transport.c
-+++ b/net/vmw_vsock/vmci_transport.c
-@@ -272,6 +272,31 @@ vmci_transport_send_control_pkt_bh(struct sockaddr_vm *src,
- false);
- }
-
-+static int
-+vmci_transport_alloc_send_control_pkt(struct sockaddr_vm *src,
-+ struct sockaddr_vm *dst,
-+ enum vmci_transport_packet_type type,
-+ u64 size,
-+ u64 mode,
-+ struct vmci_transport_waiting_info *wait,
-+ u16 proto,
-+ struct vmci_handle handle)
-+{
-+ struct vmci_transport_packet *pkt;
-+ int err;
-+
-+ pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
-+ if (!pkt)
-+ return -ENOMEM;
-+
-+ err = __vmci_transport_send_control_pkt(pkt, src, dst, type, size,
-+ mode, wait, proto, handle,
-+ true);
-+ kfree(pkt);
-+
-+ return err;
-+}
-+
- static int
- vmci_transport_send_control_pkt(struct sock *sk,
- enum vmci_transport_packet_type type,
-@@ -281,9 +306,7 @@ vmci_transport_send_control_pkt(struct sock *sk,
- u16 proto,
- struct vmci_handle handle)
- {
-- struct vmci_transport_packet *pkt;
- struct vsock_sock *vsk;
-- int err;
-
- vsk = vsock_sk(sk);
-
-@@ -293,17 +316,10 @@ vmci_transport_send_control_pkt(struct sock *sk,
- if (!vsock_addr_bound(&vsk->remote_addr))
- return -EINVAL;
-
-- pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
-- if (!pkt)
-- return -ENOMEM;
--
-- err = __vmci_transport_send_control_pkt(pkt, &vsk->local_addr,
-- &vsk->remote_addr, type, size,
-- mode, wait, proto, handle,
-- true);
-- kfree(pkt);
--
-- return err;
-+ return vmci_transport_alloc_send_control_pkt(&vsk->local_addr,
-+ &vsk->remote_addr,
-+ type, size, mode,
-+ wait, proto, handle);
- }
-
- static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst,
-@@ -321,12 +337,29 @@ static int vmci_transport_send_reset_bh(struct sockaddr_vm *dst,
- static int vmci_transport_send_reset(struct sock *sk,
- struct vmci_transport_packet *pkt)
- {
-+ struct sockaddr_vm *dst_ptr;
-+ struct sockaddr_vm dst;
-+ struct vsock_sock *vsk;
-+
- if (pkt->type == VMCI_TRANSPORT_PACKET_TYPE_RST)
- return 0;
-- return vmci_transport_send_control_pkt(sk,
-- VMCI_TRANSPORT_PACKET_TYPE_RST,
-- 0, 0, NULL, VSOCK_PROTO_INVALID,
-- VMCI_INVALID_HANDLE);
-+
-+ vsk = vsock_sk(sk);
-+
-+ if (!vsock_addr_bound(&vsk->local_addr))
-+ return -EINVAL;
-+
-+ if (vsock_addr_bound(&vsk->remote_addr)) {
-+ dst_ptr = &vsk->remote_addr;
-+ } else {
-+ vsock_addr_init(&dst, pkt->dg.src.context,
-+ pkt->src_port);
-+ dst_ptr = &dst;
-+ }
-+ return vmci_transport_alloc_send_control_pkt(&vsk->local_addr, dst_ptr,
-+ VMCI_TRANSPORT_PACKET_TYPE_RST,
-+ 0, 0, NULL, VSOCK_PROTO_INVALID,
-+ VMCI_INVALID_HANDLE);
- }
-
- static int vmci_transport_send_negotiate(struct sock *sk, size_t size)
-diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
-index 9b6e51450fc5..13f261feb75c 100644
---- a/net/xfrm/xfrm_state.c
-+++ b/net/xfrm/xfrm_state.c
-@@ -623,7 +623,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
- {
- spin_lock_bh(&net->xfrm.xfrm_state_lock);
- si->sadcnt = net->xfrm.state_num;
-- si->sadhcnt = net->xfrm.state_hmask;
-+ si->sadhcnt = net->xfrm.state_hmask + 1;
- si->sadhmcnt = xfrm_state_hashmax;
- spin_unlock_bh(&net->xfrm.xfrm_state_lock);
- }
-diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
-index dd8397894d5c..12a6940741fe 100755
---- a/scripts/checkstack.pl
-+++ b/scripts/checkstack.pl
-@@ -46,8 +46,8 @@ my (@stack, $re, $dre, $x, $xs, $funcre);
- $xs = "[0-9a-f ]"; # hex character or space
- $funcre = qr/^$x* <(.*)>:$/;
- if ($arch eq 'aarch64') {
-- #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp,#-80]!
-- $re = qr/^.*stp.*sp,\#-([0-9]{1,8})\]\!/o;
-+ #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]!
-+ $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o;
- } elsif ($arch eq 'arm') {
- #c0008ffc: e24dd064 sub sp, sp, #100 ; 0x64
- $re = qr/.*sub.*sp, sp, #(([0-9]{2}|[3-9])[0-9]{2})/o;
-diff --git a/sound/core/pcm.c b/sound/core/pcm.c
-index 6bda8f6c5f84..cdff5f976480 100644
---- a/sound/core/pcm.c
-+++ b/sound/core/pcm.c
-@@ -25,6 +25,7 @@
- #include
- #include
- #include
-+#include
- #include
- #include
- #include
-@@ -125,6 +126,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
- return -EFAULT;
- if (stream < 0 || stream > 1)
- return -EINVAL;
-+ stream = array_index_nospec(stream, 2);
- if (get_user(subdevice, &info->subdevice))
- return -EFAULT;
- mutex_lock(®ister_mutex);
-diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
-index d2951ed4bf71..1984291ebd07 100644
---- a/sound/pci/cs46xx/dsp_spos.c
-+++ b/sound/pci/cs46xx/dsp_spos.c
-@@ -899,6 +899,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
- struct dsp_spos_instance * ins = chip->dsp_spos_instance;
- int i;
-
-+ if (!ins)
-+ return 0;
-+
- snd_info_free_entry(ins->proc_sym_info_entry);
- ins->proc_sym_info_entry = NULL;
-
-diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
-index 50b216fc369f..5d422d65e62b 100644
---- a/sound/pci/emu10k1/emufx.c
-+++ b/sound/pci/emu10k1/emufx.c
-@@ -36,6 +36,7 @@
- #include
- #include
- #include
-+#include
-
- #include
- #include
-@@ -1000,6 +1001,8 @@ static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu,
-
- if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
- return -EINVAL;
-+ ipcm->substream = array_index_nospec(ipcm->substream,
-+ EMU10K1_FX8010_PCM_COUNT);
- if (ipcm->channels > 32)
- return -EINVAL;
- pcm = &emu->fx8010.pcm[ipcm->substream];
-@@ -1046,6 +1049,8 @@ static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
-
- if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
- return -EINVAL;
-+ ipcm->substream = array_index_nospec(ipcm->substream,
-+ EMU10K1_FX8010_PCM_COUNT);
- pcm = &emu->fx8010.pcm[ipcm->substream];
- mutex_lock(&emu->fx8010.lock);
- spin_lock_irq(&emu->reg_lock);
-diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
-index 17fd81736d3d..039fbbb1e53c 100644
---- a/sound/pci/hda/hda_tegra.c
-+++ b/sound/pci/hda/hda_tegra.c
-@@ -249,10 +249,12 @@ static int hda_tegra_suspend(struct device *dev)
- struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-+ struct hdac_bus *bus = azx_bus(chip);
-
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-
- azx_stop_chip(chip);
-+ synchronize_irq(bus->irq);
- azx_enter_link_reset(chip);
- hda_tegra_disable_clocks(hda);
-
-diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
-index aea3cc2abe3a..536184ac315d 100644
---- a/sound/pci/hda/patch_conexant.c
-+++ b/sound/pci/hda/patch_conexant.c
-@@ -853,6 +853,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
- SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
-+ SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
- SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
-diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
-index 7c8941b8b2de..dd6c9e6a1d53 100644
---- a/sound/pci/rme9652/hdsp.c
-+++ b/sound/pci/rme9652/hdsp.c
-@@ -30,6 +30,7 @@
- #include
- #include
- #include
-+#include
-
- #include
- #include
-@@ -4065,15 +4066,16 @@ static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
- struct snd_pcm_channel_info *info)
- {
- struct hdsp *hdsp = snd_pcm_substream_chip(substream);
-- int mapped_channel;
-+ unsigned int channel = info->channel;
-
-- if (snd_BUG_ON(info->channel >= hdsp->max_channels))
-+ if (snd_BUG_ON(channel >= hdsp->max_channels))
- return -EINVAL;
-+ channel = array_index_nospec(channel, hdsp->max_channels);
-
-- if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
-+ if (hdsp->channel_map[channel] < 0)
- return -EINVAL;
-
-- info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
-+ info->offset = hdsp->channel_map[channel] * HDSP_CHANNEL_BUFFER_BYTES;
- info->first = 0;
- info->step = 32;
- return 0;
-diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
-index e557946718a9..d9fcae071b47 100644
---- a/sound/synth/emux/emux_hwdep.c
-+++ b/sound/synth/emux/emux_hwdep.c
-@@ -22,9 +22,9 @@
- #include
- #include
- #include
-+#include
- #include "emux_voice.h"
-
--
- #define TMP_CLIENT_ID 0x1001
-
- /*
-@@ -66,13 +66,16 @@ snd_emux_hwdep_misc_mode(struct snd_emux *emu, void __user *arg)
- return -EFAULT;
- if (info.mode < 0 || info.mode >= EMUX_MD_END)
- return -EINVAL;
-+ info.mode = array_index_nospec(info.mode, EMUX_MD_END);
-
- if (info.port < 0) {
- for (i = 0; i < emu->num_ports; i++)
- emu->portptrs[i]->ctrls[info.mode] = info.value;
- } else {
-- if (info.port < emu->num_ports)
-+ if (info.port < emu->num_ports) {
-+ info.port = array_index_nospec(info.port, emu->num_ports);
- emu->portptrs[info.port]->ctrls[info.mode] = info.value;
-+ }
- }
- return 0;
- }
-diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
-index 97d6a18e6956..f7eb0d2f797b 100644
---- a/sound/usb/mixer.c
-+++ b/sound/usb/mixer.c
-@@ -1816,7 +1816,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
- char *name)
- {
- struct uac_processing_unit_descriptor *desc = raw_desc;
-- int num_ins = desc->bNrInPins;
-+ int num_ins;
- struct usb_mixer_elem_info *cval;
- struct snd_kcontrol *kctl;
- int i, err, nameid, type, len;
-@@ -1831,7 +1831,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
- 0, NULL, default_value_info
- };
-
-- if (desc->bLength < 13 || desc->bLength < 13 + num_ins ||
-+ if (desc->bLength < 13) {
-+ usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
-+ return -EINVAL;
-+ }
-+
-+ num_ins = desc->bNrInPins;
-+ if (desc->bLength < 13 + num_ins ||
- desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) {
- usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
- return -EINVAL;
-diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
-index 15cbe2565703..d32727c74a16 100644
---- a/sound/usb/quirks-table.h
-+++ b/sound/usb/quirks-table.h
-@@ -3321,6 +3321,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
- }
- }
- },
-+ {
-+ .ifnum = -1
-+ },
- }
- }
- },
-diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
-index 593066c68e3d..4f650ebd564a 100644
---- a/tools/perf/util/pmu.c
-+++ b/tools/perf/util/pmu.c
-@@ -100,7 +100,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
- char path[PATH_MAX];
- const char *lc;
-
-- snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
-+ scnprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
-@@ -147,7 +147,7 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *n
- ssize_t sret;
- int fd;
-
-- snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
-+ scnprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
-@@ -177,7 +177,7 @@ perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
- char path[PATH_MAX];
- int fd;
-
-- snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
-+ scnprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
-@@ -195,7 +195,7 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
- char path[PATH_MAX];
- int fd;
-
-- snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
-+ scnprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.170-171.patch b/patch/kernel/rk3399-default/04-patch-4.4.170-171.patch
deleted file mode 100644
index 4061abc0c..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.170-171.patch
+++ /dev/null
@@ -1,2650 +0,0 @@
-diff --git a/Makefile b/Makefile
-index bc58f206c0da..c6b680faedd8 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 170
-+SUBLEVEL = 171
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/crypto/cts.c b/crypto/cts.c
-index e467ec0acf9f..e65688d6a4ca 100644
---- a/crypto/cts.c
-+++ b/crypto/cts.c
-@@ -137,8 +137,8 @@ static int crypto_cts_encrypt(struct blkcipher_desc *desc,
- lcldesc.info = desc->info;
- lcldesc.flags = desc->flags;
-
-- if (tot_blocks == 1) {
-- err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, bsize);
-+ if (tot_blocks <= 1) {
-+ err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, nbytes);
- } else if (nbytes <= bsize * 2) {
- err = cts_cbc_encrypt(ctx, desc, dst, src, 0, nbytes);
- } else {
-@@ -232,8 +232,8 @@ static int crypto_cts_decrypt(struct blkcipher_desc *desc,
- lcldesc.info = desc->info;
- lcldesc.flags = desc->flags;
-
-- if (tot_blocks == 1) {
-- err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, bsize);
-+ if (tot_blocks <= 1) {
-+ err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, nbytes);
- } else if (nbytes <= bsize * 2) {
- err = cts_cbc_decrypt(ctx, desc, dst, src, 0, nbytes);
- } else {
-diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
-index 1c2b846c5776..f28b4949cb9d 100644
---- a/drivers/acpi/power.c
-+++ b/drivers/acpi/power.c
-@@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list)
- }
- }
-
-+static bool acpi_power_resource_is_dup(union acpi_object *package,
-+ unsigned int start, unsigned int i)
-+{
-+ acpi_handle rhandle, dup;
-+ unsigned int j;
-+
-+ /* The caller is expected to check the package element types */
-+ rhandle = package->package.elements[i].reference.handle;
-+ for (j = start; j < i; j++) {
-+ dup = package->package.elements[j].reference.handle;
-+ if (dup == rhandle)
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
- int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
- struct list_head *list)
- {
-@@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
- err = -ENODEV;
- break;
- }
-+
-+ /* Some ACPI tables contain duplicate power resource references */
-+ if (acpi_power_resource_is_dup(package, start, i))
-+ continue;
-+
- err = acpi_add_power_resource(rhandle);
- if (err)
- break;
-diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
-index 94c837046786..57e3790c87b1 100644
---- a/drivers/i2c/i2c-dev.c
-+++ b/drivers/i2c/i2c-dev.c
-@@ -459,9 +459,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- return i2cdev_ioctl_smbus(client, arg);
-
- case I2C_RETRIES:
-+ if (arg > INT_MAX)
-+ return -EINVAL;
-+
- client->adapter->retries = arg;
- break;
- case I2C_TIMEOUT:
-+ if (arg > INT_MAX)
-+ return -EINVAL;
-+
- /* For historical reasons, user-space sets the timeout
- * value in units of 10 ms.
- */
-diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c
-index 99da549d5d06..0118287a8a10 100644
---- a/drivers/pci/host/pcie-altera.c
-+++ b/drivers/pci/host/pcie-altera.c
-@@ -40,8 +40,10 @@
- #define P2A_INT_ENABLE 0x3070
- #define P2A_INT_ENA_ALL 0xf
- #define RP_LTSSM 0x3c64
-+#define RP_LTSSM_MASK 0x1f
- #define LTSSM_L0 0xf
-
-+#define PCIE_CAP_OFFSET 0x80
- /* TLP configuration type 0 and 1 */
- #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */
- #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */
-@@ -60,6 +62,9 @@
- #define TLP_LOOP 500
- #define RP_DEVFN 0
-
-+#define LINK_UP_TIMEOUT HZ
-+#define LINK_RETRAIN_TIMEOUT HZ
-+
- #define INTX_NUM 4
-
- #define DWORD_MASK 3
-@@ -80,25 +85,21 @@ struct tlp_rp_regpair_t {
- u32 reg1;
- };
-
--static void altera_pcie_retrain(struct pci_dev *dev)
-+static inline void cra_writel(struct altera_pcie *pcie, const u32 value,
-+ const u32 reg)
- {
-- u16 linkcap, linkstat;
--
-- /*
-- * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
-- * current speed is 2.5 GB/s.
-- */
-- pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap);
-+ writel_relaxed(value, pcie->cra_base + reg);
-+}
-
-- if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
-- return;
-+static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg)
-+{
-+ return readl_relaxed(pcie->cra_base + reg);
-+}
-
-- pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat);
-- if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB)
-- pcie_capability_set_word(dev, PCI_EXP_LNKCTL,
-- PCI_EXP_LNKCTL_RL);
-+static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
-+{
-+ return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0);
- }
--DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain);
-
- /*
- * Altera PCIe port uses BAR0 of RC's configuration space as the translation
-@@ -119,17 +120,6 @@ static bool altera_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,
- return false;
- }
-
--static inline void cra_writel(struct altera_pcie *pcie, const u32 value,
-- const u32 reg)
--{
-- writel_relaxed(value, pcie->cra_base + reg);
--}
--
--static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg)
--{
-- return readl_relaxed(pcie->cra_base + reg);
--}
--
- static void tlp_write_tx(struct altera_pcie *pcie,
- struct tlp_rp_regpair_t *tlp_rp_regdata)
- {
-@@ -138,11 +128,6 @@ static void tlp_write_tx(struct altera_pcie *pcie,
- cra_writel(pcie, tlp_rp_regdata->ctrl, RP_TX_CNTRL);
- }
-
--static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
--{
-- return !!(cra_readl(pcie, RP_LTSSM) & LTSSM_L0);
--}
--
- static bool altera_pcie_valid_config(struct altera_pcie *pcie,
- struct pci_bus *bus, int dev)
- {
-@@ -286,22 +271,14 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn,
- return PCIBIOS_SUCCESSFUL;
- }
-
--static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
-- int where, int size, u32 *value)
-+static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno,
-+ unsigned int devfn, int where, int size,
-+ u32 *value)
- {
-- struct altera_pcie *pcie = bus->sysdata;
- int ret;
- u32 data;
- u8 byte_en;
-
-- if (altera_pcie_hide_rc_bar(bus, devfn, where))
-- return PCIBIOS_BAD_REGISTER_NUMBER;
--
-- if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
-- *value = 0xffffffff;
-- return PCIBIOS_DEVICE_NOT_FOUND;
-- }
--
- switch (size) {
- case 1:
- byte_en = 1 << (where & 3);
-@@ -314,7 +291,7 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
- break;
- }
-
-- ret = tlp_cfg_dword_read(pcie, bus->number, devfn,
-+ ret = tlp_cfg_dword_read(pcie, busno, devfn,
- (where & ~DWORD_MASK), byte_en, &data);
- if (ret != PCIBIOS_SUCCESSFUL)
- return ret;
-@@ -334,20 +311,14 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
- return PCIBIOS_SUCCESSFUL;
- }
-
--static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
-- int where, int size, u32 value)
-+static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno,
-+ unsigned int devfn, int where, int size,
-+ u32 value)
- {
-- struct altera_pcie *pcie = bus->sysdata;
- u32 data32;
- u32 shift = 8 * (where & 3);
- u8 byte_en;
-
-- if (altera_pcie_hide_rc_bar(bus, devfn, where))
-- return PCIBIOS_BAD_REGISTER_NUMBER;
--
-- if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
-- return PCIBIOS_DEVICE_NOT_FOUND;
--
- switch (size) {
- case 1:
- data32 = (value & 0xff) << shift;
-@@ -363,8 +334,40 @@ static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
- break;
- }
-
-- return tlp_cfg_dword_write(pcie, bus->number, devfn,
-- (where & ~DWORD_MASK), byte_en, data32);
-+ return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK),
-+ byte_en, data32);
-+}
-+
-+static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 *value)
-+{
-+ struct altera_pcie *pcie = bus->sysdata;
-+
-+ if (altera_pcie_hide_rc_bar(bus, devfn, where))
-+ return PCIBIOS_BAD_REGISTER_NUMBER;
-+
-+ if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) {
-+ *value = 0xffffffff;
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ }
-+
-+ return _altera_pcie_cfg_read(pcie, bus->number, devfn, where, size,
-+ value);
-+}
-+
-+static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 value)
-+{
-+ struct altera_pcie *pcie = bus->sysdata;
-+
-+ if (altera_pcie_hide_rc_bar(bus, devfn, where))
-+ return PCIBIOS_BAD_REGISTER_NUMBER;
-+
-+ if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn)))
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+ return _altera_pcie_cfg_write(pcie, bus->number, devfn, where, size,
-+ value);
- }
-
- static struct pci_ops altera_pcie_ops = {
-@@ -372,6 +375,90 @@ static struct pci_ops altera_pcie_ops = {
- .write = altera_pcie_cfg_write,
- };
-
-+static int altera_read_cap_word(struct altera_pcie *pcie, u8 busno,
-+ unsigned int devfn, int offset, u16 *value)
-+{
-+ u32 data;
-+ int ret;
-+
-+ ret = _altera_pcie_cfg_read(pcie, busno, devfn,
-+ PCIE_CAP_OFFSET + offset, sizeof(*value),
-+ &data);
-+ *value = data;
-+ return ret;
-+}
-+
-+static int altera_write_cap_word(struct altera_pcie *pcie, u8 busno,
-+ unsigned int devfn, int offset, u16 value)
-+{
-+ return _altera_pcie_cfg_write(pcie, busno, devfn,
-+ PCIE_CAP_OFFSET + offset, sizeof(value),
-+ value);
-+}
-+
-+static void altera_wait_link_retrain(struct altera_pcie *pcie)
-+{
-+ u16 reg16;
-+ unsigned long start_jiffies;
-+
-+ /* Wait for link training end. */
-+ start_jiffies = jiffies;
-+ for (;;) {
-+ altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
-+ PCI_EXP_LNKSTA, ®16);
-+ if (!(reg16 & PCI_EXP_LNKSTA_LT))
-+ break;
-+
-+ if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) {
-+ dev_err(&pcie->pdev->dev, "link retrain timeout\n");
-+ break;
-+ }
-+ udelay(100);
-+ }
-+
-+ /* Wait for link is up */
-+ start_jiffies = jiffies;
-+ for (;;) {
-+ if (altera_pcie_link_is_up(pcie))
-+ break;
-+
-+ if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) {
-+ dev_err(&pcie->pdev->dev, "link up timeout\n");
-+ break;
-+ }
-+ udelay(100);
-+ }
-+}
-+
-+static void altera_pcie_retrain(struct altera_pcie *pcie)
-+{
-+ u16 linkcap, linkstat, linkctl;
-+
-+ if (!altera_pcie_link_is_up(pcie))
-+ return;
-+
-+ /*
-+ * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but
-+ * current speed is 2.5 GB/s.
-+ */
-+ altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKCAP,
-+ &linkcap);
-+ if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB)
-+ return;
-+
-+ altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKSTA,
-+ &linkstat);
-+ if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) {
-+ altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
-+ PCI_EXP_LNKCTL, &linkctl);
-+ linkctl |= PCI_EXP_LNKCTL_RL;
-+ altera_write_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN,
-+ PCI_EXP_LNKCTL, linkctl);
-+
-+ altera_wait_link_retrain(pcie);
-+ }
-+}
-+
- static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
- {
-@@ -506,6 +593,11 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie)
- return 0;
- }
-
-+static void altera_pcie_host_init(struct altera_pcie *pcie)
-+{
-+ altera_pcie_retrain(pcie);
-+}
-+
- static int altera_pcie_probe(struct platform_device *pdev)
- {
- struct altera_pcie *pcie;
-@@ -543,6 +635,7 @@ static int altera_pcie_probe(struct platform_device *pdev)
- cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS);
- /* enable all interrupts */
- cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
-+ altera_pcie_host_init(pcie);
-
- bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops,
- pcie, &pcie->resources);
-diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
-index 3919ea066bf9..736de1021d8b 100644
---- a/drivers/usb/class/cdc-acm.c
-+++ b/drivers/usb/class/cdc-acm.c
-@@ -1885,6 +1885,13 @@ static const struct usb_device_id acm_ids[] = {
- .driver_info = IGNORE_DEVICE,
- },
-
-+ { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */
-+ .driver_info = SEND_ZERO_PACKET,
-+ },
-+ { USB_DEVICE(0x1bc7, 0x0023), /* Telit 3G ACM + ECM composition */
-+ .driver_info = SEND_ZERO_PACKET,
-+ },
-+
- /* control interfaces without any protocol set */
- { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
- USB_CDC_PROTO_NONE) },
-diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
-index cf378b1ed373..733479ddf8a7 100644
---- a/drivers/usb/core/quirks.c
-+++ b/drivers/usb/core/quirks.c
-@@ -240,7 +240,8 @@ static const struct usb_device_id usb_quirk_list[] = {
- USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
-
- /* Corsair K70 RGB */
-- { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
-+ { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT |
-+ USB_QUIRK_DELAY_CTRL_MSG },
-
- /* Corsair Strafe */
- { USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT |
-diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
-index 6c186b4df94a..b3344a77dcce 100644
---- a/drivers/usb/storage/scsiglue.c
-+++ b/drivers/usb/storage/scsiglue.c
-@@ -223,8 +223,12 @@ static int slave_configure(struct scsi_device *sdev)
- if (!(us->fflags & US_FL_NEEDS_CAP16))
- sdev->try_rc_10_first = 1;
-
-- /* assume SPC3 or latter devices support sense size > 18 */
-- if (sdev->scsi_level > SCSI_SPC_2)
-+ /*
-+ * assume SPC3 or latter devices support sense size > 18
-+ * unless US_FL_BAD_SENSE quirk is specified.
-+ */
-+ if (sdev->scsi_level > SCSI_SPC_2 &&
-+ !(us->fflags & US_FL_BAD_SENSE))
- us->fflags |= US_FL_SANE_SENSE;
-
- /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
-diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
-index 898215cad351..d92b974f0635 100644
---- a/drivers/usb/storage/unusual_devs.h
-+++ b/drivers/usb/storage/unusual_devs.h
-@@ -1392,6 +1392,18 @@ UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999,
- USB_SC_DEVICE, USB_PR_DEVICE, NULL,
- US_FL_SANE_SENSE),
-
-+/*
-+ * Reported by Icenowy Zheng
-+ * The SMI SM3350 USB-UFS bridge controller will enter a wrong state
-+ * that do not process read/write command if a long sense is requested,
-+ * so force to use 18-byte sense.
-+ */
-+UNUSUAL_DEV( 0x090c, 0x3350, 0x0000, 0xffff,
-+ "SMI",
-+ "SM3350 UFS-to-USB-Mass-Storage bridge",
-+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
-+ US_FL_BAD_SENSE ),
-+
- /*
- * Pete Zaitcev , bz#164688.
- * The device blatantly ignores LUN and returns 1 in GetMaxLUN.
-diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
-index 6d1d0b93b1aa..c792df826e12 100644
---- a/fs/btrfs/Makefile
-+++ b/fs/btrfs/Makefile
-@@ -9,7 +9,7 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
- export.o tree-log.o free-space-cache.o zlib.o lzo.o \
- compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \
- reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \
-- uuid-tree.o props.o hash.o
-+ uuid-tree.o props.o hash.o tree-checker.o
-
- btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o
- btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o
-diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
-index 38ee08675468..8f4baa3cb992 100644
---- a/fs/btrfs/ctree.c
-+++ b/fs/btrfs/ctree.c
-@@ -1726,20 +1726,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
- return err;
- }
-
--/*
-- * The leaf data grows from end-to-front in the node.
-- * this returns the address of the start of the last item,
-- * which is the stop of the leaf data stack
-- */
--static inline unsigned int leaf_data_end(struct btrfs_root *root,
-- struct extent_buffer *leaf)
--{
-- u32 nr = btrfs_header_nritems(leaf);
-- if (nr == 0)
-- return BTRFS_LEAF_DATA_SIZE(root);
-- return btrfs_item_offset_nr(leaf, nr - 1);
--}
--
-
- /*
- * search for key in the extent_buffer. The items start at offset p,
-diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
-index e847573c6db0..4a91d3119e59 100644
---- a/fs/btrfs/ctree.h
-+++ b/fs/btrfs/ctree.h
-@@ -35,6 +35,7 @@
- #include
- #include
- #include
-+#include
- #include "extent_io.h"
- #include "extent_map.h"
- #include "async-thread.h"
-@@ -897,6 +898,7 @@ struct btrfs_balance_item {
- #define BTRFS_FILE_EXTENT_INLINE 0
- #define BTRFS_FILE_EXTENT_REG 1
- #define BTRFS_FILE_EXTENT_PREALLOC 2
-+#define BTRFS_FILE_EXTENT_TYPES 2
-
- struct btrfs_file_extent_item {
- /*
-@@ -2283,7 +2285,7 @@ do { \
- #define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31)
-
- struct btrfs_map_token {
-- struct extent_buffer *eb;
-+ const struct extent_buffer *eb;
- char *kaddr;
- unsigned long offset;
- };
-@@ -2314,18 +2316,19 @@ static inline void btrfs_init_map_token (struct btrfs_map_token *token)
- sizeof(((type *)0)->member)))
-
- #define DECLARE_BTRFS_SETGET_BITS(bits) \
--u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
-- unsigned long off, \
-- struct btrfs_map_token *token); \
--void btrfs_set_token_##bits(struct extent_buffer *eb, void *ptr, \
-+u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
-+ const void *ptr, unsigned long off, \
-+ struct btrfs_map_token *token); \
-+void btrfs_set_token_##bits(struct extent_buffer *eb, const void *ptr, \
- unsigned long off, u##bits val, \
- struct btrfs_map_token *token); \
--static inline u##bits btrfs_get_##bits(struct extent_buffer *eb, void *ptr, \
-+static inline u##bits btrfs_get_##bits(const struct extent_buffer *eb, \
-+ const void *ptr, \
- unsigned long off) \
- { \
- return btrfs_get_token_##bits(eb, ptr, off, NULL); \
- } \
--static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr, \
-+static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr,\
- unsigned long off, u##bits val) \
- { \
- btrfs_set_token_##bits(eb, ptr, off, val, NULL); \
-@@ -2337,7 +2340,8 @@ DECLARE_BTRFS_SETGET_BITS(32)
- DECLARE_BTRFS_SETGET_BITS(64)
-
- #define BTRFS_SETGET_FUNCS(name, type, member, bits) \
--static inline u##bits btrfs_##name(struct extent_buffer *eb, type *s) \
-+static inline u##bits btrfs_##name(const struct extent_buffer *eb, \
-+ const type *s) \
- { \
- BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
- return btrfs_get_##bits(eb, s, offsetof(type, member)); \
-@@ -2348,7 +2352,8 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, type *s, \
- BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
- btrfs_set_##bits(eb, s, offsetof(type, member), val); \
- } \
--static inline u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, \
-+static inline u##bits btrfs_token_##name(const struct extent_buffer *eb,\
-+ const type *s, \
- struct btrfs_map_token *token) \
- { \
- BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
-@@ -2363,9 +2368,9 @@ static inline void btrfs_set_token_##name(struct extent_buffer *eb, \
- }
-
- #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \
--static inline u##bits btrfs_##name(struct extent_buffer *eb) \
-+static inline u##bits btrfs_##name(const struct extent_buffer *eb) \
- { \
-- type *p = page_address(eb->pages[0]); \
-+ const type *p = page_address(eb->pages[0]); \
- u##bits res = le##bits##_to_cpu(p->member); \
- return res; \
- } \
-@@ -2377,7 +2382,7 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \
- }
-
- #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \
--static inline u##bits btrfs_##name(type *s) \
-+static inline u##bits btrfs_##name(const type *s) \
- { \
- return le##bits##_to_cpu(s->member); \
- } \
-@@ -2678,7 +2683,7 @@ static inline unsigned long btrfs_node_key_ptr_offset(int nr)
- sizeof(struct btrfs_key_ptr) * nr;
- }
-
--void btrfs_node_key(struct extent_buffer *eb,
-+void btrfs_node_key(const struct extent_buffer *eb,
- struct btrfs_disk_key *disk_key, int nr);
-
- static inline void btrfs_set_node_key(struct extent_buffer *eb,
-@@ -2707,28 +2712,28 @@ static inline struct btrfs_item *btrfs_item_nr(int nr)
- return (struct btrfs_item *)btrfs_item_nr_offset(nr);
- }
-
--static inline u32 btrfs_item_end(struct extent_buffer *eb,
-+static inline u32 btrfs_item_end(const struct extent_buffer *eb,
- struct btrfs_item *item)
- {
- return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item);
- }
-
--static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr)
-+static inline u32 btrfs_item_end_nr(const struct extent_buffer *eb, int nr)
- {
- return btrfs_item_end(eb, btrfs_item_nr(nr));
- }
-
--static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr)
-+static inline u32 btrfs_item_offset_nr(const struct extent_buffer *eb, int nr)
- {
- return btrfs_item_offset(eb, btrfs_item_nr(nr));
- }
-
--static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr)
-+static inline u32 btrfs_item_size_nr(const struct extent_buffer *eb, int nr)
- {
- return btrfs_item_size(eb, btrfs_item_nr(nr));
- }
-
--static inline void btrfs_item_key(struct extent_buffer *eb,
-+static inline void btrfs_item_key(const struct extent_buffer *eb,
- struct btrfs_disk_key *disk_key, int nr)
- {
- struct btrfs_item *item = btrfs_item_nr(nr);
-@@ -2764,8 +2769,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_dir_name_len, struct btrfs_dir_item,
- BTRFS_SETGET_STACK_FUNCS(stack_dir_transid, struct btrfs_dir_item,
- transid, 64);
-
--static inline void btrfs_dir_item_key(struct extent_buffer *eb,
-- struct btrfs_dir_item *item,
-+static inline void btrfs_dir_item_key(const struct extent_buffer *eb,
-+ const struct btrfs_dir_item *item,
- struct btrfs_disk_key *key)
- {
- read_eb_member(eb, item, struct btrfs_dir_item, location, key);
-@@ -2773,7 +2778,7 @@ static inline void btrfs_dir_item_key(struct extent_buffer *eb,
-
- static inline void btrfs_set_dir_item_key(struct extent_buffer *eb,
- struct btrfs_dir_item *item,
-- struct btrfs_disk_key *key)
-+ const struct btrfs_disk_key *key)
- {
- write_eb_member(eb, item, struct btrfs_dir_item, location, key);
- }
-@@ -2785,8 +2790,8 @@ BTRFS_SETGET_FUNCS(free_space_bitmaps, struct btrfs_free_space_header,
- BTRFS_SETGET_FUNCS(free_space_generation, struct btrfs_free_space_header,
- generation, 64);
-
--static inline void btrfs_free_space_key(struct extent_buffer *eb,
-- struct btrfs_free_space_header *h,
-+static inline void btrfs_free_space_key(const struct extent_buffer *eb,
-+ const struct btrfs_free_space_header *h,
- struct btrfs_disk_key *key)
- {
- read_eb_member(eb, h, struct btrfs_free_space_header, location, key);
-@@ -2794,7 +2799,7 @@ static inline void btrfs_free_space_key(struct extent_buffer *eb,
-
- static inline void btrfs_set_free_space_key(struct extent_buffer *eb,
- struct btrfs_free_space_header *h,
-- struct btrfs_disk_key *key)
-+ const struct btrfs_disk_key *key)
- {
- write_eb_member(eb, h, struct btrfs_free_space_header, location, key);
- }
-@@ -2821,25 +2826,25 @@ static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk,
- disk->objectid = cpu_to_le64(cpu->objectid);
- }
-
--static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb,
-- struct btrfs_key *key, int nr)
-+static inline void btrfs_node_key_to_cpu(const struct extent_buffer *eb,
-+ struct btrfs_key *key, int nr)
- {
- struct btrfs_disk_key disk_key;
- btrfs_node_key(eb, &disk_key, nr);
- btrfs_disk_key_to_cpu(key, &disk_key);
- }
-
--static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb,
-- struct btrfs_key *key, int nr)
-+static inline void btrfs_item_key_to_cpu(const struct extent_buffer *eb,
-+ struct btrfs_key *key, int nr)
- {
- struct btrfs_disk_key disk_key;
- btrfs_item_key(eb, &disk_key, nr);
- btrfs_disk_key_to_cpu(key, &disk_key);
- }
-
--static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb,
-- struct btrfs_dir_item *item,
-- struct btrfs_key *key)
-+static inline void btrfs_dir_item_key_to_cpu(const struct extent_buffer *eb,
-+ const struct btrfs_dir_item *item,
-+ struct btrfs_key *key)
- {
- struct btrfs_disk_key disk_key;
- btrfs_dir_item_key(eb, item, &disk_key);
-@@ -2872,7 +2877,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_header_nritems, struct btrfs_header,
- nritems, 32);
- BTRFS_SETGET_STACK_FUNCS(stack_header_bytenr, struct btrfs_header, bytenr, 64);
-
--static inline int btrfs_header_flag(struct extent_buffer *eb, u64 flag)
-+static inline int btrfs_header_flag(const struct extent_buffer *eb, u64 flag)
- {
- return (btrfs_header_flags(eb) & flag) == flag;
- }
-@@ -2891,7 +2896,7 @@ static inline int btrfs_clear_header_flag(struct extent_buffer *eb, u64 flag)
- return (flags & flag) == flag;
- }
-
--static inline int btrfs_header_backref_rev(struct extent_buffer *eb)
-+static inline int btrfs_header_backref_rev(const struct extent_buffer *eb)
- {
- u64 flags = btrfs_header_flags(eb);
- return flags >> BTRFS_BACKREF_REV_SHIFT;
-@@ -2911,12 +2916,12 @@ static inline unsigned long btrfs_header_fsid(void)
- return offsetof(struct btrfs_header, fsid);
- }
-
--static inline unsigned long btrfs_header_chunk_tree_uuid(struct extent_buffer *eb)
-+static inline unsigned long btrfs_header_chunk_tree_uuid(const struct extent_buffer *eb)
- {
- return offsetof(struct btrfs_header, chunk_tree_uuid);
- }
-
--static inline int btrfs_is_leaf(struct extent_buffer *eb)
-+static inline int btrfs_is_leaf(const struct extent_buffer *eb)
- {
- return btrfs_header_level(eb) == 0;
- }
-@@ -2950,12 +2955,12 @@ BTRFS_SETGET_STACK_FUNCS(root_stransid, struct btrfs_root_item,
- BTRFS_SETGET_STACK_FUNCS(root_rtransid, struct btrfs_root_item,
- rtransid, 64);
-
--static inline bool btrfs_root_readonly(struct btrfs_root *root)
-+static inline bool btrfs_root_readonly(const struct btrfs_root *root)
- {
- return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
- }
-
--static inline bool btrfs_root_dead(struct btrfs_root *root)
-+static inline bool btrfs_root_dead(const struct btrfs_root *root)
- {
- return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0;
- }
-@@ -3012,51 +3017,51 @@ BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup,
- /* struct btrfs_balance_item */
- BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
-
--static inline void btrfs_balance_data(struct extent_buffer *eb,
-- struct btrfs_balance_item *bi,
-+static inline void btrfs_balance_data(const struct extent_buffer *eb,
-+ const struct btrfs_balance_item *bi,
- struct btrfs_disk_balance_args *ba)
- {
- read_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
- }
-
- static inline void btrfs_set_balance_data(struct extent_buffer *eb,
-- struct btrfs_balance_item *bi,
-- struct btrfs_disk_balance_args *ba)
-+ struct btrfs_balance_item *bi,
-+ const struct btrfs_disk_balance_args *ba)
- {
- write_eb_member(eb, bi, struct btrfs_balance_item, data, ba);
- }
-
--static inline void btrfs_balance_meta(struct extent_buffer *eb,
-- struct btrfs_balance_item *bi,
-+static inline void btrfs_balance_meta(const struct extent_buffer *eb,
-+ const struct btrfs_balance_item *bi,
- struct btrfs_disk_balance_args *ba)
- {
- read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
- }
-
- static inline void btrfs_set_balance_meta(struct extent_buffer *eb,
-- struct btrfs_balance_item *bi,
-- struct btrfs_disk_balance_args *ba)
-+ struct btrfs_balance_item *bi,
-+ const struct btrfs_disk_balance_args *ba)
- {
- write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba);
- }
-
--static inline void btrfs_balance_sys(struct extent_buffer *eb,
-- struct btrfs_balance_item *bi,
-+static inline void btrfs_balance_sys(const struct extent_buffer *eb,
-+ const struct btrfs_balance_item *bi,
- struct btrfs_disk_balance_args *ba)
- {
- read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
- }
-
- static inline void btrfs_set_balance_sys(struct extent_buffer *eb,
-- struct btrfs_balance_item *bi,
-- struct btrfs_disk_balance_args *ba)
-+ struct btrfs_balance_item *bi,
-+ const struct btrfs_disk_balance_args *ba)
- {
- write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba);
- }
-
- static inline void
- btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
-- struct btrfs_disk_balance_args *disk)
-+ const struct btrfs_disk_balance_args *disk)
- {
- memset(cpu, 0, sizeof(*cpu));
-
-@@ -3076,7 +3081,7 @@ btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
-
- static inline void
- btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
-- struct btrfs_balance_args *cpu)
-+ const struct btrfs_balance_args *cpu)
- {
- memset(disk, 0, sizeof(*disk));
-
-@@ -3144,7 +3149,7 @@ BTRFS_SETGET_STACK_FUNCS(super_magic, struct btrfs_super_block, magic, 64);
- BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block,
- uuid_tree_generation, 64);
-
--static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
-+static inline int btrfs_super_csum_size(const struct btrfs_super_block *s)
- {
- u16 t = btrfs_super_csum_type(s);
- /*
-@@ -3158,6 +3163,21 @@ static inline unsigned long btrfs_leaf_data(struct extent_buffer *l)
- return offsetof(struct btrfs_leaf, items);
- }
-
-+/*
-+ * The leaf data grows from end-to-front in the node.
-+ * this returns the address of the start of the last item,
-+ * which is the stop of the leaf data stack
-+ */
-+static inline unsigned int leaf_data_end(const struct btrfs_root *root,
-+ const struct extent_buffer *leaf)
-+{
-+ u32 nr = btrfs_header_nritems(leaf);
-+
-+ if (nr == 0)
-+ return BTRFS_LEAF_DATA_SIZE(root);
-+ return btrfs_item_offset_nr(leaf, nr - 1);
-+}
-+
- /* struct btrfs_file_extent_item */
- BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8);
- BTRFS_SETGET_STACK_FUNCS(stack_file_extent_disk_bytenr,
-@@ -3174,7 +3194,7 @@ BTRFS_SETGET_STACK_FUNCS(stack_file_extent_compression,
- struct btrfs_file_extent_item, compression, 8);
-
- static inline unsigned long
--btrfs_file_extent_inline_start(struct btrfs_file_extent_item *e)
-+btrfs_file_extent_inline_start(const struct btrfs_file_extent_item *e)
- {
- return (unsigned long)e + BTRFS_FILE_EXTENT_INLINE_DATA_START;
- }
-@@ -3208,8 +3228,9 @@ BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
- * size of any extent headers. If a file is compressed on disk, this is
- * the compressed size
- */
--static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
-- struct btrfs_item *e)
-+static inline u32 btrfs_file_extent_inline_item_len(
-+ const struct extent_buffer *eb,
-+ struct btrfs_item *e)
- {
- return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START;
- }
-@@ -3217,9 +3238,9 @@ static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
- /* this returns the number of file bytes represented by the inline item.
- * If an item is compressed, this is the uncompressed size
- */
--static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
-- int slot,
-- struct btrfs_file_extent_item *fi)
-+static inline u32 btrfs_file_extent_inline_len(const struct extent_buffer *eb,
-+ int slot,
-+ const struct btrfs_file_extent_item *fi)
- {
- struct btrfs_map_token token;
-
-@@ -3241,8 +3262,8 @@ static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
-
-
- /* btrfs_dev_stats_item */
--static inline u64 btrfs_dev_stats_value(struct extent_buffer *eb,
-- struct btrfs_dev_stats_item *ptr,
-+static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb,
-+ const struct btrfs_dev_stats_item *ptr,
- int index)
- {
- u64 val;
-diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
-index 176a27bc63aa..81e5bc62e8e3 100644
---- a/fs/btrfs/dev-replace.c
-+++ b/fs/btrfs/dev-replace.c
-@@ -620,7 +620,7 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
- em = lookup_extent_mapping(em_tree, start, (u64)-1);
- if (!em)
- break;
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- for (i = 0; i < map->num_stripes; i++)
- if (srcdev == map->stripes[i].dev)
- map->stripes[i].dev = tgtdev;
-diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
-index 1f21c6c33228..f80a0af68736 100644
---- a/fs/btrfs/disk-io.c
-+++ b/fs/btrfs/disk-io.c
-@@ -49,6 +49,7 @@
- #include "raid56.h"
- #include "sysfs.h"
- #include "qgroup.h"
-+#include "tree-checker.h"
-
- #ifdef CONFIG_X86
- #include
-@@ -522,72 +523,6 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
- return ret;
- }
-
--#define CORRUPT(reason, eb, root, slot) \
-- btrfs_crit(root->fs_info, "corrupt leaf, %s: block=%llu," \
-- "root=%llu, slot=%d", reason, \
-- btrfs_header_bytenr(eb), root->objectid, slot)
--
--static noinline int check_leaf(struct btrfs_root *root,
-- struct extent_buffer *leaf)
--{
-- struct btrfs_key key;
-- struct btrfs_key leaf_key;
-- u32 nritems = btrfs_header_nritems(leaf);
-- int slot;
--
-- if (nritems == 0)
-- return 0;
--
-- /* Check the 0 item */
-- if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
-- BTRFS_LEAF_DATA_SIZE(root)) {
-- CORRUPT("invalid item offset size pair", leaf, root, 0);
-- return -EIO;
-- }
--
-- /*
-- * Check to make sure each items keys are in the correct order and their
-- * offsets make sense. We only have to loop through nritems-1 because
-- * we check the current slot against the next slot, which verifies the
-- * next slot's offset+size makes sense and that the current's slot
-- * offset is correct.
-- */
-- for (slot = 0; slot < nritems - 1; slot++) {
-- btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
-- btrfs_item_key_to_cpu(leaf, &key, slot + 1);
--
-- /* Make sure the keys are in the right order */
-- if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
-- CORRUPT("bad key order", leaf, root, slot);
-- return -EIO;
-- }
--
-- /*
-- * Make sure the offset and ends are right, remember that the
-- * item data starts at the end of the leaf and grows towards the
-- * front.
-- */
-- if (btrfs_item_offset_nr(leaf, slot) !=
-- btrfs_item_end_nr(leaf, slot + 1)) {
-- CORRUPT("slot offset bad", leaf, root, slot);
-- return -EIO;
-- }
--
-- /*
-- * Check to make sure that we don't point outside of the leaf,
-- * just incase all the items are consistent to eachother, but
-- * all point outside of the leaf.
-- */
-- if (btrfs_item_end_nr(leaf, slot) >
-- BTRFS_LEAF_DATA_SIZE(root)) {
-- CORRUPT("slot end outside of leaf", leaf, root, slot);
-- return -EIO;
-- }
-- }
--
-- return 0;
--}
--
- static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
- u64 phy_offset, struct page *page,
- u64 start, u64 end, int mirror)
-@@ -654,11 +589,14 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
- * that we don't try and read the other copies of this block, just
- * return -EIO.
- */
-- if (found_level == 0 && check_leaf(root, eb)) {
-+ if (found_level == 0 && btrfs_check_leaf_full(root, eb)) {
- set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
- ret = -EIO;
- }
-
-+ if (found_level > 0 && btrfs_check_node(root, eb))
-+ ret = -EIO;
-+
- if (!ret)
- set_extent_buffer_uptodate(eb);
- err:
-@@ -3958,7 +3896,13 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
- buf->len,
- root->fs_info->dirty_metadata_batch);
- #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
-- if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) {
-+ /*
-+ * Since btrfs_mark_buffer_dirty() can be called with item pointer set
-+ * but item data not updated.
-+ * So here we should only check item pointers, not item data.
-+ */
-+ if (btrfs_header_level(buf) == 0 &&
-+ btrfs_check_leaf_relaxed(root, buf)) {
- btrfs_print_leaf(root, buf);
- ASSERT(0);
- }
-diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
-index 13ff0fdae03e..978bbfed5a2c 100644
---- a/fs/btrfs/extent-tree.c
-+++ b/fs/btrfs/extent-tree.c
-@@ -2342,7 +2342,13 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
- ins.type = BTRFS_EXTENT_ITEM_KEY;
- }
-
-- BUG_ON(node->ref_mod != 1);
-+ if (node->ref_mod != 1) {
-+ btrfs_err(root->fs_info,
-+ "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
-+ node->bytenr, node->ref_mod, node->action, ref_root,
-+ parent);
-+ return -EIO;
-+ }
- if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
- BUG_ON(!extent_op || !extent_op->update_flags);
- ret = alloc_reserved_tree_block(trans, root,
-@@ -9481,6 +9487,8 @@ static int find_first_block_group(struct btrfs_root *root,
- int ret = 0;
- struct btrfs_key found_key;
- struct extent_buffer *leaf;
-+ struct btrfs_block_group_item bg;
-+ u64 flags;
- int slot;
-
- ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
-@@ -9502,7 +9510,47 @@ static int find_first_block_group(struct btrfs_root *root,
-
- if (found_key.objectid >= key->objectid &&
- found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
-- ret = 0;
-+ struct extent_map_tree *em_tree;
-+ struct extent_map *em;
-+
-+ em_tree = &root->fs_info->mapping_tree.map_tree;
-+ read_lock(&em_tree->lock);
-+ em = lookup_extent_mapping(em_tree, found_key.objectid,
-+ found_key.offset);
-+ read_unlock(&em_tree->lock);
-+ if (!em) {
-+ btrfs_err(root->fs_info,
-+ "logical %llu len %llu found bg but no related chunk",
-+ found_key.objectid, found_key.offset);
-+ ret = -ENOENT;
-+ } else if (em->start != found_key.objectid ||
-+ em->len != found_key.offset) {
-+ btrfs_err(root->fs_info,
-+ "block group %llu len %llu mismatch with chunk %llu len %llu",
-+ found_key.objectid, found_key.offset,
-+ em->start, em->len);
-+ ret = -EUCLEAN;
-+ } else {
-+ read_extent_buffer(leaf, &bg,
-+ btrfs_item_ptr_offset(leaf, slot),
-+ sizeof(bg));
-+ flags = btrfs_block_group_flags(&bg) &
-+ BTRFS_BLOCK_GROUP_TYPE_MASK;
-+
-+ if (flags != (em->map_lookup->type &
-+ BTRFS_BLOCK_GROUP_TYPE_MASK)) {
-+ btrfs_err(root->fs_info,
-+"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx",
-+ found_key.objectid,
-+ found_key.offset, flags,
-+ (BTRFS_BLOCK_GROUP_TYPE_MASK &
-+ em->map_lookup->type));
-+ ret = -EUCLEAN;
-+ } else {
-+ ret = 0;
-+ }
-+ }
-+ free_extent_map(em);
- goto out;
- }
- path->slots[0]++;
-@@ -9717,6 +9765,62 @@ btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size)
- return cache;
- }
-
-+
-+/*
-+ * Iterate all chunks and verify that each of them has the corresponding block
-+ * group
-+ */
-+static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info)
-+{
-+ struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
-+ struct extent_map *em;
-+ struct btrfs_block_group_cache *bg;
-+ u64 start = 0;
-+ int ret = 0;
-+
-+ while (1) {
-+ read_lock(&map_tree->map_tree.lock);
-+ /*
-+ * lookup_extent_mapping will return the first extent map
-+ * intersecting the range, so setting @len to 1 is enough to
-+ * get the first chunk.
-+ */
-+ em = lookup_extent_mapping(&map_tree->map_tree, start, 1);
-+ read_unlock(&map_tree->map_tree.lock);
-+ if (!em)
-+ break;
-+
-+ bg = btrfs_lookup_block_group(fs_info, em->start);
-+ if (!bg) {
-+ btrfs_err(fs_info,
-+ "chunk start=%llu len=%llu doesn't have corresponding block group",
-+ em->start, em->len);
-+ ret = -EUCLEAN;
-+ free_extent_map(em);
-+ break;
-+ }
-+ if (bg->key.objectid != em->start ||
-+ bg->key.offset != em->len ||
-+ (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) !=
-+ (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
-+ btrfs_err(fs_info,
-+"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx",
-+ em->start, em->len,
-+ em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK,
-+ bg->key.objectid, bg->key.offset,
-+ bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK);
-+ ret = -EUCLEAN;
-+ free_extent_map(em);
-+ btrfs_put_block_group(bg);
-+ break;
-+ }
-+ start = em->start + em->len;
-+ free_extent_map(em);
-+ btrfs_put_block_group(bg);
-+ }
-+ return ret;
-+}
-+
- int btrfs_read_block_groups(struct btrfs_root *root)
- {
- struct btrfs_path *path;
-@@ -9903,7 +10007,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
- }
-
- init_global_block_rsv(info);
-- ret = 0;
-+ ret = check_chunk_block_group_mappings(info);
- error:
- btrfs_free_path(path);
- return ret;
-@@ -10388,7 +10492,7 @@ btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info,
- * more device items and remove one chunk item), but this is done at
- * btrfs_remove_chunk() through a call to check_system_chunk().
- */
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- num_items = 3 + map->num_stripes;
- free_extent_map(em);
-
-diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
-index 88bee6703cc0..42e7f6a8f91d 100644
---- a/fs/btrfs/extent_io.c
-+++ b/fs/btrfs/extent_io.c
-@@ -3847,8 +3847,10 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
- struct block_device *bdev = fs_info->fs_devices->latest_bdev;
- struct extent_io_tree *tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
- u64 offset = eb->start;
-+ u32 nritems;
- unsigned long i, num_pages;
- unsigned long bio_flags = 0;
-+ unsigned long start, end;
- int rw = (epd->sync_io ? WRITE_SYNC : WRITE) | REQ_META;
- int ret = 0;
-
-@@ -3858,6 +3860,23 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
- if (btrfs_header_owner(eb) == BTRFS_TREE_LOG_OBJECTID)
- bio_flags = EXTENT_BIO_TREE_LOG;
-
-+ /* set btree blocks beyond nritems with 0 to avoid stale content. */
-+ nritems = btrfs_header_nritems(eb);
-+ if (btrfs_header_level(eb) > 0) {
-+ end = btrfs_node_key_ptr_offset(nritems);
-+
-+ memset_extent_buffer(eb, 0, end, eb->len - end);
-+ } else {
-+ /*
-+ * leaf:
-+ * header 0 1 2 .. N ... data_N .. data_2 data_1 data_0
-+ */
-+ start = btrfs_item_nr_offset(nritems);
-+ end = btrfs_leaf_data(eb) +
-+ leaf_data_end(fs_info->tree_root, eb);
-+ memset_extent_buffer(eb, 0, start, end - start);
-+ }
-+
- for (i = 0; i < num_pages; i++) {
- struct page *p = eb->pages[i];
-
-@@ -5362,9 +5381,8 @@ unlock_exit:
- return ret;
- }
-
--void read_extent_buffer(struct extent_buffer *eb, void *dstv,
-- unsigned long start,
-- unsigned long len)
-+void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
-+ unsigned long start, unsigned long len)
- {
- size_t cur;
- size_t offset;
-@@ -5393,9 +5411,9 @@ void read_extent_buffer(struct extent_buffer *eb, void *dstv,
- }
- }
-
--int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
-- unsigned long start,
-- unsigned long len)
-+int read_extent_buffer_to_user(const struct extent_buffer *eb,
-+ void __user *dstv,
-+ unsigned long start, unsigned long len)
- {
- size_t cur;
- size_t offset;
-@@ -5430,10 +5448,10 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
- return ret;
- }
-
--int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
-- unsigned long min_len, char **map,
-- unsigned long *map_start,
-- unsigned long *map_len)
-+int map_private_extent_buffer(const struct extent_buffer *eb,
-+ unsigned long start, unsigned long min_len,
-+ char **map, unsigned long *map_start,
-+ unsigned long *map_len)
- {
- size_t offset = start & (PAGE_CACHE_SIZE - 1);
- char *kaddr;
-@@ -5468,9 +5486,8 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
- return 0;
- }
-
--int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
-- unsigned long start,
-- unsigned long len)
-+int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
-+ unsigned long start, unsigned long len)
- {
- size_t cur;
- size_t offset;
-diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
-index f4c1ae11855f..751435967724 100644
---- a/fs/btrfs/extent_io.h
-+++ b/fs/btrfs/extent_io.h
-@@ -308,14 +308,13 @@ static inline void extent_buffer_get(struct extent_buffer *eb)
- atomic_inc(&eb->refs);
- }
-
--int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
-- unsigned long start,
-- unsigned long len);
--void read_extent_buffer(struct extent_buffer *eb, void *dst,
-+int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
-+ unsigned long start, unsigned long len);
-+void read_extent_buffer(const struct extent_buffer *eb, void *dst,
- unsigned long start,
- unsigned long len);
--int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst,
-- unsigned long start,
-+int read_extent_buffer_to_user(const struct extent_buffer *eb,
-+ void __user *dst, unsigned long start,
- unsigned long len);
- void write_extent_buffer(struct extent_buffer *eb, const void *src,
- unsigned long start, unsigned long len);
-@@ -334,10 +333,10 @@ int set_extent_buffer_uptodate(struct extent_buffer *eb);
- int clear_extent_buffer_uptodate(struct extent_buffer *eb);
- int extent_buffer_uptodate(struct extent_buffer *eb);
- int extent_buffer_under_io(struct extent_buffer *eb);
--int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
-- unsigned long min_len, char **map,
-- unsigned long *map_start,
-- unsigned long *map_len);
-+int map_private_extent_buffer(const struct extent_buffer *eb,
-+ unsigned long offset, unsigned long min_len,
-+ char **map, unsigned long *map_start,
-+ unsigned long *map_len);
- int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
- int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
- int extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
-diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
-index 6a98bddd8f33..84fb56d5c018 100644
---- a/fs/btrfs/extent_map.c
-+++ b/fs/btrfs/extent_map.c
-@@ -76,7 +76,7 @@ void free_extent_map(struct extent_map *em)
- WARN_ON(extent_map_in_tree(em));
- WARN_ON(!list_empty(&em->list));
- if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags))
-- kfree(em->bdev);
-+ kfree(em->map_lookup);
- kmem_cache_free(extent_map_cache, em);
- }
- }
-diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
-index b2991fd8583e..eb8b8fae036b 100644
---- a/fs/btrfs/extent_map.h
-+++ b/fs/btrfs/extent_map.h
-@@ -32,7 +32,15 @@ struct extent_map {
- u64 block_len;
- u64 generation;
- unsigned long flags;
-- struct block_device *bdev;
-+ union {
-+ struct block_device *bdev;
-+
-+ /*
-+ * used for chunk mappings
-+ * flags & EXTENT_FLAG_FS_MAPPING must be set
-+ */
-+ struct map_lookup *map_lookup;
-+ };
- atomic_t refs;
- unsigned int compress_type;
- struct list_head list;
-diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
-index 6dca9f937bf6..cc9ccc42f469 100644
---- a/fs/btrfs/scrub.c
-+++ b/fs/btrfs/scrub.c
-@@ -3460,7 +3460,7 @@ static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx,
- return ret;
- }
-
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- if (em->start != chunk_offset)
- goto out;
-
-diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
-index b976597b0721..63ffd213b0b7 100644
---- a/fs/btrfs/struct-funcs.c
-+++ b/fs/btrfs/struct-funcs.c
-@@ -50,8 +50,8 @@ static inline void put_unaligned_le8(u8 val, void *p)
- */
-
- #define DEFINE_BTRFS_SETGET_BITS(bits) \
--u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
-- unsigned long off, \
-+u##bits btrfs_get_token_##bits(const struct extent_buffer *eb, \
-+ const void *ptr, unsigned long off, \
- struct btrfs_map_token *token) \
- { \
- unsigned long part_offset = (unsigned long)ptr; \
-@@ -90,7 +90,8 @@ u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
- return res; \
- } \
- void btrfs_set_token_##bits(struct extent_buffer *eb, \
-- void *ptr, unsigned long off, u##bits val, \
-+ const void *ptr, unsigned long off, \
-+ u##bits val, \
- struct btrfs_map_token *token) \
- { \
- unsigned long part_offset = (unsigned long)ptr; \
-@@ -133,7 +134,7 @@ DEFINE_BTRFS_SETGET_BITS(16)
- DEFINE_BTRFS_SETGET_BITS(32)
- DEFINE_BTRFS_SETGET_BITS(64)
-
--void btrfs_node_key(struct extent_buffer *eb,
-+void btrfs_node_key(const struct extent_buffer *eb,
- struct btrfs_disk_key *disk_key, int nr)
- {
- unsigned long ptr = btrfs_node_key_ptr_offset(nr);
-diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
-new file mode 100644
-index 000000000000..5b98f3c76ce4
---- /dev/null
-+++ b/fs/btrfs/tree-checker.c
-@@ -0,0 +1,649 @@
-+/*
-+ * Copyright (C) Qu Wenruo 2017. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public
-+ * License v2 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.
-+ */
-+
-+/*
-+ * The module is used to catch unexpected/corrupted tree block data.
-+ * Such behavior can be caused either by a fuzzed image or bugs.
-+ *
-+ * The objective is to do leaf/node validation checks when tree block is read
-+ * from disk, and check *every* possible member, so other code won't
-+ * need to checking them again.
-+ *
-+ * Due to the potential and unwanted damage, every checker needs to be
-+ * carefully reviewed otherwise so it does not prevent mount of valid images.
-+ */
-+
-+#include "ctree.h"
-+#include "tree-checker.h"
-+#include "disk-io.h"
-+#include "compression.h"
-+#include "hash.h"
-+#include "volumes.h"
-+
-+#define CORRUPT(reason, eb, root, slot) \
-+ btrfs_crit(root->fs_info, \
-+ "corrupt %s, %s: block=%llu, root=%llu, slot=%d", \
-+ btrfs_header_level(eb) == 0 ? "leaf" : "node", \
-+ reason, btrfs_header_bytenr(eb), root->objectid, slot)
-+
-+/*
-+ * Error message should follow the following format:
-+ * corrupt : , [, ]
-+ *
-+ * @type: leaf or node
-+ * @identifier: the necessary info to locate the leaf/node.
-+ * It's recommened to decode key.objecitd/offset if it's
-+ * meaningful.
-+ * @reason: describe the error
-+ * @bad_value: optional, it's recommened to output bad value and its
-+ * expected value (range).
-+ *
-+ * Since comma is used to separate the components, only space is allowed
-+ * inside each component.
-+ */
-+
-+/*
-+ * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt.
-+ * Allows callers to customize the output.
-+ */
-+__printf(4, 5)
-+static void generic_err(const struct btrfs_root *root,
-+ const struct extent_buffer *eb, int slot,
-+ const char *fmt, ...)
-+{
-+ struct va_format vaf;
-+ va_list args;
-+
-+ va_start(args, fmt);
-+
-+ vaf.fmt = fmt;
-+ vaf.va = &args;
-+
-+ btrfs_crit(root->fs_info,
-+ "corrupt %s: root=%llu block=%llu slot=%d, %pV",
-+ btrfs_header_level(eb) == 0 ? "leaf" : "node",
-+ root->objectid, btrfs_header_bytenr(eb), slot, &vaf);
-+ va_end(args);
-+}
-+
-+static int check_extent_data_item(struct btrfs_root *root,
-+ struct extent_buffer *leaf,
-+ struct btrfs_key *key, int slot)
-+{
-+ struct btrfs_file_extent_item *fi;
-+ u32 sectorsize = root->sectorsize;
-+ u32 item_size = btrfs_item_size_nr(leaf, slot);
-+
-+ if (!IS_ALIGNED(key->offset, sectorsize)) {
-+ CORRUPT("unaligned key offset for file extent",
-+ leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
-+
-+ if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) {
-+ CORRUPT("invalid file extent type", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ /*
-+ * Support for new compression/encrption must introduce incompat flag,
-+ * and must be caught in open_ctree().
-+ */
-+ if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) {
-+ CORRUPT("invalid file extent compression", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ if (btrfs_file_extent_encryption(leaf, fi)) {
-+ CORRUPT("invalid file extent encryption", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) {
-+ /* Inline extent must have 0 as key offset */
-+ if (key->offset) {
-+ CORRUPT("inline extent has non-zero key offset",
-+ leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ /* Compressed inline extent has no on-disk size, skip it */
-+ if (btrfs_file_extent_compression(leaf, fi) !=
-+ BTRFS_COMPRESS_NONE)
-+ return 0;
-+
-+ /* Uncompressed inline extent size must match item size */
-+ if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START +
-+ btrfs_file_extent_ram_bytes(leaf, fi)) {
-+ CORRUPT("plaintext inline extent has invalid size",
-+ leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ return 0;
-+ }
-+
-+ /* Regular or preallocated extent has fixed item size */
-+ if (item_size != sizeof(*fi)) {
-+ CORRUPT(
-+ "regluar or preallocated extent data item size is invalid",
-+ leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ if (!IS_ALIGNED(btrfs_file_extent_ram_bytes(leaf, fi), sectorsize) ||
-+ !IS_ALIGNED(btrfs_file_extent_disk_bytenr(leaf, fi), sectorsize) ||
-+ !IS_ALIGNED(btrfs_file_extent_disk_num_bytes(leaf, fi), sectorsize) ||
-+ !IS_ALIGNED(btrfs_file_extent_offset(leaf, fi), sectorsize) ||
-+ !IS_ALIGNED(btrfs_file_extent_num_bytes(leaf, fi), sectorsize)) {
-+ CORRUPT(
-+ "regular or preallocated extent data item has unaligned value",
-+ leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ return 0;
-+}
-+
-+static int check_csum_item(struct btrfs_root *root, struct extent_buffer *leaf,
-+ struct btrfs_key *key, int slot)
-+{
-+ u32 sectorsize = root->sectorsize;
-+ u32 csumsize = btrfs_super_csum_size(root->fs_info->super_copy);
-+
-+ if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) {
-+ CORRUPT("invalid objectid for csum item", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ if (!IS_ALIGNED(key->offset, sectorsize)) {
-+ CORRUPT("unaligned key offset for csum item", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) {
-+ CORRUPT("unaligned csum item size", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Customized reported for dir_item, only important new info is key->objectid,
-+ * which represents inode number
-+ */
-+__printf(4, 5)
-+static void dir_item_err(const struct btrfs_root *root,
-+ const struct extent_buffer *eb, int slot,
-+ const char *fmt, ...)
-+{
-+ struct btrfs_key key;
-+ struct va_format vaf;
-+ va_list args;
-+
-+ btrfs_item_key_to_cpu(eb, &key, slot);
-+ va_start(args, fmt);
-+
-+ vaf.fmt = fmt;
-+ vaf.va = &args;
-+
-+ btrfs_crit(root->fs_info,
-+ "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV",
-+ btrfs_header_level(eb) == 0 ? "leaf" : "node", root->objectid,
-+ btrfs_header_bytenr(eb), slot, key.objectid, &vaf);
-+ va_end(args);
-+}
-+
-+static int check_dir_item(struct btrfs_root *root,
-+ struct extent_buffer *leaf,
-+ struct btrfs_key *key, int slot)
-+{
-+ struct btrfs_dir_item *di;
-+ u32 item_size = btrfs_item_size_nr(leaf, slot);
-+ u32 cur = 0;
-+
-+ di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
-+ while (cur < item_size) {
-+ u32 name_len;
-+ u32 data_len;
-+ u32 max_name_len;
-+ u32 total_size;
-+ u32 name_hash;
-+ u8 dir_type;
-+
-+ /* header itself should not cross item boundary */
-+ if (cur + sizeof(*di) > item_size) {
-+ dir_item_err(root, leaf, slot,
-+ "dir item header crosses item boundary, have %zu boundary %u",
-+ cur + sizeof(*di), item_size);
-+ return -EUCLEAN;
-+ }
-+
-+ /* dir type check */
-+ dir_type = btrfs_dir_type(leaf, di);
-+ if (dir_type >= BTRFS_FT_MAX) {
-+ dir_item_err(root, leaf, slot,
-+ "invalid dir item type, have %u expect [0, %u)",
-+ dir_type, BTRFS_FT_MAX);
-+ return -EUCLEAN;
-+ }
-+
-+ if (key->type == BTRFS_XATTR_ITEM_KEY &&
-+ dir_type != BTRFS_FT_XATTR) {
-+ dir_item_err(root, leaf, slot,
-+ "invalid dir item type for XATTR key, have %u expect %u",
-+ dir_type, BTRFS_FT_XATTR);
-+ return -EUCLEAN;
-+ }
-+ if (dir_type == BTRFS_FT_XATTR &&
-+ key->type != BTRFS_XATTR_ITEM_KEY) {
-+ dir_item_err(root, leaf, slot,
-+ "xattr dir type found for non-XATTR key");
-+ return -EUCLEAN;
-+ }
-+ if (dir_type == BTRFS_FT_XATTR)
-+ max_name_len = XATTR_NAME_MAX;
-+ else
-+ max_name_len = BTRFS_NAME_LEN;
-+
-+ /* Name/data length check */
-+ name_len = btrfs_dir_name_len(leaf, di);
-+ data_len = btrfs_dir_data_len(leaf, di);
-+ if (name_len > max_name_len) {
-+ dir_item_err(root, leaf, slot,
-+ "dir item name len too long, have %u max %u",
-+ name_len, max_name_len);
-+ return -EUCLEAN;
-+ }
-+ if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)) {
-+ dir_item_err(root, leaf, slot,
-+ "dir item name and data len too long, have %u max %zu",
-+ name_len + data_len,
-+ BTRFS_MAX_XATTR_SIZE(root));
-+ return -EUCLEAN;
-+ }
-+
-+ if (data_len && dir_type != BTRFS_FT_XATTR) {
-+ dir_item_err(root, leaf, slot,
-+ "dir item with invalid data len, have %u expect 0",
-+ data_len);
-+ return -EUCLEAN;
-+ }
-+
-+ total_size = sizeof(*di) + name_len + data_len;
-+
-+ /* header and name/data should not cross item boundary */
-+ if (cur + total_size > item_size) {
-+ dir_item_err(root, leaf, slot,
-+ "dir item data crosses item boundary, have %u boundary %u",
-+ cur + total_size, item_size);
-+ return -EUCLEAN;
-+ }
-+
-+ /*
-+ * Special check for XATTR/DIR_ITEM, as key->offset is name
-+ * hash, should match its name
-+ */
-+ if (key->type == BTRFS_DIR_ITEM_KEY ||
-+ key->type == BTRFS_XATTR_ITEM_KEY) {
-+ char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
-+
-+ read_extent_buffer(leaf, namebuf,
-+ (unsigned long)(di + 1), name_len);
-+ name_hash = btrfs_name_hash(namebuf, name_len);
-+ if (key->offset != name_hash) {
-+ dir_item_err(root, leaf, slot,
-+ "name hash mismatch with key, have 0x%016x expect 0x%016llx",
-+ name_hash, key->offset);
-+ return -EUCLEAN;
-+ }
-+ }
-+ cur += total_size;
-+ di = (struct btrfs_dir_item *)((void *)di + total_size);
-+ }
-+ return 0;
-+}
-+
-+__printf(4, 5)
-+__cold
-+static void block_group_err(const struct btrfs_fs_info *fs_info,
-+ const struct extent_buffer *eb, int slot,
-+ const char *fmt, ...)
-+{
-+ struct btrfs_key key;
-+ struct va_format vaf;
-+ va_list args;
-+
-+ btrfs_item_key_to_cpu(eb, &key, slot);
-+ va_start(args, fmt);
-+
-+ vaf.fmt = fmt;
-+ vaf.va = &args;
-+
-+ btrfs_crit(fs_info,
-+ "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV",
-+ btrfs_header_level(eb) == 0 ? "leaf" : "node",
-+ btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot,
-+ key.objectid, key.offset, &vaf);
-+ va_end(args);
-+}
-+
-+static int check_block_group_item(struct btrfs_fs_info *fs_info,
-+ struct extent_buffer *leaf,
-+ struct btrfs_key *key, int slot)
-+{
-+ struct btrfs_block_group_item bgi;
-+ u32 item_size = btrfs_item_size_nr(leaf, slot);
-+ u64 flags;
-+ u64 type;
-+
-+ /*
-+ * Here we don't really care about alignment since extent allocator can
-+ * handle it. We care more about the size, as if one block group is
-+ * larger than maximum size, it's must be some obvious corruption.
-+ */
-+ if (key->offset > BTRFS_MAX_DATA_CHUNK_SIZE || key->offset == 0) {
-+ block_group_err(fs_info, leaf, slot,
-+ "invalid block group size, have %llu expect (0, %llu]",
-+ key->offset, BTRFS_MAX_DATA_CHUNK_SIZE);
-+ return -EUCLEAN;
-+ }
-+
-+ if (item_size != sizeof(bgi)) {
-+ block_group_err(fs_info, leaf, slot,
-+ "invalid item size, have %u expect %zu",
-+ item_size, sizeof(bgi));
-+ return -EUCLEAN;
-+ }
-+
-+ read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot),
-+ sizeof(bgi));
-+ if (btrfs_block_group_chunk_objectid(&bgi) !=
-+ BTRFS_FIRST_CHUNK_TREE_OBJECTID) {
-+ block_group_err(fs_info, leaf, slot,
-+ "invalid block group chunk objectid, have %llu expect %llu",
-+ btrfs_block_group_chunk_objectid(&bgi),
-+ BTRFS_FIRST_CHUNK_TREE_OBJECTID);
-+ return -EUCLEAN;
-+ }
-+
-+ if (btrfs_block_group_used(&bgi) > key->offset) {
-+ block_group_err(fs_info, leaf, slot,
-+ "invalid block group used, have %llu expect [0, %llu)",
-+ btrfs_block_group_used(&bgi), key->offset);
-+ return -EUCLEAN;
-+ }
-+
-+ flags = btrfs_block_group_flags(&bgi);
-+ if (hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1) {
-+ block_group_err(fs_info, leaf, slot,
-+"invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set",
-+ flags & BTRFS_BLOCK_GROUP_PROFILE_MASK,
-+ hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK));
-+ return -EUCLEAN;
-+ }
-+
-+ type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK;
-+ if (type != BTRFS_BLOCK_GROUP_DATA &&
-+ type != BTRFS_BLOCK_GROUP_METADATA &&
-+ type != BTRFS_BLOCK_GROUP_SYSTEM &&
-+ type != (BTRFS_BLOCK_GROUP_METADATA |
-+ BTRFS_BLOCK_GROUP_DATA)) {
-+ block_group_err(fs_info, leaf, slot,
-+"invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx",
-+ type, hweight64(type),
-+ BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA,
-+ BTRFS_BLOCK_GROUP_SYSTEM,
-+ BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA);
-+ return -EUCLEAN;
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * Common point to switch the item-specific validation.
-+ */
-+static int check_leaf_item(struct btrfs_root *root,
-+ struct extent_buffer *leaf,
-+ struct btrfs_key *key, int slot)
-+{
-+ int ret = 0;
-+
-+ switch (key->type) {
-+ case BTRFS_EXTENT_DATA_KEY:
-+ ret = check_extent_data_item(root, leaf, key, slot);
-+ break;
-+ case BTRFS_EXTENT_CSUM_KEY:
-+ ret = check_csum_item(root, leaf, key, slot);
-+ break;
-+ case BTRFS_DIR_ITEM_KEY:
-+ case BTRFS_DIR_INDEX_KEY:
-+ case BTRFS_XATTR_ITEM_KEY:
-+ ret = check_dir_item(root, leaf, key, slot);
-+ break;
-+ case BTRFS_BLOCK_GROUP_ITEM_KEY:
-+ ret = check_block_group_item(root->fs_info, leaf, key, slot);
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf,
-+ bool check_item_data)
-+{
-+ struct btrfs_fs_info *fs_info = root->fs_info;
-+ /* No valid key type is 0, so all key should be larger than this key */
-+ struct btrfs_key prev_key = {0, 0, 0};
-+ struct btrfs_key key;
-+ u32 nritems = btrfs_header_nritems(leaf);
-+ int slot;
-+
-+ if (btrfs_header_level(leaf) != 0) {
-+ generic_err(root, leaf, 0,
-+ "invalid level for leaf, have %d expect 0",
-+ btrfs_header_level(leaf));
-+ return -EUCLEAN;
-+ }
-+
-+ /*
-+ * Extent buffers from a relocation tree have a owner field that
-+ * corresponds to the subvolume tree they are based on. So just from an
-+ * extent buffer alone we can not find out what is the id of the
-+ * corresponding subvolume tree, so we can not figure out if the extent
-+ * buffer corresponds to the root of the relocation tree or not. So
-+ * skip this check for relocation trees.
-+ */
-+ if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) {
-+ u64 owner = btrfs_header_owner(leaf);
-+ struct btrfs_root *check_root;
-+
-+ /* These trees must never be empty */
-+ if (owner == BTRFS_ROOT_TREE_OBJECTID ||
-+ owner == BTRFS_CHUNK_TREE_OBJECTID ||
-+ owner == BTRFS_EXTENT_TREE_OBJECTID ||
-+ owner == BTRFS_DEV_TREE_OBJECTID ||
-+ owner == BTRFS_FS_TREE_OBJECTID ||
-+ owner == BTRFS_DATA_RELOC_TREE_OBJECTID) {
-+ generic_err(root, leaf, 0,
-+ "invalid root, root %llu must never be empty",
-+ owner);
-+ return -EUCLEAN;
-+ }
-+ key.objectid = owner;
-+ key.type = BTRFS_ROOT_ITEM_KEY;
-+ key.offset = (u64)-1;
-+
-+ check_root = btrfs_get_fs_root(fs_info, &key, false);
-+ /*
-+ * The only reason we also check NULL here is that during
-+ * open_ctree() some roots has not yet been set up.
-+ */
-+ if (!IS_ERR_OR_NULL(check_root)) {
-+ struct extent_buffer *eb;
-+
-+ eb = btrfs_root_node(check_root);
-+ /* if leaf is the root, then it's fine */
-+ if (leaf != eb) {
-+ CORRUPT("non-root leaf's nritems is 0",
-+ leaf, check_root, 0);
-+ free_extent_buffer(eb);
-+ return -EUCLEAN;
-+ }
-+ free_extent_buffer(eb);
-+ }
-+ return 0;
-+ }
-+
-+ if (nritems == 0)
-+ return 0;
-+
-+ /*
-+ * Check the following things to make sure this is a good leaf, and
-+ * leaf users won't need to bother with similar sanity checks:
-+ *
-+ * 1) key ordering
-+ * 2) item offset and size
-+ * No overlap, no hole, all inside the leaf.
-+ * 3) item content
-+ * If possible, do comprehensive sanity check.
-+ * NOTE: All checks must only rely on the item data itself.
-+ */
-+ for (slot = 0; slot < nritems; slot++) {
-+ u32 item_end_expected;
-+ int ret;
-+
-+ btrfs_item_key_to_cpu(leaf, &key, slot);
-+
-+ /* Make sure the keys are in the right order */
-+ if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
-+ CORRUPT("bad key order", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ /*
-+ * Make sure the offset and ends are right, remember that the
-+ * item data starts at the end of the leaf and grows towards the
-+ * front.
-+ */
-+ if (slot == 0)
-+ item_end_expected = BTRFS_LEAF_DATA_SIZE(root);
-+ else
-+ item_end_expected = btrfs_item_offset_nr(leaf,
-+ slot - 1);
-+ if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
-+ CORRUPT("slot offset bad", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ /*
-+ * Check to make sure that we don't point outside of the leaf,
-+ * just in case all the items are consistent to each other, but
-+ * all point outside of the leaf.
-+ */
-+ if (btrfs_item_end_nr(leaf, slot) >
-+ BTRFS_LEAF_DATA_SIZE(root)) {
-+ CORRUPT("slot end outside of leaf", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ /* Also check if the item pointer overlaps with btrfs item. */
-+ if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) >
-+ btrfs_item_ptr_offset(leaf, slot)) {
-+ CORRUPT("slot overlap with its data", leaf, root, slot);
-+ return -EUCLEAN;
-+ }
-+
-+ if (check_item_data) {
-+ /*
-+ * Check if the item size and content meet other
-+ * criteria
-+ */
-+ ret = check_leaf_item(root, leaf, &key, slot);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ prev_key.objectid = key.objectid;
-+ prev_key.type = key.type;
-+ prev_key.offset = key.offset;
-+ }
-+
-+ return 0;
-+}
-+
-+int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf)
-+{
-+ return check_leaf(root, leaf, true);
-+}
-+
-+int btrfs_check_leaf_relaxed(struct btrfs_root *root,
-+ struct extent_buffer *leaf)
-+{
-+ return check_leaf(root, leaf, false);
-+}
-+
-+int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node)
-+{
-+ unsigned long nr = btrfs_header_nritems(node);
-+ struct btrfs_key key, next_key;
-+ int slot;
-+ int level = btrfs_header_level(node);
-+ u64 bytenr;
-+ int ret = 0;
-+
-+ if (level <= 0 || level >= BTRFS_MAX_LEVEL) {
-+ generic_err(root, node, 0,
-+ "invalid level for node, have %d expect [1, %d]",
-+ level, BTRFS_MAX_LEVEL - 1);
-+ return -EUCLEAN;
-+ }
-+ if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
-+ btrfs_crit(root->fs_info,
-+"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%zu]",
-+ root->objectid, node->start,
-+ nr == 0 ? "small" : "large", nr,
-+ BTRFS_NODEPTRS_PER_BLOCK(root));
-+ return -EUCLEAN;
-+ }
-+
-+ for (slot = 0; slot < nr - 1; slot++) {
-+ bytenr = btrfs_node_blockptr(node, slot);
-+ btrfs_node_key_to_cpu(node, &key, slot);
-+ btrfs_node_key_to_cpu(node, &next_key, slot + 1);
-+
-+ if (!bytenr) {
-+ generic_err(root, node, slot,
-+ "invalid NULL node pointer");
-+ ret = -EUCLEAN;
-+ goto out;
-+ }
-+ if (!IS_ALIGNED(bytenr, root->sectorsize)) {
-+ generic_err(root, node, slot,
-+ "unaligned pointer, have %llu should be aligned to %u",
-+ bytenr, root->sectorsize);
-+ ret = -EUCLEAN;
-+ goto out;
-+ }
-+
-+ if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
-+ generic_err(root, node, slot,
-+ "bad key order, current (%llu %u %llu) next (%llu %u %llu)",
-+ key.objectid, key.type, key.offset,
-+ next_key.objectid, next_key.type,
-+ next_key.offset);
-+ ret = -EUCLEAN;
-+ goto out;
-+ }
-+ }
-+out:
-+ return ret;
-+}
-diff --git a/fs/btrfs/tree-checker.h b/fs/btrfs/tree-checker.h
-new file mode 100644
-index 000000000000..3d53e8d6fda0
---- /dev/null
-+++ b/fs/btrfs/tree-checker.h
-@@ -0,0 +1,38 @@
-+/*
-+ * Copyright (C) Qu Wenruo 2017. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public
-+ * License v2 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.
-+ */
-+
-+#ifndef __BTRFS_TREE_CHECKER__
-+#define __BTRFS_TREE_CHECKER__
-+
-+#include "ctree.h"
-+#include "extent_io.h"
-+
-+/*
-+ * Comprehensive leaf checker.
-+ * Will check not only the item pointers, but also every possible member
-+ * in item data.
-+ */
-+int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf);
-+
-+/*
-+ * Less strict leaf checker.
-+ * Will only check item pointers, not reading item data.
-+ */
-+int btrfs_check_leaf_relaxed(struct btrfs_root *root,
-+ struct extent_buffer *leaf);
-+int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node);
-+
-+#endif
-diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
-index b4d63a9842fa..5e8fe8f3942d 100644
---- a/fs/btrfs/volumes.c
-+++ b/fs/btrfs/volumes.c
-@@ -1184,7 +1184,7 @@ again:
- struct map_lookup *map;
- int i;
-
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- for (i = 0; i < map->num_stripes; i++) {
- u64 end;
-
-@@ -2757,7 +2757,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
- free_extent_map(em);
- return -EINVAL;
- }
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- lock_chunks(root->fs_info->chunk_root);
- check_system_chunk(trans, extent_root, map->type);
- unlock_chunks(root->fs_info->chunk_root);
-@@ -4540,7 +4540,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
-
- if (type & BTRFS_BLOCK_GROUP_DATA) {
- max_stripe_size = 1024 * 1024 * 1024;
-- max_chunk_size = 10 * max_stripe_size;
-+ max_chunk_size = BTRFS_MAX_DATA_CHUNK_SIZE;
- if (!devs_max)
- devs_max = BTRFS_MAX_DEVS(info->chunk_root);
- } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
-@@ -4731,7 +4731,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
- goto error;
- }
- set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
-- em->bdev = (struct block_device *)map;
-+ em->map_lookup = map;
- em->start = start;
- em->len = num_bytes;
- em->block_start = 0;
-@@ -4826,7 +4826,7 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
- return -EINVAL;
- }
-
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- item_size = btrfs_chunk_item_size(map->num_stripes);
- stripe_size = em->orig_block_len;
-
-@@ -4968,7 +4968,7 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset)
- if (!em)
- return 1;
-
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- for (i = 0; i < map->num_stripes; i++) {
- if (map->stripes[i].dev->missing) {
- miss_ndevs++;
-@@ -5048,7 +5048,7 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
- return 1;
- }
-
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1))
- ret = map->num_stripes;
- else if (map->type & BTRFS_BLOCK_GROUP_RAID10)
-@@ -5091,7 +5091,7 @@ unsigned long btrfs_full_stripe_len(struct btrfs_root *root,
- BUG_ON(!em);
-
- BUG_ON(em->start > logical || em->start + em->len < logical);
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
- len = map->stripe_len * nr_data_stripes(map);
- free_extent_map(em);
-@@ -5112,7 +5112,7 @@ int btrfs_is_parity_mirror(struct btrfs_mapping_tree *map_tree,
- BUG_ON(!em);
-
- BUG_ON(em->start > logical || em->start + em->len < logical);
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
- ret = 1;
- free_extent_map(em);
-@@ -5271,7 +5271,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
- return -EINVAL;
- }
-
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
- offset = logical - em->start;
-
- stripe_len = map->stripe_len;
-@@ -5813,7 +5813,7 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
- free_extent_map(em);
- return -EIO;
- }
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
-
- length = em->len;
- rmap_len = map->stripe_len;
-@@ -6208,6 +6208,101 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
- return dev;
- }
-
-+/* Return -EIO if any error, otherwise return 0. */
-+static int btrfs_check_chunk_valid(struct btrfs_root *root,
-+ struct extent_buffer *leaf,
-+ struct btrfs_chunk *chunk, u64 logical)
-+{
-+ u64 length;
-+ u64 stripe_len;
-+ u16 num_stripes;
-+ u16 sub_stripes;
-+ u64 type;
-+ u64 features;
-+ bool mixed = false;
-+
-+ length = btrfs_chunk_length(leaf, chunk);
-+ stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
-+ num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
-+ sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
-+ type = btrfs_chunk_type(leaf, chunk);
-+
-+ if (!num_stripes) {
-+ btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
-+ num_stripes);
-+ return -EIO;
-+ }
-+ if (!IS_ALIGNED(logical, root->sectorsize)) {
-+ btrfs_err(root->fs_info,
-+ "invalid chunk logical %llu", logical);
-+ return -EIO;
-+ }
-+ if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) {
-+ btrfs_err(root->fs_info, "invalid chunk sectorsize %u",
-+ btrfs_chunk_sector_size(leaf, chunk));
-+ return -EIO;
-+ }
-+ if (!length || !IS_ALIGNED(length, root->sectorsize)) {
-+ btrfs_err(root->fs_info,
-+ "invalid chunk length %llu", length);
-+ return -EIO;
-+ }
-+ if (!is_power_of_2(stripe_len)) {
-+ btrfs_err(root->fs_info, "invalid chunk stripe length: %llu",
-+ stripe_len);
-+ return -EIO;
-+ }
-+ if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
-+ type) {
-+ btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
-+ ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
-+ BTRFS_BLOCK_GROUP_PROFILE_MASK) &
-+ btrfs_chunk_type(leaf, chunk));
-+ return -EIO;
-+ }
-+
-+ if ((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0) {
-+ btrfs_err(root->fs_info, "missing chunk type flag: 0x%llx", type);
-+ return -EIO;
-+ }
-+
-+ if ((type & BTRFS_BLOCK_GROUP_SYSTEM) &&
-+ (type & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA))) {
-+ btrfs_err(root->fs_info,
-+ "system chunk with data or metadata type: 0x%llx", type);
-+ return -EIO;
-+ }
-+
-+ features = btrfs_super_incompat_flags(root->fs_info->super_copy);
-+ if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
-+ mixed = true;
-+
-+ if (!mixed) {
-+ if ((type & BTRFS_BLOCK_GROUP_METADATA) &&
-+ (type & BTRFS_BLOCK_GROUP_DATA)) {
-+ btrfs_err(root->fs_info,
-+ "mixed chunk type in non-mixed mode: 0x%llx", type);
-+ return -EIO;
-+ }
-+ }
-+
-+ if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
-+ (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
-+ (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
-+ (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
-+ (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) ||
-+ ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
-+ num_stripes != 1)) {
-+ btrfs_err(root->fs_info,
-+ "invalid num_stripes:sub_stripes %u:%u for profile %llu",
-+ num_stripes, sub_stripes,
-+ type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
-+ return -EIO;
-+ }
-+
-+ return 0;
-+}
-+
- static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
- struct extent_buffer *leaf,
- struct btrfs_chunk *chunk)
-@@ -6217,6 +6312,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
- struct extent_map *em;
- u64 logical;
- u64 length;
-+ u64 stripe_len;
- u64 devid;
- u8 uuid[BTRFS_UUID_SIZE];
- int num_stripes;
-@@ -6225,6 +6321,12 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
-
- logical = key->offset;
- length = btrfs_chunk_length(leaf, chunk);
-+ stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
-+ num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
-+
-+ ret = btrfs_check_chunk_valid(root, leaf, chunk, logical);
-+ if (ret)
-+ return ret;
-
- read_lock(&map_tree->map_tree.lock);
- em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
-@@ -6241,7 +6343,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
- em = alloc_extent_map();
- if (!em)
- return -ENOMEM;
-- num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
- map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
- if (!map) {
- free_extent_map(em);
-@@ -6249,7 +6350,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
- }
-
- set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
-- em->bdev = (struct block_device *)map;
-+ em->map_lookup = map;
- em->start = logical;
- em->len = length;
- em->orig_start = 0;
-@@ -6473,6 +6574,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
- u32 array_size;
- u32 len = 0;
- u32 cur_offset;
-+ u64 type;
- struct btrfs_key key;
-
- ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize);
-@@ -6539,6 +6641,15 @@ int btrfs_read_sys_array(struct btrfs_root *root)
- break;
- }
-
-+ type = btrfs_chunk_type(sb, chunk);
-+ if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
-+ btrfs_err(root->fs_info,
-+ "invalid chunk type %llu in sys_array at offset %u",
-+ type, cur_offset);
-+ ret = -EIO;
-+ break;
-+ }
-+
- len = btrfs_chunk_item_size(num_stripes);
- if (cur_offset + len > array_size)
- goto out_short_read;
-@@ -6948,7 +7059,7 @@ void btrfs_update_commit_device_bytes_used(struct btrfs_root *root,
- /* In order to kick the device replace finish process */
- lock_chunks(root);
- list_for_each_entry(em, &transaction->pending_chunks, list) {
-- map = (struct map_lookup *)em->bdev;
-+ map = em->map_lookup;
-
- for (i = 0; i < map->num_stripes; i++) {
- dev = map->stripes[i].dev;
-diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
-index d5c84f6b1353..3c651df420be 100644
---- a/fs/btrfs/volumes.h
-+++ b/fs/btrfs/volumes.h
-@@ -24,6 +24,8 @@
- #include
- #include "async-thread.h"
-
-+#define BTRFS_MAX_DATA_CHUNK_SIZE (10ULL * SZ_1G)
-+
- extern struct mutex uuid_mutex;
-
- #define BTRFS_STRIPE_LEN (64 * 1024)
-diff --git a/fs/cifs/file.c b/fs/cifs/file.c
-index 0141aba9eca6..026b399af215 100644
---- a/fs/cifs/file.c
-+++ b/fs/cifs/file.c
-@@ -1073,10 +1073,10 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
-- * and check it for zero before using.
-+ * and check it before using.
- */
- max_buf = tcon->ses->server->maxBuf;
-- if (!max_buf) {
-+ if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) {
- free_xid(xid);
- return -EINVAL;
- }
-@@ -1404,10 +1404,10 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
-- * and check it for zero before using.
-+ * and check it before using.
- */
- max_buf = tcon->ses->server->maxBuf;
-- if (!max_buf)
-+ if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE)))
- return -EINVAL;
-
- max_num = (max_buf - sizeof(struct smb_hdr)) /
-diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
-index b2aff0c6f22c..b7885dc0d9bb 100644
---- a/fs/cifs/smb2file.c
-+++ b/fs/cifs/smb2file.c
-@@ -123,10 +123,10 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
-
- /*
- * Accessing maxBuf is racy with cifs_reconnect - need to store value
-- * and check it for zero before using.
-+ * and check it before using.
- */
- max_buf = tcon->ses->server->maxBuf;
-- if (!max_buf)
-+ if (max_buf < sizeof(struct smb2_lock_element))
- return -EINVAL;
-
- max_num = max_buf / sizeof(struct smb2_lock_element);
-diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
-index 54af10204e83..1cf0a336ec06 100644
---- a/fs/cifs/transport.c
-+++ b/fs/cifs/transport.c
-@@ -360,7 +360,7 @@ uncork:
- if (rc < 0 && rc != -EINTR)
- cifs_dbg(VFS, "Error %d sending data on socket to server\n",
- rc);
-- else
-+ else if (rc > 0)
- rc = 0;
-
- return rc;
-diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
-index 46d4fac48cf4..0dcd33f62637 100644
---- a/fs/ext4/inline.c
-+++ b/fs/ext4/inline.c
-@@ -1861,12 +1861,12 @@ int ext4_inline_data_fiemap(struct inode *inode,
- physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;
- physical += offsetof(struct ext4_inode, i_block);
-
-- if (physical)
-- error = fiemap_fill_next_extent(fieinfo, start, physical,
-- inline_len, flags);
- brelse(iloc.bh);
- out:
- up_read(&EXT4_I(inode)->xattr_sem);
-+ if (physical)
-+ error = fiemap_fill_next_extent(fieinfo, start, physical,
-+ inline_len, flags);
- return (error < 0 ? error : 0);
- }
-
-diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
-index cc0fc712bb82..a8ac3f25b4ec 100644
---- a/include/linux/sunrpc/svc.h
-+++ b/include/linux/sunrpc/svc.h
-@@ -290,9 +290,12 @@ struct svc_rqst {
- struct svc_cacherep * rq_cacherep; /* cache info */
- struct task_struct *rq_task; /* service thread */
- spinlock_t rq_lock; /* per-request lock */
-+ struct net *rq_bc_net; /* pointer to backchannel's
-+ * net namespace
-+ */
- };
-
--#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net)
-+#define SVC_NET(rqst) (rqst->rq_xprt ? rqst->rq_xprt->xpt_net : rqst->rq_bc_net)
-
- /*
- * Rigorous type checking on sockaddr type conversions
-diff --git a/mm/slab.c b/mm/slab.c
-index fa49c01225a7..92df044f5e00 100644
---- a/mm/slab.c
-+++ b/mm/slab.c
-@@ -875,8 +875,10 @@ static struct alien_cache *__alloc_alien_cache(int node, int entries,
- struct alien_cache *alc = NULL;
-
- alc = kmalloc_node(memsize, gfp, node);
-- init_arraycache(&alc->ac, entries, batch);
-- spin_lock_init(&alc->lock);
-+ if (alc) {
-+ init_arraycache(&alc->ac, entries, batch);
-+ spin_lock_init(&alc->lock);
-+ }
- return alc;
- }
-
-diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
-index c5b0cb4f4056..41f6e964fe91 100644
---- a/net/sunrpc/svc.c
-+++ b/net/sunrpc/svc.c
-@@ -1062,6 +1062,8 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
- static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
- #endif
-
-+extern void svc_tcp_prep_reply_hdr(struct svc_rqst *);
-+
- /*
- * Common routine for processing the RPC request.
- */
-@@ -1091,7 +1093,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
- clear_bit(RQ_DROPME, &rqstp->rq_flags);
-
- /* Setup reply header */
-- rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
-+ if (rqstp->rq_prot == IPPROTO_TCP)
-+ svc_tcp_prep_reply_hdr(rqstp);
-
- svc_putu32(resv, rqstp->rq_xid);
-
-@@ -1138,7 +1141,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
- case SVC_DENIED:
- goto err_bad_auth;
- case SVC_CLOSE:
-- if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
-+ if (rqstp->rq_xprt &&
-+ test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
- svc_close_xprt(rqstp->rq_xprt);
- case SVC_DROP:
- goto dropit;
-@@ -1360,10 +1364,10 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
- dprintk("svc: %s(%p)\n", __func__, req);
-
- /* Build the svc_rqst used by the common processing routine */
-- rqstp->rq_xprt = serv->sv_bc_xprt;
- rqstp->rq_xid = req->rq_xid;
- rqstp->rq_prot = req->rq_xprt->prot;
- rqstp->rq_server = serv;
-+ rqstp->rq_bc_net = req->rq_xprt->xprt_net;
-
- rqstp->rq_addrlen = sizeof(req->rq_xprt->addr);
- memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
-diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
-index 71f15da72f02..2b8e80c721db 100644
---- a/net/sunrpc/svc_xprt.c
-+++ b/net/sunrpc/svc_xprt.c
-@@ -454,10 +454,11 @@ out:
- */
- void svc_reserve(struct svc_rqst *rqstp, int space)
- {
-+ struct svc_xprt *xprt = rqstp->rq_xprt;
-+
- space += rqstp->rq_res.head[0].iov_len;
-
-- if (space < rqstp->rq_reserved) {
-- struct svc_xprt *xprt = rqstp->rq_xprt;
-+ if (xprt && space < rqstp->rq_reserved) {
- atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved);
- rqstp->rq_reserved = space;
-
-diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
-index 9701fcca002c..0a9fe033132c 100644
---- a/net/sunrpc/svcsock.c
-+++ b/net/sunrpc/svcsock.c
-@@ -1240,7 +1240,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
- /*
- * Setup response header. TCP has a 4B record length field.
- */
--static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
-+void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
- {
- struct kvec *resv = &rqstp->rq_res.head[0];
-
-diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
-index 0467e5ba82e0..5d8ac2d798df 100644
---- a/sound/pci/hda/patch_realtek.c
-+++ b/sound/pci/hda/patch_realtek.c
-@@ -4792,6 +4792,13 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec,
- }
- }
-
-+static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
-+ const struct hda_fixup *fix, int action)
-+{
-+ if (action == HDA_FIXUP_ACT_PRE_PROBE)
-+ snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
-+}
-+
- /* for hda_fixup_thinkpad_acpi() */
- #include "thinkpad_helper.c"
-
-@@ -4891,6 +4898,7 @@ enum {
- ALC293_FIXUP_LENOVO_SPK_NOISE,
- ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
- ALC255_FIXUP_DELL_SPK_NOISE,
-+ ALC225_FIXUP_DISABLE_MIC_VREF,
- ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
- ALC295_FIXUP_DISABLE_DAC3,
- ALC280_FIXUP_HP_HEADSET_MIC,
-@@ -5546,6 +5554,12 @@ static const struct hda_fixup alc269_fixups[] = {
- .chained = true,
- .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
- },
-+ [ALC225_FIXUP_DISABLE_MIC_VREF] = {
-+ .type = HDA_FIXUP_FUNC,
-+ .v.func = alc_fixup_disable_mic_vref,
-+ .chained = true,
-+ .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
-+ },
- [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
- .type = HDA_FIXUP_VERBS,
- .v.verbs = (const struct hda_verb[]) {
-@@ -5555,7 +5569,7 @@ static const struct hda_fixup alc269_fixups[] = {
- {}
- },
- .chained = true,
-- .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
-+ .chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
- },
- [ALC280_FIXUP_HP_HEADSET_MIC] = {
- .type = HDA_FIXUP_FUNC,
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.171-172.patch b/patch/kernel/rk3399-default/04-patch-4.4.171-172.patch
deleted file mode 100644
index a01dcfe3e..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.171-172.patch
+++ /dev/null
@@ -1,1952 +0,0 @@
-diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
-index 6d2689ebf824..5b87946a53a3 100644
---- a/Documentation/filesystems/proc.txt
-+++ b/Documentation/filesystems/proc.txt
-@@ -466,7 +466,9 @@ manner. The codes are the following:
-
- Note that there is no guarantee that every flag and associated mnemonic will
- be present in all further kernel releases. Things get changed, the flags may
--be vanished or the reverse -- new added.
-+be vanished or the reverse -- new added. Interpretation of their meaning
-+might change in future as well. So each consumer of these flags has to
-+follow each specific kernel version for the exact semantic.
-
- This file is only present if the CONFIG_MMU kernel configuration option is
- enabled.
-diff --git a/Makefile b/Makefile
-index c6b680faedd8..2aa8db459a74 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 171
-+SUBLEVEL = 172
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
-index ef8e13d379cb..d7e7cf56e8d6 100644
---- a/arch/arm64/include/asm/kvm_arm.h
-+++ b/arch/arm64/include/asm/kvm_arm.h
-@@ -23,6 +23,8 @@
- #include
-
- /* Hyp Configuration Register (HCR) bits */
-+#define HCR_API (UL(1) << 41)
-+#define HCR_APK (UL(1) << 40)
- #define HCR_ID (UL(1) << 33)
- #define HCR_CD (UL(1) << 32)
- #define HCR_RW_SHIFT 31
-@@ -81,6 +83,7 @@
- HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
- #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
- #define HCR_INT_OVERRIDE (HCR_FMO | HCR_IMO)
-+#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
-
-
- /* Hyp System Control Register (SCTLR_EL2) bits */
-diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
-index d019c3a58cc2..0382eba4bf7b 100644
---- a/arch/arm64/kernel/head.S
-+++ b/arch/arm64/kernel/head.S
-@@ -30,6 +30,7 @@
- #include
- #include
- #include
-+#include
- #include
- #include
- #include
-@@ -464,7 +465,7 @@ CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
- ret
-
- /* Hyp configuration. */
--2: mov x0, #(1 << 31) // 64-bit EL1
-+2: mov_q x0, HCR_HOST_NVHE_FLAGS
- msr hcr_el2, x0
-
- /* Generic timers. */
-diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
-index 62d3dc60ca09..e99a0ed7e66b 100644
---- a/arch/arm64/kernel/perf_event.c
-+++ b/arch/arm64/kernel/perf_event.c
-@@ -670,6 +670,7 @@ static struct platform_driver armv8_pmu_driver = {
- .driver = {
- .name = "armv8-pmu",
- .of_match_table = armv8_pmu_of_device_ids,
-+ .suppress_bind_attrs = true,
- },
- .probe = armv8_pmu_device_probe,
- };
-diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
-index 8b0424abc84c..333ea0389adb 100644
---- a/arch/mips/Kconfig
-+++ b/arch/mips/Kconfig
-@@ -760,6 +760,7 @@ config SIBYTE_SWARM
- select SYS_SUPPORTS_HIGHMEM
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select ZONE_DMA32 if 64BIT
-+ select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
-
- config SIBYTE_LITTLESUR
- bool "Sibyte BCM91250C2-LittleSur"
-@@ -782,6 +783,7 @@ config SIBYTE_SENTOSA
- select SYS_HAS_CPU_SB1
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_LITTLE_ENDIAN
-+ select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
-
- config SIBYTE_BIGSUR
- bool "Sibyte BCM91480B-BigSur"
-@@ -795,6 +797,7 @@ config SIBYTE_BIGSUR
- select SYS_SUPPORTS_HIGHMEM
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select ZONE_DMA32 if 64BIT
-+ select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
-
- config SNI_RM
- bool "SNI RM200/300/400"
-@@ -2972,6 +2975,7 @@ config MIPS32_O32
- config MIPS32_N32
- bool "Kernel support for n32 binaries"
- depends on 64BIT
-+ select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
- select COMPAT
- select MIPS32_COMPAT
- select SYSVIPC_COMPAT if SYSVIPC
-diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
-index 2a5bb849b10e..288b58b00dc8 100644
---- a/arch/mips/pci/msi-octeon.c
-+++ b/arch/mips/pci/msi-octeon.c
-@@ -369,7 +369,9 @@ int __init octeon_msi_initialize(void)
- int irq;
- struct irq_chip *msi;
-
-- if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
-+ if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_INVALID) {
-+ return 0;
-+ } else if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
- msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0;
- msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1;
- msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2;
-diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile
-index b3d6bf23a662..3ef3fb658136 100644
---- a/arch/mips/sibyte/common/Makefile
-+++ b/arch/mips/sibyte/common/Makefile
-@@ -1,4 +1,5 @@
- obj-y := cfe.o
-+obj-$(CONFIG_SWIOTLB) += dma.o
- obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o
- obj-$(CONFIG_SIBYTE_CFE_CONSOLE) += cfe_console.o
- obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o
-diff --git a/arch/mips/sibyte/common/dma.c b/arch/mips/sibyte/common/dma.c
-new file mode 100644
-index 000000000000..eb47a94f3583
---- /dev/null
-+++ b/arch/mips/sibyte/common/dma.c
-@@ -0,0 +1,14 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * DMA support for Broadcom SiByte platforms.
-+ *
-+ * Copyright (c) 2018 Maciej W. Rozycki
-+ */
-+
-+#include
-+#include
-+
-+void __init plat_swiotlb_setup(void)
-+{
-+ swiotlb_init(1);
-+}
-diff --git a/crypto/authenc.c b/crypto/authenc.c
-index b7290c5b1eaa..5c25005ff398 100644
---- a/crypto/authenc.c
-+++ b/crypto/authenc.c
-@@ -58,14 +58,22 @@ int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
- return -EINVAL;
- if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
- return -EINVAL;
-- if (RTA_PAYLOAD(rta) < sizeof(*param))
-+
-+ /*
-+ * RTA_OK() didn't align the rtattr's payload when validating that it
-+ * fits in the buffer. Yet, the keys should start on the next 4-byte
-+ * aligned boundary. To avoid confusion, require that the rtattr
-+ * payload be exactly the param struct, which has a 4-byte aligned size.
-+ */
-+ if (RTA_PAYLOAD(rta) != sizeof(*param))
- return -EINVAL;
-+ BUILD_BUG_ON(sizeof(*param) % RTA_ALIGNTO);
-
- param = RTA_DATA(rta);
- keys->enckeylen = be32_to_cpu(param->enckeylen);
-
-- key += RTA_ALIGN(rta->rta_len);
-- keylen -= RTA_ALIGN(rta->rta_len);
-+ key += rta->rta_len;
-+ keylen -= rta->rta_len;
-
- if (keylen < keys->enckeylen)
- return -EINVAL;
-diff --git a/crypto/authencesn.c b/crypto/authencesn.c
-index fa0c4567f697..5fdf3e532310 100644
---- a/crypto/authencesn.c
-+++ b/crypto/authencesn.c
-@@ -276,7 +276,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
- struct aead_request *req = areq->data;
-
- err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
-- aead_request_complete(req, err);
-+ authenc_esn_request_complete(req, err);
- }
-
- static int crypto_authenc_esn_decrypt(struct aead_request *req)
-diff --git a/drivers/base/bus.c b/drivers/base/bus.c
-index 0346e46e2871..ecca4ae248e0 100644
---- a/drivers/base/bus.c
-+++ b/drivers/base/bus.c
-@@ -33,6 +33,9 @@ static struct kset *system_kset;
-
- #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
-
-+#define DRIVER_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
-+ struct driver_attribute driver_attr_##_name = \
-+ __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
-
- static int __must_check bus_rescan_devices_helper(struct device *dev,
- void *data);
-@@ -198,7 +201,7 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf,
- bus_put(bus);
- return err;
- }
--static DRIVER_ATTR_WO(unbind);
-+static DRIVER_ATTR_IGNORE_LOCKDEP(unbind, S_IWUSR, NULL, unbind_store);
-
- /*
- * Manually attach a device to a driver.
-@@ -234,7 +237,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
- bus_put(bus);
- return err;
- }
--static DRIVER_ATTR_WO(bind);
-+static DRIVER_ATTR_IGNORE_LOCKDEP(bind, S_IWUSR, NULL, bind_store);
-
- static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
- {
-diff --git a/drivers/block/loop.c b/drivers/block/loop.c
-index da3902ac16c8..b1cf891cb3d9 100644
---- a/drivers/block/loop.c
-+++ b/drivers/block/loop.c
-@@ -81,7 +81,7 @@
- #include
-
- static DEFINE_IDR(loop_index_idr);
--static DEFINE_MUTEX(loop_index_mutex);
-+static DEFINE_MUTEX(loop_ctl_mutex);
-
- static int max_part;
- static int part_shift;
-@@ -1044,7 +1044,7 @@ static int loop_clr_fd(struct loop_device *lo)
- */
- if (atomic_read(&lo->lo_refcnt) > 1) {
- lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
-- mutex_unlock(&lo->lo_ctl_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
- return 0;
- }
-
-@@ -1093,12 +1093,12 @@ static int loop_clr_fd(struct loop_device *lo)
- if (!part_shift)
- lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
- loop_unprepare_queue(lo);
-- mutex_unlock(&lo->lo_ctl_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
- /*
-- * Need not hold lo_ctl_mutex to fput backing file.
-- * Calling fput holding lo_ctl_mutex triggers a circular
-+ * Need not hold loop_ctl_mutex to fput backing file.
-+ * Calling fput holding loop_ctl_mutex triggers a circular
- * lock dependency possibility warning as fput can take
-- * bd_mutex which is usually taken before lo_ctl_mutex.
-+ * bd_mutex which is usually taken before loop_ctl_mutex.
- */
- fput(filp);
- return 0;
-@@ -1361,7 +1361,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
- struct loop_device *lo = bdev->bd_disk->private_data;
- int err;
-
-- mutex_lock_nested(&lo->lo_ctl_mutex, 1);
-+ mutex_lock_nested(&loop_ctl_mutex, 1);
- switch (cmd) {
- case LOOP_SET_FD:
- err = loop_set_fd(lo, mode, bdev, arg);
-@@ -1370,7 +1370,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
- err = loop_change_fd(lo, bdev, arg);
- break;
- case LOOP_CLR_FD:
-- /* loop_clr_fd would have unlocked lo_ctl_mutex on success */
-+ /* loop_clr_fd would have unlocked loop_ctl_mutex on success */
- err = loop_clr_fd(lo);
- if (!err)
- goto out_unlocked;
-@@ -1406,7 +1406,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
- default:
- err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
- }
-- mutex_unlock(&lo->lo_ctl_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
-
- out_unlocked:
- return err;
-@@ -1539,16 +1539,16 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
-
- switch(cmd) {
- case LOOP_SET_STATUS:
-- mutex_lock(&lo->lo_ctl_mutex);
-+ mutex_lock(&loop_ctl_mutex);
- err = loop_set_status_compat(
- lo, (const struct compat_loop_info __user *) arg);
-- mutex_unlock(&lo->lo_ctl_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
- break;
- case LOOP_GET_STATUS:
-- mutex_lock(&lo->lo_ctl_mutex);
-+ mutex_lock(&loop_ctl_mutex);
- err = loop_get_status_compat(
- lo, (struct compat_loop_info __user *) arg);
-- mutex_unlock(&lo->lo_ctl_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
- break;
- case LOOP_SET_CAPACITY:
- case LOOP_CLR_FD:
-@@ -1570,9 +1570,11 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
- static int lo_open(struct block_device *bdev, fmode_t mode)
- {
- struct loop_device *lo;
-- int err = 0;
-+ int err;
-
-- mutex_lock(&loop_index_mutex);
-+ err = mutex_lock_killable(&loop_ctl_mutex);
-+ if (err)
-+ return err;
- lo = bdev->bd_disk->private_data;
- if (!lo) {
- err = -ENXIO;
-@@ -1581,18 +1583,20 @@ static int lo_open(struct block_device *bdev, fmode_t mode)
-
- atomic_inc(&lo->lo_refcnt);
- out:
-- mutex_unlock(&loop_index_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
- return err;
- }
-
--static void __lo_release(struct loop_device *lo)
-+static void lo_release(struct gendisk *disk, fmode_t mode)
- {
-+ struct loop_device *lo;
- int err;
-
-+ mutex_lock(&loop_ctl_mutex);
-+ lo = disk->private_data;
- if (atomic_dec_return(&lo->lo_refcnt))
-- return;
-+ goto out_unlock;
-
-- mutex_lock(&lo->lo_ctl_mutex);
- if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
- /*
- * In autoclear mode, stop the loop thread
-@@ -1609,14 +1613,8 @@ static void __lo_release(struct loop_device *lo)
- loop_flush(lo);
- }
-
-- mutex_unlock(&lo->lo_ctl_mutex);
--}
--
--static void lo_release(struct gendisk *disk, fmode_t mode)
--{
-- mutex_lock(&loop_index_mutex);
-- __lo_release(disk->private_data);
-- mutex_unlock(&loop_index_mutex);
-+out_unlock:
-+ mutex_unlock(&loop_ctl_mutex);
- }
-
- static const struct block_device_operations lo_fops = {
-@@ -1655,10 +1653,10 @@ static int unregister_transfer_cb(int id, void *ptr, void *data)
- struct loop_device *lo = ptr;
- struct loop_func_table *xfer = data;
-
-- mutex_lock(&lo->lo_ctl_mutex);
-+ mutex_lock(&loop_ctl_mutex);
- if (lo->lo_encryption == xfer)
- loop_release_xfer(lo);
-- mutex_unlock(&lo->lo_ctl_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
- return 0;
- }
-
-@@ -1820,7 +1818,6 @@ static int loop_add(struct loop_device **l, int i)
- if (!part_shift)
- disk->flags |= GENHD_FL_NO_PART_SCAN;
- disk->flags |= GENHD_FL_EXT_DEVT;
-- mutex_init(&lo->lo_ctl_mutex);
- atomic_set(&lo->lo_refcnt, 0);
- lo->lo_number = i;
- spin_lock_init(&lo->lo_lock);
-@@ -1899,7 +1896,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
- struct kobject *kobj;
- int err;
-
-- mutex_lock(&loop_index_mutex);
-+ mutex_lock(&loop_ctl_mutex);
- err = loop_lookup(&lo, MINOR(dev) >> part_shift);
- if (err < 0)
- err = loop_add(&lo, MINOR(dev) >> part_shift);
-@@ -1907,7 +1904,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
- kobj = NULL;
- else
- kobj = get_disk(lo->lo_disk);
-- mutex_unlock(&loop_index_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
-
- *part = 0;
- return kobj;
-@@ -1917,9 +1914,13 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
- unsigned long parm)
- {
- struct loop_device *lo;
-- int ret = -ENOSYS;
-+ int ret;
-+
-+ ret = mutex_lock_killable(&loop_ctl_mutex);
-+ if (ret)
-+ return ret;
-
-- mutex_lock(&loop_index_mutex);
-+ ret = -ENOSYS;
- switch (cmd) {
- case LOOP_CTL_ADD:
- ret = loop_lookup(&lo, parm);
-@@ -1933,19 +1934,15 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
- ret = loop_lookup(&lo, parm);
- if (ret < 0)
- break;
-- mutex_lock(&lo->lo_ctl_mutex);
- if (lo->lo_state != Lo_unbound) {
- ret = -EBUSY;
-- mutex_unlock(&lo->lo_ctl_mutex);
- break;
- }
- if (atomic_read(&lo->lo_refcnt) > 0) {
- ret = -EBUSY;
-- mutex_unlock(&lo->lo_ctl_mutex);
- break;
- }
- lo->lo_disk->private_data = NULL;
-- mutex_unlock(&lo->lo_ctl_mutex);
- idr_remove(&loop_index_idr, lo->lo_number);
- loop_remove(lo);
- break;
-@@ -1955,7 +1952,7 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
- break;
- ret = loop_add(&lo, -1);
- }
-- mutex_unlock(&loop_index_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
-
- return ret;
- }
-@@ -2038,10 +2035,10 @@ static int __init loop_init(void)
- THIS_MODULE, loop_probe, NULL, NULL);
-
- /* pre-create number of devices given by config or max_loop */
-- mutex_lock(&loop_index_mutex);
-+ mutex_lock(&loop_ctl_mutex);
- for (i = 0; i < nr; i++)
- loop_add(&lo, i);
-- mutex_unlock(&loop_index_mutex);
-+ mutex_unlock(&loop_ctl_mutex);
-
- printk(KERN_INFO "loop: module loaded\n");
- return 0;
-diff --git a/drivers/block/loop.h b/drivers/block/loop.h
-index 60f0fd2c0c65..a923e74495ce 100644
---- a/drivers/block/loop.h
-+++ b/drivers/block/loop.h
-@@ -55,7 +55,6 @@ struct loop_device {
-
- spinlock_t lo_lock;
- int lo_state;
-- struct mutex lo_ctl_mutex;
- struct kthread_worker worker;
- struct task_struct *worker_task;
- bool use_dio;
-diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
-index 7a2e23d6bfdd..b2da2382d544 100644
---- a/drivers/char/ipmi/ipmi_ssif.c
-+++ b/drivers/char/ipmi/ipmi_ssif.c
-@@ -637,8 +637,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
-
- /* Remove the multi-part read marker. */
- len -= 2;
-+ data += 2;
- for (i = 0; i < len; i++)
-- ssif_info->data[i] = data[i+2];
-+ ssif_info->data[i] = data[i];
- ssif_info->multi_len = len;
- ssif_info->multi_pos = 1;
-
-@@ -666,8 +667,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
- }
-
- blocknum = data[0];
-+ len--;
-+ data++;
-+
-+ if (blocknum != 0xff && len != 31) {
-+ /* All blocks but the last must have 31 data bytes. */
-+ result = -EIO;
-+ if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-+ pr_info("Received middle message <31\n");
-
-- if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
-+ goto continue_op;
-+ }
-+
-+ if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
- /* Received message too big, abort the operation. */
- result = -E2BIG;
- if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-@@ -676,16 +688,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
- goto continue_op;
- }
-
-- /* Remove the blocknum from the data. */
-- len--;
- for (i = 0; i < len; i++)
-- ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
-+ ssif_info->data[i + ssif_info->multi_len] = data[i];
- ssif_info->multi_len += len;
- if (blocknum == 0xff) {
- /* End of read */
- len = ssif_info->multi_len;
- data = ssif_info->data;
-- } else if (blocknum + 1 != ssif_info->multi_pos) {
-+ } else if (blocknum != ssif_info->multi_pos) {
- /*
- * Out of sequence block, just abort. Block
- * numbers start at zero for the second block,
-@@ -713,6 +723,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
- }
- }
-
-+ continue_op:
- if (result < 0) {
- ssif_inc_stat(ssif_info, receive_errors);
- } else {
-@@ -720,8 +731,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
- ssif_inc_stat(ssif_info, received_message_parts);
- }
-
--
-- continue_op:
- if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
- pr_info(PFX "DONE 1: state = %d, result=%d.\n",
- ssif_info->ssif_state, result);
-diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
-index a0df83e6b84b..46c05c9a9354 100644
---- a/drivers/clk/imx/clk-imx6q.c
-+++ b/drivers/clk/imx/clk-imx6q.c
-@@ -239,8 +239,12 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
- * lvds1_gate and lvds2_gate are pseudo-gates. Both can be
- * independently configured as clock inputs or outputs. We treat
- * the "output_enable" bit as a gate, even though it's really just
-- * enabling clock output.
-+ * enabling clock output. Initially the gate bits are cleared, as
-+ * otherwise the exclusive configuration gets locked in the setup done
-+ * by software running before the clock driver, with no way to change
-+ * it.
- */
-+ writel(readl(base + 0x160) & ~0x3c00, base + 0x160);
- clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12));
- clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13));
-
-diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
-index 07135e009d8b..601a6c3acc7f 100644
---- a/drivers/cpuidle/cpuidle-pseries.c
-+++ b/drivers/cpuidle/cpuidle-pseries.c
-@@ -240,7 +240,13 @@ static int pseries_idle_probe(void)
- return -ENODEV;
-
- if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
-- if (lppaca_shared_proc(get_lppaca())) {
-+ /*
-+ * Use local_paca instead of get_lppaca() since
-+ * preemption is not disabled, and it is not required in
-+ * fact, since lppaca_ptr does not need to be the value
-+ * associated to the current CPU, it can be from any CPU.
-+ */
-+ if (lppaca_shared_proc(local_paca->lppaca_ptr)) {
- cpuidle_state_table = shared_states;
- max_idle_state = ARRAY_SIZE(shared_states);
- } else {
-diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
-index 5ad036741b99..e449f22c8f29 100644
---- a/drivers/gpu/drm/drm_fb_helper.c
-+++ b/drivers/gpu/drm/drm_fb_helper.c
-@@ -1109,9 +1109,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
- struct drm_framebuffer *fb = fb_helper->fb;
- int depth;
-
-- if (var->pixclock != 0 || in_dbg_master())
-+ if (in_dbg_master())
- return -EINVAL;
-
-+ if (var->pixclock != 0) {
-+ DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
-+ var->pixclock = 0;
-+ }
-+
- /* Need to resize the fb object !!! */
- if (var->bits_per_pixel > fb->bits_per_pixel ||
- var->xres > fb->width || var->yres > fb->height ||
-diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
-index 54c308e6704f..04248394843e 100644
---- a/drivers/md/dm-kcopyd.c
-+++ b/drivers/md/dm-kcopyd.c
-@@ -55,15 +55,17 @@ struct dm_kcopyd_client {
- struct dm_kcopyd_throttle *throttle;
-
- /*
-- * We maintain three lists of jobs:
-+ * We maintain four lists of jobs:
- *
- * i) jobs waiting for pages
- * ii) jobs that have pages, and are waiting for the io to be issued.
-- * iii) jobs that have completed.
-+ * iii) jobs that don't need to do any IO and just run a callback
-+ * iv) jobs that have completed.
- *
-- * All three of these are protected by job_lock.
-+ * All four of these are protected by job_lock.
- */
- spinlock_t job_lock;
-+ struct list_head callback_jobs;
- struct list_head complete_jobs;
- struct list_head io_jobs;
- struct list_head pages_jobs;
-@@ -583,6 +585,7 @@ static void do_work(struct work_struct *work)
- struct dm_kcopyd_client *kc = container_of(work,
- struct dm_kcopyd_client, kcopyd_work);
- struct blk_plug plug;
-+ unsigned long flags;
-
- /*
- * The order that these are called is *very* important.
-@@ -591,6 +594,10 @@ static void do_work(struct work_struct *work)
- * list. io jobs call wake when they complete and it all
- * starts again.
- */
-+ spin_lock_irqsave(&kc->job_lock, flags);
-+ list_splice_tail_init(&kc->callback_jobs, &kc->complete_jobs);
-+ spin_unlock_irqrestore(&kc->job_lock, flags);
-+
- blk_start_plug(&plug);
- process_jobs(&kc->complete_jobs, kc, run_complete_job);
- process_jobs(&kc->pages_jobs, kc, run_pages_job);
-@@ -608,7 +615,7 @@ static void dispatch_job(struct kcopyd_job *job)
- struct dm_kcopyd_client *kc = job->kc;
- atomic_inc(&kc->nr_jobs);
- if (unlikely(!job->source.count))
-- push(&kc->complete_jobs, job);
-+ push(&kc->callback_jobs, job);
- else if (job->pages == &zero_page_list)
- push(&kc->io_jobs, job);
- else
-@@ -795,7 +802,7 @@ void dm_kcopyd_do_callback(void *j, int read_err, unsigned long write_err)
- job->read_err = read_err;
- job->write_err = write_err;
-
-- push(&kc->complete_jobs, job);
-+ push(&kc->callback_jobs, job);
- wake(kc);
- }
- EXPORT_SYMBOL(dm_kcopyd_do_callback);
-@@ -825,6 +832,7 @@ struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *thro
- return ERR_PTR(-ENOMEM);
-
- spin_lock_init(&kc->job_lock);
-+ INIT_LIST_HEAD(&kc->callback_jobs);
- INIT_LIST_HEAD(&kc->complete_jobs);
- INIT_LIST_HEAD(&kc->io_jobs);
- INIT_LIST_HEAD(&kc->pages_jobs);
-@@ -874,6 +882,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc)
- /* Wait for completion of all jobs submitted by this client. */
- wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
-
-+ BUG_ON(!list_empty(&kc->callback_jobs));
- BUG_ON(!list_empty(&kc->complete_jobs));
- BUG_ON(!list_empty(&kc->io_jobs));
- BUG_ON(!list_empty(&kc->pages_jobs));
-diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
-index e108deebbaaa..5d3797728b9c 100644
---- a/drivers/md/dm-snap.c
-+++ b/drivers/md/dm-snap.c
-@@ -19,6 +19,7 @@
- #include
- #include
- #include
-+#include
-
- #include "dm.h"
-
-@@ -105,6 +106,9 @@ struct dm_snapshot {
- /* The on disk metadata handler */
- struct dm_exception_store *store;
-
-+ /* Maximum number of in-flight COW jobs. */
-+ struct semaphore cow_count;
-+
- struct dm_kcopyd_client *kcopyd_client;
-
- /* Wait for events based on state_bits */
-@@ -145,6 +149,19 @@ struct dm_snapshot {
- #define RUNNING_MERGE 0
- #define SHUTDOWN_MERGE 1
-
-+/*
-+ * Maximum number of chunks being copied on write.
-+ *
-+ * The value was decided experimentally as a trade-off between memory
-+ * consumption, stalling the kernel's workqueues and maintaining a high enough
-+ * throughput.
-+ */
-+#define DEFAULT_COW_THRESHOLD 2048
-+
-+static int cow_threshold = DEFAULT_COW_THRESHOLD;
-+module_param_named(snapshot_cow_threshold, cow_threshold, int, 0644);
-+MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write");
-+
- DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
- "A percentage of time allocated for copy on write");
-
-@@ -1190,6 +1207,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
- goto bad_hash_tables;
- }
-
-+ sema_init(&s->cow_count, (cow_threshold > 0) ? cow_threshold : INT_MAX);
-+
- s->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle);
- if (IS_ERR(s->kcopyd_client)) {
- r = PTR_ERR(s->kcopyd_client);
-@@ -1563,6 +1582,7 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
- }
- list_add(&pe->out_of_order_entry, lh);
- }
-+ up(&s->cow_count);
- }
-
- /*
-@@ -1586,6 +1606,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
- dest.count = src.count;
-
- /* Hand over to kcopyd */
-+ down(&s->cow_count);
- dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
- }
-
-@@ -1606,6 +1627,7 @@ static void start_full_bio(struct dm_snap_pending_exception *pe,
- pe->full_bio_end_io = bio->bi_end_io;
- pe->full_bio_private = bio->bi_private;
-
-+ down(&s->cow_count);
- callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client,
- copy_callback, pe);
-
-diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c
-index 251a556112a9..280b5ffea592 100644
---- a/drivers/media/firewire/firedtv-avc.c
-+++ b/drivers/media/firewire/firedtv-avc.c
-@@ -968,7 +968,8 @@ static int get_ca_object_length(struct avc_response_frame *r)
- return r->operand[7];
- }
-
--int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
-+int avc_ca_app_info(struct firedtv *fdtv, unsigned char *app_info,
-+ unsigned int *len)
- {
- struct avc_command_frame *c = (void *)fdtv->avc_data;
- struct avc_response_frame *r = (void *)fdtv->avc_data;
-@@ -1009,7 +1010,8 @@ out:
- return ret;
- }
-
--int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
-+int avc_ca_info(struct firedtv *fdtv, unsigned char *app_info,
-+ unsigned int *len)
- {
- struct avc_command_frame *c = (void *)fdtv->avc_data;
- struct avc_response_frame *r = (void *)fdtv->avc_data;
-diff --git a/drivers/media/firewire/firedtv.h b/drivers/media/firewire/firedtv.h
-index 345d1eda8c05..5b18a08c6285 100644
---- a/drivers/media/firewire/firedtv.h
-+++ b/drivers/media/firewire/firedtv.h
-@@ -124,8 +124,10 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
- struct dvb_diseqc_master_cmd *diseqcmd);
- void avc_remote_ctrl_work(struct work_struct *work);
- int avc_register_remote_control(struct firedtv *fdtv);
--int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
--int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
-+int avc_ca_app_info(struct firedtv *fdtv, unsigned char *app_info,
-+ unsigned int *len);
-+int avc_ca_info(struct firedtv *fdtv, unsigned char *app_info,
-+ unsigned int *len);
- int avc_ca_reset(struct firedtv *fdtv);
- int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
- int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
-diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
-index 83cc6d3b4784..81ba454a6d95 100644
---- a/drivers/media/platform/vivid/vivid-kthread-cap.c
-+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
-@@ -863,8 +863,11 @@ int vivid_start_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
- "%s-vid-cap", dev->v4l2_dev.name);
-
- if (IS_ERR(dev->kthread_vid_cap)) {
-+ int err = PTR_ERR(dev->kthread_vid_cap);
-+
-+ dev->kthread_vid_cap = NULL;
- v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
-- return PTR_ERR(dev->kthread_vid_cap);
-+ return err;
- }
- *pstreaming = true;
- vivid_grab_controls(dev, true);
-diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
-index c2c46dcdbe95..2c5dbdcb576a 100644
---- a/drivers/media/platform/vivid/vivid-kthread-out.c
-+++ b/drivers/media/platform/vivid/vivid-kthread-out.c
-@@ -248,8 +248,11 @@ int vivid_start_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
- "%s-vid-out", dev->v4l2_dev.name);
-
- if (IS_ERR(dev->kthread_vid_out)) {
-+ int err = PTR_ERR(dev->kthread_vid_out);
-+
-+ dev->kthread_vid_out = NULL;
- v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
-- return PTR_ERR(dev->kthread_vid_out);
-+ return err;
- }
- *pstreaming = true;
- vivid_grab_controls(dev, true);
-diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
-index 1678b730dba2..2e82f520a869 100644
---- a/drivers/media/platform/vivid/vivid-vid-common.c
-+++ b/drivers/media/platform/vivid/vivid-vid-common.c
-@@ -33,7 +33,7 @@ const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
- .type = V4L2_DV_BT_656_1120,
- /* keep this initialization for compatibility with GCC < 4.4.6 */
- .reserved = { 0 },
-- V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 14000000, 775000000,
-+ V4L2_INIT_BT_TIMINGS(16, MAX_WIDTH, 16, MAX_HEIGHT, 14000000, 775000000,
- V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
- V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
- V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
-diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
-index 6cfcdcea27e0..873948e429e8 100644
---- a/drivers/media/usb/em28xx/em28xx-video.c
-+++ b/drivers/media/usb/em28xx/em28xx-video.c
-@@ -930,6 +930,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
-
- em28xx_videodbg("%s\n", __func__);
-
-+ dev->v4l2->field_count = 0;
-+
- /* Make sure streaming is not already in progress for this type
- of filehandle (e.g. video, vbi) */
- rc = res_get(dev, vq->type);
-@@ -1149,8 +1151,6 @@ static void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
- {
- struct em28xx *dev = priv;
-
-- dev->v4l2->field_count = 0;
--
- /*
- * In the case of non-AC97 volume controls, we still need
- * to do some setups at em28xx, in order to mute/unmute
-diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
-index 8ce9c63dfc59..e0041fcfa783 100644
---- a/drivers/media/v4l2-core/videobuf2-core.c
-+++ b/drivers/media/v4l2-core/videobuf2-core.c
-@@ -1976,9 +1976,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
- return -EINVAL;
- }
- }
-+
-+ mutex_lock(&q->mmap_lock);
-+
- if (vb2_fileio_is_active(q)) {
- dprintk(1, "mmap: file io in progress\n");
-- return -EBUSY;
-+ ret = -EBUSY;
-+ goto unlock;
- }
-
- /*
-@@ -1986,7 +1990,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
- */
- ret = __find_plane_by_offset(q, off, &buffer, &plane);
- if (ret)
-- return ret;
-+ goto unlock;
-
- vb = q->bufs[buffer];
-
-@@ -1999,11 +2003,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
- if (length < (vma->vm_end - vma->vm_start)) {
- dprintk(1,
- "MMAP invalid, as it would overflow buffer length\n");
-- return -EINVAL;
-+ ret = -EINVAL;
-+ goto unlock;
- }
-
-- mutex_lock(&q->mmap_lock);
- ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);
-+
-+unlock:
- mutex_unlock(&q->mmap_lock);
- if (ret)
- return ret;
-diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
-index 5628a6b5b19b..c5c320efc7b4 100644
---- a/drivers/mfd/tps6586x.c
-+++ b/drivers/mfd/tps6586x.c
-@@ -594,6 +594,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
- return 0;
- }
-
-+static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
-+{
-+ struct tps6586x *tps6586x = dev_get_drvdata(dev);
-+
-+ if (tps6586x->client->irq)
-+ disable_irq(tps6586x->client->irq);
-+
-+ return 0;
-+}
-+
-+static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
-+{
-+ struct tps6586x *tps6586x = dev_get_drvdata(dev);
-+
-+ if (tps6586x->client->irq)
-+ enable_irq(tps6586x->client->irq);
-+
-+ return 0;
-+}
-+
-+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
-+ tps6586x_i2c_resume);
-+
- static const struct i2c_device_id tps6586x_id_table[] = {
- { "tps6586x", 0 },
- { },
-@@ -604,6 +627,7 @@ static struct i2c_driver tps6586x_driver = {
- .driver = {
- .name = "tps6586x",
- .of_match_table = of_match_ptr(tps6586x_of_match),
-+ .pm = &tps6586x_pm_ops,
- },
- .probe = tps6586x_i2c_probe,
- .remove = tps6586x_i2c_remove,
-diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
-index bf62e429f7fc..98be9eb3184b 100644
---- a/drivers/mmc/host/atmel-mci.c
-+++ b/drivers/mmc/host/atmel-mci.c
-@@ -1840,13 +1840,14 @@ static void atmci_tasklet_func(unsigned long priv)
- }
-
- atmci_request_end(host, host->mrq);
-- state = STATE_IDLE;
-+ goto unlock; /* atmci_request_end() sets host->state */
- break;
- }
- } while (state != prev_state);
-
- host->state = state;
-
-+unlock:
- spin_unlock(&host->lock);
- }
-
-diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
-index 25a0ad5102d6..855cf8c15c8a 100644
---- a/drivers/net/ethernet/intel/e1000e/ptp.c
-+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
-@@ -111,10 +111,14 @@ static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
- struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
- ptp_clock_info);
- unsigned long flags;
-- u64 ns;
-+ u64 cycles, ns;
-
- spin_lock_irqsave(&adapter->systim_lock, flags);
-- ns = timecounter_read(&adapter->tc);
-+
-+ /* Use timecounter_cyc2time() to allow non-monotonic SYSTIM readings */
-+ cycles = adapter->cc.read(&adapter->cc);
-+ ns = timecounter_cyc2time(&adapter->tc, cycles);
-+
- spin_unlock_irqrestore(&adapter->systim_lock, flags);
-
- *ts = ns_to_timespec64(ns);
-@@ -170,9 +174,12 @@ static void e1000e_systim_overflow_work(struct work_struct *work)
- systim_overflow_work.work);
- struct e1000_hw *hw = &adapter->hw;
- struct timespec64 ts;
-+ u64 ns;
-
-- adapter->ptp_clock_info.gettime64(&adapter->ptp_clock_info, &ts);
-+ /* Update the timecounter */
-+ ns = timecounter_read(&adapter->tc);
-
-+ ts = ns_to_timespec64(ns);
- e_dbg("SYSTIM overflow check at %lld.%09lu\n",
- (long long) ts.tv_sec, ts.tv_nsec);
-
-diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
-index 93543e176829..8f40e121f7d4 100644
---- a/drivers/net/ethernet/realtek/r8169.c
-+++ b/drivers/net/ethernet/realtek/r8169.c
-@@ -324,6 +324,8 @@ enum cfg_version {
- };
-
- static const struct pci_device_id rtl8169_pci_tbl[] = {
-+ { PCI_VDEVICE(REALTEK, 0x2502), RTL_CFG_1 },
-+ { PCI_VDEVICE(REALTEK, 0x2600), RTL_CFG_1 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x0000), 0, 0, RTL_CFG_1 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
-diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index f96f7b865267..7c1defaef3f5 100644
---- a/drivers/platform/x86/asus-wmi.c
-+++ b/drivers/platform/x86/asus-wmi.c
-@@ -2084,7 +2084,8 @@ static int asus_wmi_add(struct platform_device *pdev)
- err = asus_wmi_backlight_init(asus);
- if (err && err != -ENODEV)
- goto fail_backlight;
-- }
-+ } else
-+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
-
- status = wmi_install_notify_handler(asus->driver->event_guid,
- asus_wmi_notify, asus);
-diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
-index 741509b35617..14f32c114c55 100644
---- a/drivers/scsi/megaraid/megaraid_sas_fp.c
-+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
-@@ -1273,7 +1273,7 @@ void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map,
-
- for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
- ld = MR_TargetIdToLdGet(ldCount, drv_map);
-- if (ld >= MAX_LOGICAL_DRIVES_EXT) {
-+ if (ld >= MAX_LOGICAL_DRIVES_EXT - 1) {
- lbInfo[ldCount].loadBalanceFlag = 0;
- continue;
- }
-diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
-index 213944ed64d9..3d3bfa814093 100644
---- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
-+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
-@@ -1758,7 +1758,7 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
- device_id < instance->fw_supported_vd_count)) {
-
- ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
-- if (ld >= instance->fw_supported_vd_count)
-+ if (ld >= instance->fw_supported_vd_count - 1)
- fp_possible = 0;
-
- raid = MR_LdRaidGet(ld, local_map_ptr);
-diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
-index 6fffb73766de..ec80a0077ace 100644
---- a/drivers/scsi/sd.c
-+++ b/drivers/scsi/sd.c
-@@ -207,6 +207,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
- sp = buffer_data[0] & 0x80 ? 1 : 0;
- buffer_data[0] &= ~0x80;
-
-+ /*
-+ * Ensure WP, DPOFUA, and RESERVED fields are cleared in
-+ * received mode parameter buffer before doing MODE SELECT.
-+ */
-+ data.device_specific = 0;
-+
- if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
- SD_MAX_RETRIES, &data, &sshdr)) {
- if (scsi_sense_valid(&sshdr))
-diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
-index 9413e1a949e5..5af4d6a03d6e 100644
---- a/drivers/target/target_core_spc.c
-+++ b/drivers/target/target_core_spc.c
-@@ -108,12 +108,17 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
-
- buf[7] = 0x2; /* CmdQue=1 */
-
-- memcpy(&buf[8], "LIO-ORG ", 8);
-- memset(&buf[16], 0x20, 16);
-+ /*
-+ * ASCII data fields described as being left-aligned shall have any
-+ * unused bytes at the end of the field (i.e., highest offset) and the
-+ * unused bytes shall be filled with ASCII space characters (20h).
-+ */
-+ memset(&buf[8], 0x20, 8 + 16 + 4);
-+ memcpy(&buf[8], "LIO-ORG", sizeof("LIO-ORG") - 1);
- memcpy(&buf[16], dev->t10_wwn.model,
-- min_t(size_t, strlen(dev->t10_wwn.model), 16));
-+ strnlen(dev->t10_wwn.model, 16));
- memcpy(&buf[32], dev->t10_wwn.revision,
-- min_t(size_t, strlen(dev->t10_wwn.revision), 4));
-+ strnlen(dev->t10_wwn.revision, 4));
- buf[4] = 31; /* Set additional length to 31 */
-
- return 0;
-@@ -251,7 +256,9 @@ check_t10_vend_desc:
- buf[off] = 0x2; /* ASCII */
- buf[off+1] = 0x1; /* T10 Vendor ID */
- buf[off+2] = 0x0;
-- memcpy(&buf[off+4], "LIO-ORG", 8);
-+ /* left align Vendor ID and pad with spaces */
-+ memset(&buf[off+4], 0x20, 8);
-+ memcpy(&buf[off+4], "LIO-ORG", sizeof("LIO-ORG") - 1);
- /* Extra Byte for NULL Terminator */
- id_len++;
- /* Identifier Length */
-diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
-index ad7eba5ca380..34234c233851 100644
---- a/drivers/tty/tty_ldsem.c
-+++ b/drivers/tty/tty_ldsem.c
-@@ -307,6 +307,16 @@ down_write_failed(struct ld_semaphore *sem, long count, long timeout)
- if (!locked)
- ldsem_atomic_update(-LDSEM_WAIT_BIAS, sem);
- list_del(&waiter.list);
-+
-+ /*
-+ * In case of timeout, wake up every reader who gave the right of way
-+ * to writer. Prevent separation readers into two groups:
-+ * one that helds semaphore and another that sleeps.
-+ * (in case of no contention with a writer)
-+ */
-+ if (!locked && list_empty(&sem->write_wait))
-+ __ldsem_wake_readers(sem);
-+
- raw_spin_unlock_irq(&sem->wait_lock);
-
- __set_task_state(tsk, TASK_RUNNING);
-diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
-index 34ab4f950f0a..0c1c34ff40a9 100644
---- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
-+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
-@@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
-
- int r = 0;
-
-+ memset(&p, 0, sizeof(p));
-+
- switch (cmd) {
- case OMAPFB_SYNC_GFX:
- DBG("ioctl SYNC_GFX\n");
-diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
-index f80a0af68736..78722aaffecd 100644
---- a/fs/btrfs/disk-io.c
-+++ b/fs/btrfs/disk-io.c
-@@ -4111,6 +4111,14 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info)
- spin_lock(&fs_info->ordered_root_lock);
- }
- spin_unlock(&fs_info->ordered_root_lock);
-+
-+ /*
-+ * We need this here because if we've been flipped read-only we won't
-+ * get sync() from the umount, so we need to make sure any ordered
-+ * extents that haven't had their dirty pages IO start writeout yet
-+ * actually get run and error out properly.
-+ */
-+ btrfs_wait_ordered_roots(fs_info, -1);
- }
-
- static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
-diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
-index 1544f530ccd0..023e7f32ee1b 100644
---- a/fs/jffs2/super.c
-+++ b/fs/jffs2/super.c
-@@ -101,7 +101,8 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
- struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
-
- #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-- cancel_delayed_work_sync(&c->wbuf_dwork);
-+ if (jffs2_is_writebuffered(c))
-+ cancel_delayed_work_sync(&c->wbuf_dwork);
- #endif
-
- mutex_lock(&c->alloc_sem);
-diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
-index 0a4457fb0711..85111d740c9d 100644
---- a/fs/ocfs2/localalloc.c
-+++ b/fs/ocfs2/localalloc.c
-@@ -345,13 +345,18 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
- if (num_used
- || alloc->id1.bitmap1.i_used
- || alloc->id1.bitmap1.i_total
-- || la->la_bm_off)
-- mlog(ML_ERROR, "Local alloc hasn't been recovered!\n"
-+ || la->la_bm_off) {
-+ mlog(ML_ERROR, "inconsistent detected, clean journal with"
-+ " unrecovered local alloc, please run fsck.ocfs2!\n"
- "found = %u, set = %u, taken = %u, off = %u\n",
- num_used, le32_to_cpu(alloc->id1.bitmap1.i_used),
- le32_to_cpu(alloc->id1.bitmap1.i_total),
- OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
-
-+ status = -EINVAL;
-+ goto bail;
-+ }
-+
- osb->local_alloc_bh = alloc_bh;
- osb->local_alloc_state = OCFS2_LA_ENABLED;
-
-diff --git a/fs/proc/array.c b/fs/proc/array.c
-index cb71cbae606d..60cbaa821164 100644
---- a/fs/proc/array.c
-+++ b/fs/proc/array.c
-@@ -333,7 +333,7 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
- #ifdef CONFIG_SECCOMP
- seq_printf(m, "Seccomp:\t%d\n", p->seccomp.mode);
- #endif
-- seq_printf(m, "\nSpeculation_Store_Bypass:\t");
-+ seq_printf(m, "Speculation_Store_Bypass:\t");
- switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {
- case -EINVAL:
- seq_printf(m, "unknown");
-diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
-index bd21795ce657..679d75a864d0 100644
---- a/fs/pstore/ram_core.c
-+++ b/fs/pstore/ram_core.c
-@@ -445,6 +445,11 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
- sig ^= PERSISTENT_RAM_SIG;
-
- if (prz->buffer->sig == sig) {
-+ if (buffer_size(prz) == 0) {
-+ pr_debug("found existing empty buffer\n");
-+ return 0;
-+ }
-+
- if (buffer_size(prz) > prz->buffer_size ||
- buffer_start(prz) > buffer_size(prz))
- pr_info("found existing invalid buffer, size %zu, start %zu\n",
-diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
-index fb9636cc927c..5d8d12746e6e 100644
---- a/fs/xfs/libxfs/xfs_attr.c
-+++ b/fs/xfs/libxfs/xfs_attr.c
-@@ -528,7 +528,14 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
- if (args->flags & ATTR_CREATE)
- return retval;
- retval = xfs_attr_shortform_remove(args);
-- ASSERT(retval == 0);
-+ if (retval)
-+ return retval;
-+ /*
-+ * Since we have removed the old attr, clear ATTR_REPLACE so
-+ * that the leaf format add routine won't trip over the attr
-+ * not being around.
-+ */
-+ args->flags &= ~ATTR_REPLACE;
- }
-
- if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
-diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
-index a307c37c2e6c..072501a0ac86 100644
---- a/include/linux/backing-dev-defs.h
-+++ b/include/linux/backing-dev-defs.h
-@@ -225,6 +225,14 @@ static inline void wb_get(struct bdi_writeback *wb)
- */
- static inline void wb_put(struct bdi_writeback *wb)
- {
-+ if (WARN_ON_ONCE(!wb->bdi)) {
-+ /*
-+ * A driver bug might cause a file to be removed before bdi was
-+ * initialized.
-+ */
-+ return;
-+ }
-+
- if (wb != &wb->bdi->wb)
- percpu_ref_put(&wb->refcnt);
- }
-diff --git a/mm/page-writeback.c b/mm/page-writeback.c
-index 3309dbda7ffa..0bc7fa21db85 100644
---- a/mm/page-writeback.c
-+++ b/mm/page-writeback.c
-@@ -2151,6 +2151,7 @@ int write_cache_pages(struct address_space *mapping,
- {
- int ret = 0;
- int done = 0;
-+ int error;
- struct pagevec pvec;
- int nr_pages;
- pgoff_t uninitialized_var(writeback_index);
-@@ -2247,25 +2248,31 @@ continue_unlock:
- goto continue_unlock;
-
- trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
-- ret = (*writepage)(page, wbc, data);
-- if (unlikely(ret)) {
-- if (ret == AOP_WRITEPAGE_ACTIVATE) {
-+ error = (*writepage)(page, wbc, data);
-+ if (unlikely(error)) {
-+ /*
-+ * Handle errors according to the type of
-+ * writeback. There's no need to continue for
-+ * background writeback. Just push done_index
-+ * past this page so media errors won't choke
-+ * writeout for the entire file. For integrity
-+ * writeback, we must process the entire dirty
-+ * set regardless of errors because the fs may
-+ * still have state to clear for each page. In
-+ * that case we continue processing and return
-+ * the first error.
-+ */
-+ if (error == AOP_WRITEPAGE_ACTIVATE) {
- unlock_page(page);
-- ret = 0;
-- } else {
-- /*
-- * done_index is set past this page,
-- * so media errors will not choke
-- * background writeout for the entire
-- * file. This has consequences for
-- * range_cyclic semantics (ie. it may
-- * not be suitable for data integrity
-- * writeout).
-- */
-+ error = 0;
-+ } else if (wbc->sync_mode != WB_SYNC_ALL) {
-+ ret = error;
- done_index = page->index + 1;
- done = 1;
- break;
- }
-+ if (!ret)
-+ ret = error;
- }
-
- /*
-diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
-index 55dcb2b20b59..6def85d75b1d 100644
---- a/net/bridge/br_netfilter_hooks.c
-+++ b/net/bridge/br_netfilter_hooks.c
-@@ -267,7 +267,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
- struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
- int ret;
-
-- if (neigh->hh.hh_len) {
-+ if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) {
- neigh_hh_bridge(&neigh->hh, skb);
- skb->dev = nf_bridge->physindev;
- ret = br_handle_frame_finish(net, sk, skb);
-diff --git a/net/can/gw.c b/net/can/gw.c
-index 77c8af4047ef..81650affa3fa 100644
---- a/net/can/gw.c
-+++ b/net/can/gw.c
-@@ -418,13 +418,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
- while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
- (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
-
-- /* check for checksum updates when the CAN frame has been modified */
-+ /* Has the CAN frame been modified? */
- if (modidx) {
-- if (gwj->mod.csumfunc.crc8)
-+ /* get available space for the processed CAN frame type */
-+ int max_len = nskb->len - offsetof(struct can_frame, data);
-+
-+ /* dlc may have changed, make sure it fits to the CAN frame */
-+ if (cf->can_dlc > max_len)
-+ goto out_delete;
-+
-+ /* check for checksum updates in classic CAN length only */
-+ if (gwj->mod.csumfunc.crc8) {
-+ if (cf->can_dlc > 8)
-+ goto out_delete;
-+
- (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
-+ }
-+
-+ if (gwj->mod.csumfunc.xor) {
-+ if (cf->can_dlc > 8)
-+ goto out_delete;
-
-- if (gwj->mod.csumfunc.xor)
- (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
-+ }
- }
-
- /* clear the skb timestamp if not configured the other way */
-@@ -436,6 +452,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
- gwj->dropped_frames++;
- else
- gwj->handled_frames++;
-+
-+ return;
-+
-+ out_delete:
-+ /* delete frame due to misconfiguration */
-+ gwj->deleted_frames++;
-+ kfree_skb(nskb);
-+ return;
- }
-
- static inline int cgw_register_filter(struct cgw_job *gwj)
-diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 9703924ed071..8a57bbaf7452 100644
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -2388,12 +2388,15 @@ EXPORT_SYMBOL(skb_queue_purge);
- */
- void skb_rbtree_purge(struct rb_root *root)
- {
-- struct sk_buff *skb, *next;
-+ struct rb_node *p = rb_first(root);
-
-- rbtree_postorder_for_each_entry_safe(skb, next, root, rbnode)
-- kfree_skb(skb);
-+ while (p) {
-+ struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode);
-
-- *root = RB_ROOT;
-+ p = rb_next(p);
-+ rb_erase(&skb->rbnode, root);
-+ kfree_skb(skb);
-+ }
- }
-
- /**
-diff --git a/net/core/sock.c b/net/core/sock.c
-index 9fb1c073d0c4..8aa4a5f89572 100644
---- a/net/core/sock.c
-+++ b/net/core/sock.c
-@@ -732,6 +732,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
- break;
- case SO_DONTROUTE:
- sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
-+ sk_dst_reset(sk);
- break;
- case SO_BROADCAST:
- sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
-diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
-index 3f8caf7d19b8..1ea36bf778e6 100644
---- a/net/ipv4/ip_sockglue.c
-+++ b/net/ipv4/ip_sockglue.c
-@@ -133,19 +133,17 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
-
- static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
- {
-+ __be16 _ports[2], *ports;
- struct sockaddr_in sin;
-- __be16 *ports;
-- int end;
--
-- end = skb_transport_offset(skb) + 4;
-- if (end > 0 && !pskb_may_pull(skb, end))
-- return;
-
- /* All current transport protocols have the port numbers in the
- * first four bytes of the transport header and this function is
- * written with this assumption in mind.
- */
-- ports = (__be16 *)skb_transport_header(skb);
-+ ports = skb_header_pointer(skb, skb_transport_offset(skb),
-+ sizeof(_ports), &_ports);
-+ if (!ports)
-+ return;
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
-diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
-index 637a0e41b0aa..d6f2dab28d14 100644
---- a/net/ipv6/af_inet6.c
-+++ b/net/ipv6/af_inet6.c
-@@ -292,6 +292,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
-
- /* Check if the address belongs to the host. */
- if (addr_type == IPV6_ADDR_MAPPED) {
-+ struct net_device *dev = NULL;
- int chk_addr_ret;
-
- /* Binding to v4-mapped address on a v6-only socket
-@@ -302,9 +303,20 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- goto out;
- }
-
-+ rcu_read_lock();
-+ if (sk->sk_bound_dev_if) {
-+ dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
-+ if (!dev) {
-+ err = -ENODEV;
-+ goto out_unlock;
-+ }
-+ }
-+
- /* Reproduce AF_INET checks to make the bindings consistent */
- v4addr = addr->sin6_addr.s6_addr32[3];
-- chk_addr_ret = inet_addr_type(net, v4addr);
-+ chk_addr_ret = inet_addr_type_dev_table(net, dev, v4addr);
-+ rcu_read_unlock();
-+
- if (!net->ipv4.sysctl_ip_nonlocal_bind &&
- !(inet->freebind || inet->transparent) &&
- v4addr != htonl(INADDR_ANY) &&
-diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
-index 9f6e57ded338..27cdf543c539 100644
---- a/net/ipv6/datagram.c
-+++ b/net/ipv6/datagram.c
-@@ -290,6 +290,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
- skb_reset_network_header(skb);
- iph = ipv6_hdr(skb);
- iph->daddr = fl6->daddr;
-+ ip6_flow_hdr(iph, 0, 0);
-
- serr = SKB_EXT_ERR(skb);
- serr->ee.ee_errno = err;
-@@ -657,17 +658,15 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
- }
- if (np->rxopt.bits.rxorigdstaddr) {
- struct sockaddr_in6 sin6;
-- __be16 *ports;
-- int end;
-+ __be16 _ports[2], *ports;
-
-- end = skb_transport_offset(skb) + 4;
-- if (end <= 0 || pskb_may_pull(skb, end)) {
-+ ports = skb_header_pointer(skb, skb_transport_offset(skb),
-+ sizeof(_ports), &_ports);
-+ if (ports) {
- /* All current transport protocols have the port numbers in the
- * first four bytes of the transport header and this function is
- * written with this assumption in mind.
- */
-- ports = (__be16 *)skb_transport_header(skb);
--
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = ipv6_hdr(skb)->daddr;
- sin6.sin6_port = ports[1];
-diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
-index 0f50977ed53b..753b2837318d 100644
---- a/net/packet/af_packet.c
-+++ b/net/packet/af_packet.c
-@@ -2514,7 +2514,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
- addr = saddr->sll_halen ? saddr->sll_addr : NULL;
- dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
- if (addr && dev && saddr->sll_halen < dev->addr_len)
-- goto out;
-+ goto out_put;
- }
-
- err = -ENXIO;
-@@ -2683,7 +2683,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
- addr = saddr->sll_halen ? saddr->sll_addr : NULL;
- dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
- if (addr && dev && saddr->sll_halen < dev->addr_len)
-- goto out;
-+ goto out_unlock;
- }
-
- err = -ENXIO;
-diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
-index 7dffc97a953c..9fa0b0dc3868 100644
---- a/net/sctp/ipv6.c
-+++ b/net/sctp/ipv6.c
-@@ -97,11 +97,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
-
- switch (ev) {
- case NETDEV_UP:
-- addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
-+ addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
- if (addr) {
- addr->a.v6.sin6_family = AF_INET6;
-- addr->a.v6.sin6_port = 0;
-- addr->a.v6.sin6_flowinfo = 0;
- addr->a.v6.sin6_addr = ifa->addr;
- addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
- addr->valid = 1;
-@@ -412,7 +410,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
- addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
- if (addr) {
- addr->a.v6.sin6_family = AF_INET6;
-- addr->a.v6.sin6_port = 0;
- addr->a.v6.sin6_addr = ifp->addr;
- addr->a.v6.sin6_scope_id = dev->ifindex;
- addr->valid = 1;
-diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
-index dc030efa4447..9f2f3c48b7b6 100644
---- a/net/sctp/protocol.c
-+++ b/net/sctp/protocol.c
-@@ -151,7 +151,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
- addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
- if (addr) {
- addr->a.v4.sin_family = AF_INET;
-- addr->a.v4.sin_port = 0;
- addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
- addr->valid = 1;
- INIT_LIST_HEAD(&addr->list);
-@@ -775,10 +774,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
-
- switch (ev) {
- case NETDEV_UP:
-- addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
-+ addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
- if (addr) {
- addr->a.v4.sin_family = AF_INET;
-- addr->a.v4.sin_port = 0;
- addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
- addr->valid = 1;
- spin_lock_bh(&net->sctp.local_addr_lock);
-diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
-index cf5770d8f49a..c89626b2afff 100644
---- a/net/sunrpc/rpcb_clnt.c
-+++ b/net/sunrpc/rpcb_clnt.c
-@@ -772,6 +772,12 @@ void rpcb_getport_async(struct rpc_task *task)
- case RPCBVERS_3:
- map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID];
- map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC);
-+ if (!map->r_addr) {
-+ status = -ENOMEM;
-+ dprintk("RPC: %5u %s: no memory available\n",
-+ task->tk_pid, __func__);
-+ goto bailout_free_args;
-+ }
- map->r_owner = "";
- break;
- case RPCBVERS_2:
-@@ -794,6 +800,8 @@ void rpcb_getport_async(struct rpc_task *task)
- rpc_put_task(child);
- return;
-
-+bailout_free_args:
-+ kfree(map);
- bailout_release_client:
- rpc_release_client(rpcb_clnt);
- bailout_nofree:
-diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
-index f86c6555a539..e9653c42cdd1 100644
---- a/net/tipc/netlink_compat.c
-+++ b/net/tipc/netlink_compat.c
-@@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb)
- return limit;
- }
-
-+static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
-+{
-+ return TLV_GET_LEN(tlv) - TLV_SPACE(0);
-+}
-+
- static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
- {
- struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);
-@@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str)
- return buf;
- }
-
-+static inline bool string_is_valid(char *s, int len)
-+{
-+ return memchr(s, '\0', len) ? true : false;
-+}
-+
- static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
- struct tipc_nl_compat_msg *msg,
- struct sk_buff *arg)
-@@ -364,6 +374,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
- struct nlattr *prop;
- struct nlattr *bearer;
- struct tipc_bearer_config *b;
-+ int len;
-
- b = (struct tipc_bearer_config *)TLV_DATA(msg->req);
-
-@@ -371,6 +382,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
- if (!bearer)
- return -EMSGSIZE;
-
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
-+ if (!string_is_valid(b->name, len))
-+ return -EINVAL;
-+
- if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name))
- return -EMSGSIZE;
-
-@@ -396,6 +411,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
- {
- char *name;
- struct nlattr *bearer;
-+ int len;
-
- name = (char *)TLV_DATA(msg->req);
-
-@@ -403,6 +419,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
- if (!bearer)
- return -EMSGSIZE;
-
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
-+ if (!string_is_valid(name, len))
-+ return -EINVAL;
-+
- if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name))
- return -EMSGSIZE;
-
-@@ -462,6 +482,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
- struct nlattr *link[TIPC_NLA_LINK_MAX + 1];
- struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
- struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
-+ int len;
-
- nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL);
-
-@@ -472,6 +493,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
- NULL);
-
- name = (char *)TLV_DATA(msg->req);
-+
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
-+ if (!string_is_valid(name, len))
-+ return -EINVAL;
-+
- if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
- return 0;
-
-@@ -605,6 +631,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
- struct nlattr *prop;
- struct nlattr *media;
- struct tipc_link_config *lc;
-+ int len;
-
- lc = (struct tipc_link_config *)TLV_DATA(msg->req);
-
-@@ -612,6 +639,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
- if (!media)
- return -EMSGSIZE;
-
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
-+ if (!string_is_valid(lc->name, len))
-+ return -EINVAL;
-+
- if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
- return -EMSGSIZE;
-
-@@ -632,6 +663,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
- struct nlattr *prop;
- struct nlattr *bearer;
- struct tipc_link_config *lc;
-+ int len;
-
- lc = (struct tipc_link_config *)TLV_DATA(msg->req);
-
-@@ -639,6 +671,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
- if (!bearer)
- return -EMSGSIZE;
-
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
-+ if (!string_is_valid(lc->name, len))
-+ return -EINVAL;
-+
- if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
- return -EMSGSIZE;
-
-@@ -687,9 +723,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
- struct tipc_link_config *lc;
- struct tipc_bearer *bearer;
- struct tipc_media *media;
-+ int len;
-
- lc = (struct tipc_link_config *)TLV_DATA(msg->req);
-
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
-+ if (!string_is_valid(lc->name, len))
-+ return -EINVAL;
-+
- media = tipc_media_find(lc->name);
- if (media) {
- cmd->doit = &tipc_nl_media_set;
-@@ -711,6 +752,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
- {
- char *name;
- struct nlattr *link;
-+ int len;
-
- name = (char *)TLV_DATA(msg->req);
-
-@@ -718,6 +760,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
- if (!link)
- return -EMSGSIZE;
-
-+ len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
-+ if (!string_is_valid(name, len))
-+ return -EINVAL;
-+
- if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name))
- return -EMSGSIZE;
-
-@@ -739,6 +785,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg)
- };
-
- ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
-+ if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query))
-+ return -EINVAL;
-
- depth = ntohl(ntq->depth);
-
-@@ -1117,7 +1165,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
- }
-
- len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-- if (len && !TLV_OK(msg.req, len)) {
-+ if (!len || !TLV_OK(msg.req, len)) {
- msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
- err = -EOPNOTSUPP;
- goto send;
-diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
-index c410d257da06..0c7800112ff5 100644
---- a/scripts/kconfig/zconf.l
-+++ b/scripts/kconfig/zconf.l
-@@ -71,7 +71,7 @@ static void warn_ignored_character(char chr)
- {
- fprintf(stderr,
- "%s:%d:warning: ignoring unsupported character '%c'\n",
-- zconf_curname(), zconf_lineno(), chr);
-+ current_file->name, yylineno, chr);
- }
- %}
-
-@@ -191,6 +191,8 @@ n [A-Za-z0-9_-]
- }
- <> {
- BEGIN(INITIAL);
-+ yylval.string = text;
-+ return T_WORD_QUOTE;
- }
- }
-
-diff --git a/security/security.c b/security/security.c
-index 46f405ce6b0f..0dde287db5c5 100644
---- a/security/security.c
-+++ b/security/security.c
-@@ -861,6 +861,13 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
-
- void security_cred_free(struct cred *cred)
- {
-+ /*
-+ * There is a failure case in prepare_creds() that
-+ * may result in a call here with ->security being NULL.
-+ */
-+ if (unlikely(cred->security == NULL))
-+ return;
-+
- call_void_hook(cred_free, cred);
- }
-
-diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
-index 992a31530825..965a55eacaba 100644
---- a/security/selinux/ss/policydb.c
-+++ b/security/selinux/ss/policydb.c
-@@ -726,7 +726,8 @@ static int sens_destroy(void *key, void *datum, void *p)
- kfree(key);
- if (datum) {
- levdatum = datum;
-- ebitmap_destroy(&levdatum->level->cat);
-+ if (levdatum->level)
-+ ebitmap_destroy(&levdatum->level->cat);
- kfree(levdatum->level);
- }
- kfree(datum);
-diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
-index cb6ed10816d4..0a8808954bd8 100644
---- a/security/yama/yama_lsm.c
-+++ b/security/yama/yama_lsm.c
-@@ -288,7 +288,9 @@ static int yama_ptrace_access_check(struct task_struct *child,
- break;
- case YAMA_SCOPE_RELATIONAL:
- rcu_read_lock();
-- if (!task_is_descendant(current, child) &&
-+ if (!pid_alive(child))
-+ rc = -EPERM;
-+ if (!rc && !task_is_descendant(current, child) &&
- !ptracer_exception_found(current, child) &&
- !ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
- rc = -EPERM;
-diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
-index 091290d1f3ea..1898fa4228ad 100644
---- a/sound/firewire/bebob/bebob.c
-+++ b/sound/firewire/bebob/bebob.c
-@@ -382,7 +382,7 @@ static const struct ieee1394_device_id bebob_id_table[] = {
- /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */
- SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal),
- /* Apogee Electronics, Ensemble */
-- SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00001eee, &spec_normal),
-+ SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x01eeee, &spec_normal),
- /* ESI, Quatafire610 */
- SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal),
- /* AcousticReality, eARMasterOne */
-diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
-index c53f78767568..df21da796fa7 100644
---- a/tools/perf/arch/x86/util/intel-pt.c
-+++ b/tools/perf/arch/x86/util/intel-pt.c
-@@ -471,10 +471,21 @@ static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu,
- struct perf_evsel *evsel)
- {
- int err;
-+ char c;
-
- if (!evsel)
- return 0;
-
-+ /*
-+ * If supported, force pass-through config term (pt=1) even if user
-+ * sets pt=0, which avoids senseless kernel errors.
-+ */
-+ if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 &&
-+ !(evsel->attr.config & 1)) {
-+ pr_warning("pt=0 doesn't make sense, forcing pt=1\n");
-+ evsel->attr.config |= 1;
-+ }
-+
- err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds",
- "cyc_thresh", "caps/psb_cyc",
- evsel->attr.config);
-diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
-index e81dfb2e239c..9351738df703 100644
---- a/tools/perf/util/parse-events.c
-+++ b/tools/perf/util/parse-events.c
-@@ -1903,7 +1903,7 @@ restart:
- if (!name_only && strlen(syms->alias))
- snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
- else
-- strncpy(name, syms->symbol, MAX_NAME_LEN);
-+ strlcpy(name, syms->symbol, MAX_NAME_LEN);
-
- evt_list[evt_i] = strdup(name);
- if (evt_list[evt_i] == NULL)
-diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
-index eec6c1149f44..132878d4847a 100644
---- a/tools/perf/util/svghelper.c
-+++ b/tools/perf/util/svghelper.c
-@@ -333,7 +333,7 @@ static char *cpu_model(void)
- if (file) {
- while (fgets(buf, 255, file)) {
- if (strstr(buf, "model name")) {
-- strncpy(cpu_m, &buf[13], 255);
-+ strlcpy(cpu_m, &buf[13], 255);
- break;
- }
- }
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.172-173.patch b/patch/kernel/rk3399-default/04-patch-4.4.172-173.patch
deleted file mode 100644
index e1e72b435..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.172-173.patch
+++ /dev/null
@@ -1,1665 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 2aa8db459a74..db7665e32da8 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 172
-+SUBLEVEL = 173
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
-index 5f071762fb1c..6a2ae61748e4 100644
---- a/arch/arc/include/asm/perf_event.h
-+++ b/arch/arc/include/asm/perf_event.h
-@@ -103,7 +103,8 @@ static const char * const arc_pmu_ev_hw_map[] = {
-
- /* counts condition */
- [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
-- [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", /* Excludes ZOL jumps */
-+ /* All jump instructions that are taken */
-+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmptak",
- [PERF_COUNT_ARC_BPOK] = "bpok", /* NP-NT, PT-T, PNT-NT */
- #ifdef CONFIG_ISA_ARCV2
- [PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
-diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
-index 318394ed5c7a..5e11ad3164e0 100644
---- a/arch/arm/mach-cns3xxx/pcie.c
-+++ b/arch/arm/mach-cns3xxx/pcie.c
-@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
- } else /* remote PCI bus */
- base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
-
-- return base + (where & 0xffc) + (devfn << 12);
-+ return base + where + (devfn << 12);
- }
-
- static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
-index a272f335c289..096e957aecb0 100644
---- a/arch/arm64/kernel/hyp-stub.S
-+++ b/arch/arm64/kernel/hyp-stub.S
-@@ -26,6 +26,8 @@
- #include
-
- .text
-+ .pushsection .hyp.text, "ax"
-+
- .align 11
-
- ENTRY(__hyp_stub_vectors)
-diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
-index c26b804015e8..a90615baa529 100644
---- a/arch/arm64/mm/flush.c
-+++ b/arch/arm64/mm/flush.c
-@@ -70,10 +70,6 @@ void __sync_icache_dcache(pte_t pte, unsigned long addr)
- {
- struct page *page = pte_page(pte);
-
-- /* no flushing needed for anonymous pages */
-- if (!page_mapping(page))
-- return;
--
- if (!test_and_set_bit(PG_dcache_clean, &page->flags))
- sync_icache_aliases(page_address(page),
- PAGE_SIZE << compound_order(page));
-diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
-index 8eccead675d4..cc7b450a7766 100644
---- a/arch/s390/kernel/early.c
-+++ b/arch/s390/kernel/early.c
-@@ -224,10 +224,10 @@ static noinline __init void detect_machine_type(void)
- if (stsi(vmms, 3, 2, 2) || !vmms->count)
- return;
-
-- /* Running under KVM? If not we assume z/VM */
-+ /* Detect known hypervisors */
- if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
- S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
-- else
-+ else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4))
- S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
- }
-
-diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
-index e7a43a30e3ff..47692c78d09c 100644
---- a/arch/s390/kernel/setup.c
-+++ b/arch/s390/kernel/setup.c
-@@ -833,6 +833,8 @@ void __init setup_arch(char **cmdline_p)
- pr_info("Linux is running under KVM in 64-bit mode\n");
- else if (MACHINE_IS_LPAR)
- pr_info("Linux is running natively in 64-bit mode\n");
-+ else
-+ pr_info("Linux is running as a guest in 64-bit mode\n");
-
- /* Have one command line that is parsed and saved in /proc/cmdline */
- /* boot_command_line has been already set up in early.c */
-diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
-index 77f4f334a465..29e5409c0d48 100644
---- a/arch/s390/kernel/smp.c
-+++ b/arch/s390/kernel/smp.c
-@@ -360,9 +360,13 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
- */
- void smp_call_ipl_cpu(void (*func)(void *), void *data)
- {
-+ struct _lowcore *lc = pcpu_devices->lowcore;
-+
-+ if (pcpu_devices[0].address == stap())
-+ lc = &S390_lowcore;
-+
- pcpu_delegate(&pcpu_devices[0], func, data,
-- pcpu_devices->lowcore->panic_stack -
-- PANIC_FRAME_OFFSET + PAGE_SIZE);
-+ lc->panic_stack - PANIC_FRAME_OFFSET + PAGE_SIZE);
- }
-
- int smp_find_processor_id(u16 address)
-@@ -1152,7 +1156,11 @@ static ssize_t __ref rescan_store(struct device *dev,
- {
- int rc;
-
-+ rc = lock_device_hotplug_sysfs();
-+ if (rc)
-+ return rc;
- rc = smp_rescan_cpus();
-+ unlock_device_hotplug();
- return rc ? rc : count;
- }
- static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);
-diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
-index 31dab2135188..21332b431f10 100644
---- a/arch/x86/boot/compressed/aslr.c
-+++ b/arch/x86/boot/compressed/aslr.c
-@@ -25,8 +25,8 @@ static inline u16 i8254(void)
- u16 status, timer;
-
- do {
-- outb(I8254_PORT_CONTROL,
-- I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
-+ outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
-+ I8254_PORT_CONTROL);
- status = inb(I8254_PORT_COUNTER0);
- timer = inb(I8254_PORT_COUNTER0);
- timer |= inb(I8254_PORT_COUNTER0) << 8;
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index 1a934bb8ed1c..758e2b39567d 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -5524,8 +5524,7 @@ restart:
- toggle_interruptibility(vcpu, ctxt->interruptibility);
- vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
- kvm_rip_write(vcpu, ctxt->eip);
-- if (r == EMULATE_DONE &&
-- (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
-+ if (r == EMULATE_DONE && ctxt->tf)
- kvm_vcpu_do_singlestep(vcpu, &r);
- if (!ctxt->have_exception ||
- exception_type(ctxt->exception.vector) == EXCPT_TRAP)
-diff --git a/drivers/base/core.c b/drivers/base/core.c
-index 049ccc070ce5..cb5718d2669e 100644
---- a/drivers/base/core.c
-+++ b/drivers/base/core.c
-@@ -862,6 +862,8 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
- return;
-
- mutex_lock(&gdp_mutex);
-+ if (!kobject_has_children(glue_dir))
-+ kobject_del(glue_dir);
- kobject_put(glue_dir);
- mutex_unlock(&gdp_mutex);
- }
-diff --git a/drivers/block/loop.c b/drivers/block/loop.c
-index b1cf891cb3d9..ae361ee90587 100644
---- a/drivers/block/loop.c
-+++ b/drivers/block/loop.c
-@@ -81,6 +81,7 @@
- #include
-
- static DEFINE_IDR(loop_index_idr);
-+static DEFINE_MUTEX(loop_index_mutex);
- static DEFINE_MUTEX(loop_ctl_mutex);
-
- static int max_part;
-@@ -1570,11 +1571,9 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
- static int lo_open(struct block_device *bdev, fmode_t mode)
- {
- struct loop_device *lo;
-- int err;
-+ int err = 0;
-
-- err = mutex_lock_killable(&loop_ctl_mutex);
-- if (err)
-- return err;
-+ mutex_lock(&loop_index_mutex);
- lo = bdev->bd_disk->private_data;
- if (!lo) {
- err = -ENXIO;
-@@ -1583,20 +1582,18 @@ static int lo_open(struct block_device *bdev, fmode_t mode)
-
- atomic_inc(&lo->lo_refcnt);
- out:
-- mutex_unlock(&loop_ctl_mutex);
-+ mutex_unlock(&loop_index_mutex);
- return err;
- }
-
--static void lo_release(struct gendisk *disk, fmode_t mode)
-+static void __lo_release(struct loop_device *lo)
- {
-- struct loop_device *lo;
- int err;
-
-- mutex_lock(&loop_ctl_mutex);
-- lo = disk->private_data;
- if (atomic_dec_return(&lo->lo_refcnt))
-- goto out_unlock;
-+ return;
-
-+ mutex_lock(&loop_ctl_mutex);
- if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
- /*
- * In autoclear mode, stop the loop thread
-@@ -1613,10 +1610,16 @@ static void lo_release(struct gendisk *disk, fmode_t mode)
- loop_flush(lo);
- }
-
--out_unlock:
- mutex_unlock(&loop_ctl_mutex);
- }
-
-+static void lo_release(struct gendisk *disk, fmode_t mode)
-+{
-+ mutex_lock(&loop_index_mutex);
-+ __lo_release(disk->private_data);
-+ mutex_unlock(&loop_index_mutex);
-+}
-+
- static const struct block_device_operations lo_fops = {
- .owner = THIS_MODULE,
- .open = lo_open,
-@@ -1896,7 +1899,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
- struct kobject *kobj;
- int err;
-
-- mutex_lock(&loop_ctl_mutex);
-+ mutex_lock(&loop_index_mutex);
- err = loop_lookup(&lo, MINOR(dev) >> part_shift);
- if (err < 0)
- err = loop_add(&lo, MINOR(dev) >> part_shift);
-@@ -1904,7 +1907,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
- kobj = NULL;
- else
- kobj = get_disk(lo->lo_disk);
-- mutex_unlock(&loop_ctl_mutex);
-+ mutex_unlock(&loop_index_mutex);
-
- *part = 0;
- return kobj;
-@@ -1914,13 +1917,9 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
- unsigned long parm)
- {
- struct loop_device *lo;
-- int ret;
--
-- ret = mutex_lock_killable(&loop_ctl_mutex);
-- if (ret)
-- return ret;
-+ int ret = -ENOSYS;
-
-- ret = -ENOSYS;
-+ mutex_lock(&loop_index_mutex);
- switch (cmd) {
- case LOOP_CTL_ADD:
- ret = loop_lookup(&lo, parm);
-@@ -1934,15 +1933,19 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
- ret = loop_lookup(&lo, parm);
- if (ret < 0)
- break;
-+ mutex_lock(&loop_ctl_mutex);
- if (lo->lo_state != Lo_unbound) {
- ret = -EBUSY;
-+ mutex_unlock(&loop_ctl_mutex);
- break;
- }
- if (atomic_read(&lo->lo_refcnt) > 0) {
- ret = -EBUSY;
-+ mutex_unlock(&loop_ctl_mutex);
- break;
- }
- lo->lo_disk->private_data = NULL;
-+ mutex_unlock(&loop_ctl_mutex);
- idr_remove(&loop_index_idr, lo->lo_number);
- loop_remove(lo);
- break;
-@@ -1952,7 +1955,7 @@ static long loop_control_ioctl(struct file *file, unsigned int cmd,
- break;
- ret = loop_add(&lo, -1);
- }
-- mutex_unlock(&loop_ctl_mutex);
-+ mutex_unlock(&loop_index_mutex);
-
- return ret;
- }
-@@ -2035,10 +2038,10 @@ static int __init loop_init(void)
- THIS_MODULE, loop_probe, NULL, NULL);
-
- /* pre-create number of devices given by config or max_loop */
-- mutex_lock(&loop_ctl_mutex);
-+ mutex_lock(&loop_index_mutex);
- for (i = 0; i < nr; i++)
- loop_add(&lo, i);
-- mutex_unlock(&loop_ctl_mutex);
-+ mutex_unlock(&loop_index_mutex);
-
- printk(KERN_INFO "loop: module loaded\n");
- return 0;
-diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
-index 164544afd680..618f3df6c3b9 100644
---- a/drivers/char/mwave/mwavedd.c
-+++ b/drivers/char/mwave/mwavedd.c
-@@ -59,6 +59,7 @@
- #include
- #include
- #include
-+#include
- #include "smapi.h"
- #include "mwavedd.h"
- #include "3780i.h"
-@@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
- ipcnum);
- return -EINVAL;
- }
-+ ipcnum = array_index_nospec(ipcnum,
-+ ARRAY_SIZE(pDrvData->IPCs));
- PRINTK_3(TRACE_MWAVE,
- "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
- " ipcnum %x entry usIntCount %x\n",
-@@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
- " Invalid ipcnum %x\n", ipcnum);
- return -EINVAL;
- }
-+ ipcnum = array_index_nospec(ipcnum,
-+ ARRAY_SIZE(pDrvData->IPCs));
- PRINTK_3(TRACE_MWAVE,
- "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
- " ipcnum %x, usIntCount %x\n",
-@@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
- ipcnum);
- return -EINVAL;
- }
-+ ipcnum = array_index_nospec(ipcnum,
-+ ARRAY_SIZE(pDrvData->IPCs));
- mutex_lock(&mwave_mutex);
- if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
- pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
-diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
-index f55dcdf99bc5..26476a64e663 100644
---- a/drivers/input/joystick/xpad.c
-+++ b/drivers/input/joystick/xpad.c
-@@ -255,6 +255,8 @@ static const struct xpad_device {
- { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
- { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
- { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
-+ { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
-+ { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
- { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
- { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
- { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
-@@ -431,6 +433,7 @@ static const struct usb_device_id xpad_table[] = {
- XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */
- XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
- XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
-+ XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
- XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
- XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
- XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
-diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
-index c3d7a1461043..114d5883d497 100644
---- a/drivers/irqchip/irq-gic-v3-its.c
-+++ b/drivers/irqchip/irq-gic-v3-its.c
-@@ -1230,13 +1230,14 @@ static void its_free_device(struct its_device *its_dev)
- kfree(its_dev);
- }
-
--static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
-+static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
- {
- int idx;
-
-- idx = find_first_zero_bit(dev->event_map.lpi_map,
-- dev->event_map.nr_lpis);
-- if (idx == dev->event_map.nr_lpis)
-+ idx = bitmap_find_free_region(dev->event_map.lpi_map,
-+ dev->event_map.nr_lpis,
-+ get_count_order(nvecs));
-+ if (idx < 0)
- return -ENOSPC;
-
- *hwirq = dev->event_map.lpi_base + idx;
-@@ -1317,20 +1318,20 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
- int err;
- int i;
-
-- for (i = 0; i < nr_irqs; i++) {
-- err = its_alloc_device_irq(its_dev, &hwirq);
-- if (err)
-- return err;
-+ err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
-+ if (err)
-+ return err;
-
-- err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
-+ for (i = 0; i < nr_irqs; i++) {
-+ err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
- if (err)
- return err;
-
- irq_domain_set_hwirq_and_chip(domain, virq + i,
-- hwirq, &its_irq_chip, its_dev);
-+ hwirq + i, &its_irq_chip, its_dev);
- pr_debug("ID:%d pID:%d vID:%d\n",
-- (int)(hwirq - its_dev->event_map.lpi_base),
-- (int) hwirq, virq + i);
-+ (int)(hwirq + i - its_dev->event_map.lpi_base),
-+ (int)(hwirq + i), virq + i);
- }
-
- return 0;
-diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c
-index ffd448149796..4a2ae06d0da4 100644
---- a/drivers/mmc/host/sdhci-iproc.c
-+++ b/drivers/mmc/host/sdhci-iproc.c
-@@ -217,7 +217,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
-
- iproc_host->data = iproc_data;
-
-- mmc_of_parse(host->mmc);
-+ ret = mmc_of_parse(host->mmc);
-+ if (ret)
-+ goto err;
-+
- sdhci_get_of_property(pdev);
-
- /* Enable EMMC 1/8V DDR capable */
-diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
-index 1dbee1cb3df9..8b7c6425b681 100644
---- a/drivers/net/can/dev.c
-+++ b/drivers/net/can/dev.c
-@@ -426,8 +426,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
- struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
- {
- struct can_priv *priv = netdev_priv(dev);
-- struct sk_buff *skb = priv->echo_skb[idx];
-- struct canfd_frame *cf;
-
- if (idx >= priv->echo_skb_max) {
- netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
-@@ -435,20 +433,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
- return NULL;
- }
-
-- if (!skb) {
-- netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
-- __func__, idx);
-- return NULL;
-- }
-+ if (priv->echo_skb[idx]) {
-+ /* Using "struct canfd_frame::len" for the frame
-+ * length is supported on both CAN and CANFD frames.
-+ */
-+ struct sk_buff *skb = priv->echo_skb[idx];
-+ struct canfd_frame *cf = (struct canfd_frame *)skb->data;
-+ u8 len = cf->len;
-+
-+ *len_ptr = len;
-+ priv->echo_skb[idx] = NULL;
-
-- /* Using "struct canfd_frame::len" for the frame
-- * length is supported on both CAN and CANFD frames.
-- */
-- cf = (struct canfd_frame *)skb->data;
-- *len_ptr = cf->len;
-- priv->echo_skb[idx] = NULL;
-+ return skb;
-+ }
-
-- return skb;
-+ return NULL;
- }
-
- /*
-diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
-index 650f7888e32b..55ac00055977 100644
---- a/drivers/net/ethernet/freescale/ucc_geth.c
-+++ b/drivers/net/ethernet/freescale/ucc_geth.c
-@@ -1888,6 +1888,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
- u16 i, j;
- u8 __iomem *bd;
-
-+ netdev_reset_queue(ugeth->ndev);
-+
- ug_info = ugeth->ug_info;
- uf_info = &ug_info->uf_info;
-
-diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
-index 90db94e83fde..033f99d2f15c 100644
---- a/drivers/net/ethernet/mellanox/mlx4/fw.c
-+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
-@@ -1906,9 +1906,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
- {
- struct mlx4_cmd_mailbox *mailbox;
- __be32 *outbox;
-+ u64 qword_field;
- u32 dword_field;
-- int err;
-+ u16 word_field;
- u8 byte_field;
-+ int err;
- static const u8 a0_dmfs_query_hw_steering[] = {
- [0] = MLX4_STEERING_DMFS_A0_DEFAULT,
- [1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
-@@ -1936,19 +1938,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
-
- /* QPC/EEC/CQC/EQC/RDMARC attributes */
-
-- MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET);
-- MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET);
-- MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET);
-- MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET);
-- MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET);
-- MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET);
-- MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET);
-- MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET);
-- MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET);
-- MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET);
-- MLX4_GET(param->num_sys_eqs, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
-- MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
-- MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
-+ MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
-+ param->qpc_base = qword_field & ~((u64)0x1f);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
-+ param->log_num_qps = byte_field & 0x1f;
-+ MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
-+ param->srqc_base = qword_field & ~((u64)0x1f);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
-+ param->log_num_srqs = byte_field & 0x1f;
-+ MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
-+ param->cqc_base = qword_field & ~((u64)0x1f);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
-+ param->log_num_cqs = byte_field & 0x1f;
-+ MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
-+ param->altc_base = qword_field;
-+ MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
-+ param->auxc_base = qword_field;
-+ MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
-+ param->eqc_base = qword_field & ~((u64)0x1f);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
-+ param->log_num_eqs = byte_field & 0x1f;
-+ MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
-+ param->num_sys_eqs = word_field & 0xfff;
-+ MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
-+ param->rdmarc_base = qword_field & ~((u64)0x1f);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
-+ param->log_rd_per_qp = byte_field & 0x7;
-
- MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
- if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
-@@ -1967,22 +1982,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
- /* steering attributes */
- if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
- MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
-- MLX4_GET(param->log_mc_entry_sz, outbox,
-- INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
-- MLX4_GET(param->log_mc_table_sz, outbox,
-- INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
-- MLX4_GET(byte_field, outbox,
-- INIT_HCA_FS_A0_OFFSET);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
-+ param->log_mc_entry_sz = byte_field & 0x1f;
-+ MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
-+ param->log_mc_table_sz = byte_field & 0x1f;
-+ MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
- param->dmfs_high_steer_mode =
- a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
- } else {
- MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
-- MLX4_GET(param->log_mc_entry_sz, outbox,
-- INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
-- MLX4_GET(param->log_mc_hash_sz, outbox,
-- INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-- MLX4_GET(param->log_mc_table_sz, outbox,
-- INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
-+ param->log_mc_entry_sz = byte_field & 0x1f;
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-+ param->log_mc_hash_sz = byte_field & 0x1f;
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
-+ param->log_mc_table_sz = byte_field & 0x1f;
- }
-
- /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
-@@ -2006,15 +2020,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
- /* TPT attributes */
-
- MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET);
-- MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
-- MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
-+ param->mw_enabled = byte_field >> 7;
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
-+ param->log_mpt_sz = byte_field & 0x3f;
- MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET);
- MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET);
-
- /* UAR attributes */
-
- MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
-- MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
-+ MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
-+ param->log_uar_sz = byte_field & 0xf;
-
- /* phv_check enable */
- MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
-diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
-index 583d50f80b24..02327e6c4819 100644
---- a/drivers/net/ppp/pppoe.c
-+++ b/drivers/net/ppp/pppoe.c
-@@ -442,6 +442,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
- if (pskb_trim_rcsum(skb, len))
- goto drop;
-
-+ ph = pppoe_hdr(skb);
- pn = pppoe_pernet(dev_net(dev));
-
- /* Note that get_item does a sock_hold(), so sk_pppox(po)
-diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
-index 852d2de7f69f..a284a2b42bcd 100644
---- a/drivers/platform/x86/asus-nb-wmi.c
-+++ b/drivers/platform/x86/asus-nb-wmi.c
-@@ -339,8 +339,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
- { KE_KEY, 0x30, { KEY_VOLUMEUP } },
- { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
- { KE_KEY, 0x32, { KEY_MUTE } },
-- { KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
-- { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
-+ { KE_KEY, 0x35, { KEY_SCREENLOCK } },
- { KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
- { KE_KEY, 0x41, { KEY_NEXTSONG } },
- { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */
-diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
-index 944156207477..dcb949dcfa66 100644
---- a/drivers/s390/char/sclp_config.c
-+++ b/drivers/s390/char/sclp_config.c
-@@ -43,7 +43,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
-
- static void __ref sclp_cpu_change_notify(struct work_struct *work)
- {
-+ lock_device_hotplug();
- smp_rescan_cpus();
-+ unlock_device_hotplug();
- }
-
- static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
-diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
-index c2d2c17550a7..951f22265105 100644
---- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
-+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
-@@ -47,6 +47,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
- {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
- {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
- {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
-+ {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
- {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
- {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
- {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
-diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
-index 6d1e2f746ab4..8d6253903f24 100644
---- a/drivers/tty/n_hdlc.c
-+++ b/drivers/tty/n_hdlc.c
-@@ -598,6 +598,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
- /* too large for caller's buffer */
- ret = -EOVERFLOW;
- } else {
-+ __set_current_state(TASK_RUNNING);
- if (copy_to_user(buf, rbuf->buf, rbuf->count))
- ret = -EFAULT;
- else
-diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
-index c1cff2b455ae..5b86ebc76a8a 100644
---- a/drivers/tty/tty_io.c
-+++ b/drivers/tty/tty_io.c
-@@ -2297,7 +2297,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
- return -EFAULT;
- tty_audit_tiocsti(tty, ch);
- ld = tty_ldisc_ref_wait(tty);
-- ld->ops->receive_buf(tty, &ch, &mbz, 1);
-+ if (ld->ops->receive_buf)
-+ ld->ops->receive_buf(tty, &ch, &mbz, 1);
- tty_ldisc_deref(ld);
- return 0;
- }
-diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
-index ff3286fc22d8..6779f733bb83 100644
---- a/drivers/tty/vt/vt.c
-+++ b/drivers/tty/vt/vt.c
-@@ -958,6 +958,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
- if (CON_IS_VISIBLE(vc))
- update_screen(vc);
- vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
-+ notify_update(vc);
- return err;
- }
-
-diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
-index 4966768d3c98..9706d214c409 100644
---- a/drivers/usb/serial/pl2303.c
-+++ b/drivers/usb/serial/pl2303.c
-@@ -47,6 +47,7 @@ static const struct usb_device_id id_table[] = {
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
- { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
-+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) },
- { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
- { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
- { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
-diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
-index a84f0959ab34..d84c3b3d477b 100644
---- a/drivers/usb/serial/pl2303.h
-+++ b/drivers/usb/serial/pl2303.h
-@@ -13,6 +13,7 @@
-
- #define PL2303_VENDOR_ID 0x067b
- #define PL2303_PRODUCT_ID 0x2303
-+#define PL2303_PRODUCT_ID_TB 0x2304
- #define PL2303_PRODUCT_ID_RSAQ2 0x04bb
- #define PL2303_PRODUCT_ID_DCU11 0x1234
- #define PL2303_PRODUCT_ID_PHAROS 0xaaa0
-@@ -25,6 +26,7 @@
- #define PL2303_PRODUCT_ID_MOTOROLA 0x0307
- #define PL2303_PRODUCT_ID_ZTEK 0xe1f1
-
-+
- #define ATEN_VENDOR_ID 0x0557
- #define ATEN_VENDOR_ID2 0x0547
- #define ATEN_PRODUCT_ID 0x2008
-diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
-index 6d6acf2c07c3..511242111403 100644
---- a/drivers/usb/serial/usb-serial-simple.c
-+++ b/drivers/usb/serial/usb-serial-simple.c
-@@ -88,7 +88,8 @@ DEVICE(moto_modem, MOTO_IDS);
- /* Motorola Tetra driver */
- #define MOTOROLA_TETRA_IDS() \
- { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
-- { USB_DEVICE(0x0cad, 0x9012) } /* MTP6550 */
-+ { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
-+ { USB_DEVICE(0x0cad, 0x9016) } /* TPG2200 */
- DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
-
- /* Novatel Wireless GPS driver */
-diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
-index 1eeb4780c3ed..eacf57c24ca9 100644
---- a/fs/cifs/connect.c
-+++ b/fs/cifs/connect.c
-@@ -48,6 +48,7 @@
- #include "cifs_unicode.h"
- #include "cifs_debug.h"
- #include "cifs_fs_sb.h"
-+#include "dns_resolve.h"
- #include "ntlmssp.h"
- #include "nterr.h"
- #include "rfc1002pdu.h"
-@@ -303,6 +304,53 @@ static void cifs_prune_tlinks(struct work_struct *work);
- static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
- const char *devname);
-
-+/*
-+ * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
-+ * get their ip addresses changed at some point.
-+ *
-+ * This should be called with server->srv_mutex held.
-+ */
-+#ifdef CONFIG_CIFS_DFS_UPCALL
-+static int reconn_set_ipaddr(struct TCP_Server_Info *server)
-+{
-+ int rc;
-+ int len;
-+ char *unc, *ipaddr = NULL;
-+
-+ if (!server->hostname)
-+ return -EINVAL;
-+
-+ len = strlen(server->hostname) + 3;
-+
-+ unc = kmalloc(len, GFP_KERNEL);
-+ if (!unc) {
-+ cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
-+ return -ENOMEM;
-+ }
-+ snprintf(unc, len, "\\\\%s", server->hostname);
-+
-+ rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
-+ kfree(unc);
-+
-+ if (rc < 0) {
-+ cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
-+ __func__, server->hostname, rc);
-+ return rc;
-+ }
-+
-+ rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
-+ strlen(ipaddr));
-+ kfree(ipaddr);
-+
-+ return !rc ? -1 : 0;
-+}
-+#else
-+static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
-+{
-+ return 0;
-+}
-+#endif
-+
- /*
- * cifs tcp session reconnection
- *
-@@ -400,6 +448,11 @@ cifs_reconnect(struct TCP_Server_Info *server)
- rc = generic_ip_connect(server);
- if (rc) {
- cifs_dbg(FYI, "reconnect error %d\n", rc);
-+ rc = reconn_set_ipaddr(server);
-+ if (rc) {
-+ cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
-+ __func__, rc);
-+ }
- mutex_unlock(&server->srv_mutex);
- msleep(3000);
- } else {
-diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
-index 2725085a3f9f..eae3cdffaf7f 100644
---- a/fs/cifs/smb2ops.c
-+++ b/fs/cifs/smb2ops.c
-@@ -143,14 +143,14 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
-
- scredits = server->credits;
- /* can deadlock with reopen */
-- if (scredits == 1) {
-+ if (scredits <= 8) {
- *num = SMB2_MAX_BUFFER_SIZE;
- *credits = 0;
- break;
- }
-
-- /* leave one credit for a possible reopen */
-- scredits--;
-+ /* leave some credits for reopen and other ops */
-+ scredits -= 8;
- *num = min_t(unsigned int, size,
- scredits * SMB2_MAX_BUFFER_SIZE);
-
-diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
-index f7111bb88ec1..5e21d58c49ef 100644
---- a/fs/cifs/smb2pdu.c
-+++ b/fs/cifs/smb2pdu.c
-@@ -2523,8 +2523,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
- if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) {
- srch_inf->endOfSearch = true;
- rc = 0;
-- }
-- cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
-+ } else
-+ cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
- goto qdir_exit;
- }
-
-diff --git a/fs/dcache.c b/fs/dcache.c
-index 141651b0c766..9ffe60702299 100644
---- a/fs/dcache.c
-+++ b/fs/dcache.c
-@@ -1155,15 +1155,11 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
- */
- void shrink_dcache_sb(struct super_block *sb)
- {
-- long freed;
--
- do {
- LIST_HEAD(dispose);
-
-- freed = list_lru_walk(&sb->s_dentry_lru,
-+ list_lru_walk(&sb->s_dentry_lru,
- dentry_lru_isolate_shrink, &dispose, 1024);
--
-- this_cpu_sub(nr_dentry_unused, freed);
- shrink_dentry_list(&dispose);
- cond_resched();
- } while (list_lru_count(&sb->s_dentry_lru) > 0);
-diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
-index 763fe7737065..ef24894edecc 100644
---- a/fs/gfs2/rgrp.c
-+++ b/fs/gfs2/rgrp.c
-@@ -1720,9 +1720,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
- goto next_iter;
- }
- if (ret == -E2BIG) {
-- n += rbm->bii - initial_bii;
- rbm->bii = 0;
- rbm->offset = 0;
-+ n += (rbm->bii - initial_bii);
- goto res_covered_end_of_rgrp;
- }
- return ret;
-diff --git a/fs/read_write.c b/fs/read_write.c
-index bfd1a5dddf6e..16e554ba885d 100644
---- a/fs/read_write.c
-+++ b/fs/read_write.c
-@@ -363,8 +363,10 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos)
- iter->type |= WRITE;
- ret = file->f_op->write_iter(&kiocb, iter);
- BUG_ON(ret == -EIOCBQUEUED);
-- if (ret > 0)
-+ if (ret > 0) {
- *ppos = kiocb.ki_pos;
-+ fsnotify_modify(file);
-+ }
- return ret;
- }
- EXPORT_SYMBOL(vfs_iter_write);
-diff --git a/fs/super.c b/fs/super.c
-index 09b526a50986..b9cd7982f6e2 100644
---- a/fs/super.c
-+++ b/fs/super.c
-@@ -118,13 +118,23 @@ static unsigned long super_cache_count(struct shrinker *shrink,
- sb = container_of(shrink, struct super_block, s_shrink);
-
- /*
-- * Don't call trylock_super as it is a potential
-- * scalability bottleneck. The counts could get updated
-- * between super_cache_count and super_cache_scan anyway.
-- * Call to super_cache_count with shrinker_rwsem held
-- * ensures the safety of call to list_lru_shrink_count() and
-- * s_op->nr_cached_objects().
-+ * We don't call trylock_super() here as it is a scalability bottleneck,
-+ * so we're exposed to partial setup state. The shrinker rwsem does not
-+ * protect filesystem operations backing list_lru_shrink_count() or
-+ * s_op->nr_cached_objects(). Counts can change between
-+ * super_cache_count and super_cache_scan, so we really don't need locks
-+ * here.
-+ *
-+ * However, if we are currently mounting the superblock, the underlying
-+ * filesystem might be in a state of partial construction and hence it
-+ * is dangerous to access it. trylock_super() uses a MS_BORN check to
-+ * avoid this situation, so do the same here. The memory barrier is
-+ * matched with the one in mount_fs() as we don't hold locks here.
- */
-+ if (!(sb->s_flags & MS_BORN))
-+ return 0;
-+ smp_rmb();
-+
- if (sb->s_op && sb->s_op->nr_cached_objects)
- total_objects = sb->s_op->nr_cached_objects(sb, sc);
-
-@@ -1133,6 +1143,14 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
- sb = root->d_sb;
- BUG_ON(!sb);
- WARN_ON(!sb->s_bdi);
-+
-+ /*
-+ * Write barrier is for super_cache_count(). We place it before setting
-+ * MS_BORN as the data dependency between the two functions is the
-+ * superblock structure contents that we just set up, not the MS_BORN
-+ * flag.
-+ */
-+ smp_wmb();
- sb->s_flags |= MS_BORN;
-
- error = security_sb_kern_mount(sb, flags, secdata);
-diff --git a/include/linux/kobject.h b/include/linux/kobject.h
-index e6284591599e..5957c6a3fd7f 100644
---- a/include/linux/kobject.h
-+++ b/include/linux/kobject.h
-@@ -113,6 +113,23 @@ extern void kobject_put(struct kobject *kobj);
- extern const void *kobject_namespace(struct kobject *kobj);
- extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
-
-+/**
-+ * kobject_has_children - Returns whether a kobject has children.
-+ * @kobj: the object to test
-+ *
-+ * This will return whether a kobject has other kobjects as children.
-+ *
-+ * It does NOT account for the presence of attribute files, only sub
-+ * directories. It also assumes there is no concurrent addition or
-+ * removal of such children, and thus relies on external locking.
-+ */
-+static inline bool kobject_has_children(struct kobject *kobj)
-+{
-+ WARN_ON_ONCE(atomic_read(&kobj->kref.refcount) == 0);
-+
-+ return kobj->sd && kobj->sd->dir.subdirs;
-+}
-+
- struct kobj_type {
- void (*release)(struct kobject *kobj);
- const struct sysfs_ops *sysfs_ops;
-diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index a490dd718654..6d39d81d3c38 100644
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -2798,6 +2798,7 @@ static inline unsigned char *skb_push_rcsum(struct sk_buff *skb,
- *
- * This is exactly the same as pskb_trim except that it ensures the
- * checksum of received packets are still valid after the operation.
-+ * It can change skb pointers.
- */
-
- static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
-diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
-index 2a25b53cd427..f6ff83b2ac87 100644
---- a/include/net/ip_fib.h
-+++ b/include/net/ip_fib.h
-@@ -200,7 +200,7 @@ int fib_table_insert(struct fib_table *, struct fib_config *);
- int fib_table_delete(struct fib_table *, struct fib_config *);
- int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
- struct netlink_callback *cb);
--int fib_table_flush(struct fib_table *table);
-+int fib_table_flush(struct fib_table *table, bool flush_all);
- struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
- void fib_table_flush_external(struct fib_table *table);
- void fib_free_table(struct fib_table *tb);
-diff --git a/kernel/exit.c b/kernel/exit.c
-index f20e6339761b..03f6722302b5 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -450,12 +450,14 @@ static struct task_struct *find_alive_thread(struct task_struct *p)
- return NULL;
- }
-
--static struct task_struct *find_child_reaper(struct task_struct *father)
-+static struct task_struct *find_child_reaper(struct task_struct *father,
-+ struct list_head *dead)
- __releases(&tasklist_lock)
- __acquires(&tasklist_lock)
- {
- struct pid_namespace *pid_ns = task_active_pid_ns(father);
- struct task_struct *reaper = pid_ns->child_reaper;
-+ struct task_struct *p, *n;
-
- if (likely(reaper != father))
- return reaper;
-@@ -471,6 +473,12 @@ static struct task_struct *find_child_reaper(struct task_struct *father)
- panic("Attempted to kill init! exitcode=0x%08x\n",
- father->signal->group_exit_code ?: father->exit_code);
- }
-+
-+ list_for_each_entry_safe(p, n, dead, ptrace_entry) {
-+ list_del_init(&p->ptrace_entry);
-+ release_task(p);
-+ }
-+
- zap_pid_ns_processes(pid_ns);
- write_lock_irq(&tasklist_lock);
-
-@@ -557,7 +565,7 @@ static void forget_original_parent(struct task_struct *father,
- exit_ptrace(father, dead);
-
- /* Can drop and reacquire tasklist_lock */
-- reaper = find_child_reaper(father);
-+ reaper = find_child_reaper(father, dead);
- if (list_empty(&father->children))
- return;
-
-diff --git a/mm/migrate.c b/mm/migrate.c
-index afedcfab60e2..ce88dff1da98 100644
---- a/mm/migrate.c
-+++ b/mm/migrate.c
-@@ -936,6 +936,7 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
- int rc = MIGRATEPAGE_SUCCESS;
- int *result = NULL;
- struct page *newpage;
-+ bool is_lru = !isolated_balloon_page(page);
-
- newpage = get_new_page(page, private, &result);
- if (!newpage)
-@@ -983,11 +984,13 @@ out:
- /*
- * If migration was not successful and there's a freeing callback, use
- * it. Otherwise, putback_lru_page() will drop the reference grabbed
-- * during isolation.
-+ * during isolation. Use the old state of the isolated source page to
-+ * determine if we migrated a LRU page. newpage was already unlocked
-+ * and possibly modified by its owner - don't rely on the page state.
- */
- if (put_new_page)
- put_new_page(newpage, private);
-- else if (unlikely(__is_movable_balloon_page(newpage))) {
-+ else if (rc == MIGRATEPAGE_SUCCESS && unlikely(!is_lru)) {
- /* drop our reference, page already in the balloon */
- put_page(newpage);
- } else
-diff --git a/mm/oom_kill.c b/mm/oom_kill.c
-index c12680993ff3..bc781cdc0d04 100644
---- a/mm/oom_kill.c
-+++ b/mm/oom_kill.c
-@@ -544,6 +544,13 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
- * still freeing memory.
- */
- read_lock(&tasklist_lock);
-+
-+ /*
-+ * The task 'p' might have already exited before reaching here. The
-+ * put_task_struct() will free task_struct 'p' while the loop still try
-+ * to access the field of 'p', so, get an extra reference.
-+ */
-+ get_task_struct(p);
- for_each_thread(p, t) {
- list_for_each_entry(child, &t->children, sibling) {
- unsigned int child_points;
-@@ -563,6 +570,7 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
- }
- }
- }
-+ put_task_struct(p);
- read_unlock(&tasklist_lock);
-
- p = find_lock_task_mm(victim);
-diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
-index fcdb86dd5a23..c21209aada8c 100644
---- a/net/bridge/br_forward.c
-+++ b/net/bridge/br_forward.c
-@@ -39,10 +39,10 @@ static inline int should_deliver(const struct net_bridge_port *p,
-
- int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
- {
-+ skb_push(skb, ETH_HLEN);
- if (!is_skb_forwardable(skb->dev, skb))
- goto drop;
-
-- skb_push(skb, ETH_HLEN);
- br_drop_fake_rtable(skb);
- skb_sender_cpu_clear(skb);
-
-@@ -88,12 +88,11 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
- skb->dev = to->dev;
-
- if (unlikely(netpoll_tx_running(to->br->dev))) {
-+ skb_push(skb, ETH_HLEN);
- if (!is_skb_forwardable(skb->dev, skb))
- kfree_skb(skb);
-- else {
-- skb_push(skb, ETH_HLEN);
-+ else
- br_netpoll_send_skb(to, skb);
-- }
- return;
- }
-
-diff --git a/net/bridge/br_netfilter_ipv6.c b/net/bridge/br_netfilter_ipv6.c
-index d61f56efc8dc..69dfd212e50d 100644
---- a/net/bridge/br_netfilter_ipv6.c
-+++ b/net/bridge/br_netfilter_ipv6.c
-@@ -131,6 +131,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
- IPSTATS_MIB_INDISCARDS);
- goto drop;
- }
-+ hdr = ipv6_hdr(skb);
- }
- if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb))
- goto drop;
-diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
-index fdba3d9fbff3..6e48aa69fa24 100644
---- a/net/bridge/netfilter/nft_reject_bridge.c
-+++ b/net/bridge/netfilter/nft_reject_bridge.c
-@@ -192,6 +192,7 @@ static bool reject6_br_csum_ok(struct sk_buff *skb, int hook)
- pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h)))
- return false;
-
-+ ip6h = ipv6_hdr(skb);
- thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo);
- if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0)
- return false;
-diff --git a/net/can/bcm.c b/net/can/bcm.c
-index 4ccfd356baed..1f15622d3c65 100644
---- a/net/can/bcm.c
-+++ b/net/can/bcm.c
-@@ -67,6 +67,9 @@
- */
- #define MAX_NFRAMES 256
-
-+/* limit timers to 400 days for sending/timeouts */
-+#define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
-+
- /* use of last_frames[index].can_dlc */
- #define RX_RECV 0x40 /* received data for this element */
- #define RX_THR 0x80 /* element not been sent due to throttle feature */
-@@ -136,6 +139,22 @@ static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
- return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
- }
-
-+/* check limitations for timeval provided by user */
-+static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
-+{
-+ if ((msg_head->ival1.tv_sec < 0) ||
-+ (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
-+ (msg_head->ival1.tv_usec < 0) ||
-+ (msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
-+ (msg_head->ival2.tv_sec < 0) ||
-+ (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
-+ (msg_head->ival2.tv_usec < 0) ||
-+ (msg_head->ival2.tv_usec >= USEC_PER_SEC))
-+ return true;
-+
-+ return false;
-+}
-+
- #define CFSIZ sizeof(struct can_frame)
- #define OPSIZ sizeof(struct bcm_op)
- #define MHSIZ sizeof(struct bcm_msg_head)
-@@ -855,6 +874,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
- if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
- return -EINVAL;
-
-+ /* check timeval limitations */
-+ if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
-+ return -EINVAL;
-+
- /* check the given can_id */
- op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex);
-
-@@ -1020,6 +1043,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
- (!(msg_head->can_id & CAN_RTR_FLAG))))
- return -EINVAL;
-
-+ /* check timeval limitations */
-+ if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
-+ return -EINVAL;
-+
- /* check the given can_id */
- op = bcm_find_op(&bo->rx_ops, msg_head->can_id, ifindex);
- if (op) {
-diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
-index ce646572b912..1f7b47ca2243 100644
---- a/net/ipv4/fib_frontend.c
-+++ b/net/ipv4/fib_frontend.c
-@@ -187,7 +187,7 @@ static void fib_flush(struct net *net)
- struct fib_table *tb;
-
- hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
-- flushed += fib_table_flush(tb);
-+ flushed += fib_table_flush(tb, false);
- }
-
- if (flushed)
-@@ -1277,7 +1277,7 @@ static void ip_fib_net_exit(struct net *net)
-
- hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
- hlist_del(&tb->tb_hlist);
-- fib_table_flush(tb);
-+ fib_table_flush(tb, true);
- fib_free_table(tb);
- }
- }
-diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
-index 5c598f99a500..fdaa905dccdd 100644
---- a/net/ipv4/fib_trie.c
-+++ b/net/ipv4/fib_trie.c
-@@ -1806,7 +1806,7 @@ void fib_table_flush_external(struct fib_table *tb)
- }
-
- /* Caller must hold RTNL. */
--int fib_table_flush(struct fib_table *tb)
-+int fib_table_flush(struct fib_table *tb, bool flush_all)
- {
- struct trie *t = (struct trie *)tb->tb_data;
- struct key_vector *pn = t->kv;
-@@ -1850,7 +1850,17 @@ int fib_table_flush(struct fib_table *tb)
- hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) {
- struct fib_info *fi = fa->fa_info;
-
-- if (!fi || !(fi->fib_flags & RTNH_F_DEAD)) {
-+ if (!fi ||
-+ (!(fi->fib_flags & RTNH_F_DEAD) &&
-+ !fib_props[fa->fa_type].error)) {
-+ slen = fa->fa_slen;
-+ continue;
-+ }
-+
-+ /* Do not flush error routes if network namespace is
-+ * not being dismantled
-+ */
-+ if (!flush_all && fib_props[fa->fa_type].error) {
- slen = fa->fa_slen;
- continue;
- }
-diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
-index b1209b63381f..eb1834f2682f 100644
---- a/net/ipv4/ip_input.c
-+++ b/net/ipv4/ip_input.c
-@@ -444,6 +444,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
- goto drop;
- }
-
-+ iph = ip_hdr(skb);
- skb->transport_header = skb->network_header + iph->ihl*4;
-
- /* Remove any debris in the socket control block */
-diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
-index d6f2dab28d14..f9a4447ca002 100644
---- a/net/ipv6/af_inet6.c
-+++ b/net/ipv6/af_inet6.c
-@@ -345,6 +345,9 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
- err = -EINVAL;
- goto out_unlock;
- }
-+ }
-+
-+ if (sk->sk_bound_dev_if) {
- dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
- if (!dev) {
- err = -ENODEV;
-diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
-index 591d18785285..429dbb064240 100644
---- a/net/l2tp/l2tp_core.c
-+++ b/net/l2tp/l2tp_core.c
-@@ -83,8 +83,7 @@
- #define L2TP_SLFLAG_S 0x40000000
- #define L2TP_SL_SEQ_MASK 0x00ffffff
-
--#define L2TP_HDR_SIZE_SEQ 10
--#define L2TP_HDR_SIZE_NOSEQ 6
-+#define L2TP_HDR_SIZE_MAX 14
-
- /* Default trace flags */
- #define L2TP_DEFAULT_DEBUG_FLAGS 0
-@@ -705,11 +704,9 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
- "%s: recv data ns=%u, session nr=%u\n",
- session->name, ns, session->nr);
- }
-+ ptr += 4;
- }
-
-- /* Advance past L2-specific header, if present */
-- ptr += session->l2specific_len;
--
- if (L2TP_SKB_CB(skb)->has_seq) {
- /* Received a packet with sequence numbers. If we're the LNS,
- * check if we sre sending sequence numbers and if not,
-@@ -860,7 +857,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
- __skb_pull(skb, sizeof(struct udphdr));
-
- /* Short packet? */
-- if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) {
-+ if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
- l2tp_info(tunnel, L2TP_MSG_DATA,
- "%s: recv short packet (len=%d)\n",
- tunnel->name, skb->len);
-@@ -933,6 +930,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
- goto error;
- }
-
-+ if (tunnel->version == L2TP_HDR_VER_3 &&
-+ l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
-+ goto error;
-+
- l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook);
-
- return 0;
-@@ -1031,21 +1032,20 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
- memcpy(bufp, &session->cookie[0], session->cookie_len);
- bufp += session->cookie_len;
- }
-- if (session->l2specific_len) {
-- if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
-- u32 l2h = 0;
-- if (session->send_seq) {
-- l2h = 0x40000000 | session->ns;
-- session->ns++;
-- session->ns &= 0xffffff;
-- l2tp_dbg(session, L2TP_MSG_SEQ,
-- "%s: updated ns to %u\n",
-- session->name, session->ns);
-- }
-+ if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
-+ u32 l2h = 0;
-
-- *((__be32 *) bufp) = htonl(l2h);
-+ if (session->send_seq) {
-+ l2h = 0x40000000 | session->ns;
-+ session->ns++;
-+ session->ns &= 0xffffff;
-+ l2tp_dbg(session, L2TP_MSG_SEQ,
-+ "%s: updated ns to %u\n",
-+ session->name, session->ns);
- }
-- bufp += session->l2specific_len;
-+
-+ *((__be32 *)bufp) = htonl(l2h);
-+ bufp += 4;
- }
- if (session->offset)
- bufp += session->offset;
-@@ -1724,7 +1724,7 @@ int l2tp_session_delete(struct l2tp_session *session)
- EXPORT_SYMBOL_GPL(l2tp_session_delete);
-
- /* We come here whenever a session's send_seq, cookie_len or
-- * l2specific_len parameters are set.
-+ * l2specific_type parameters are set.
- */
- void l2tp_session_set_header_len(struct l2tp_session *session, int version)
- {
-@@ -1733,7 +1733,8 @@ void l2tp_session_set_header_len(struct l2tp_session *session, int version)
- if (session->send_seq)
- session->hdr_len += 4;
- } else {
-- session->hdr_len = 4 + session->cookie_len + session->l2specific_len + session->offset;
-+ session->hdr_len = 4 + session->cookie_len + session->offset;
-+ session->hdr_len += l2tp_get_l2specific_len(session);
- if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
- session->hdr_len += 4;
- }
-diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
-index 9cf546846edb..fad47e9d74bc 100644
---- a/net/l2tp/l2tp_core.h
-+++ b/net/l2tp/l2tp_core.h
-@@ -313,6 +313,37 @@ do { \
- #define l2tp_session_dec_refcount(s) l2tp_session_dec_refcount_1(s)
- #endif
-
-+static inline int l2tp_get_l2specific_len(struct l2tp_session *session)
-+{
-+ switch (session->l2specific_type) {
-+ case L2TP_L2SPECTYPE_DEFAULT:
-+ return 4;
-+ case L2TP_L2SPECTYPE_NONE:
-+ default:
-+ return 0;
-+ }
-+}
-+
-+static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, struct sk_buff *skb,
-+ unsigned char **ptr, unsigned char **optr)
-+{
-+ int opt_len = session->peer_cookie_len + l2tp_get_l2specific_len(session);
-+
-+ if (opt_len > 0) {
-+ int off = *ptr - *optr;
-+
-+ if (!pskb_may_pull(skb, off + opt_len))
-+ return -1;
-+
-+ if (skb->data != *optr) {
-+ *optr = skb->data;
-+ *ptr = skb->data + off;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
- #define l2tp_printk(ptr, type, func, fmt, ...) \
- do { \
- if (((ptr)->debug) & (type)) \
-diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
-index af74e3ba0f92..7efb3cadc152 100644
---- a/net/l2tp/l2tp_ip.c
-+++ b/net/l2tp/l2tp_ip.c
-@@ -163,6 +163,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
- }
-
-+ if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
-+ goto discard;
-+
- l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook);
-
- return 0;
-diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
-index 591d308bf63a..e066111b9398 100644
---- a/net/l2tp/l2tp_ip6.c
-+++ b/net/l2tp/l2tp_ip6.c
-@@ -174,6 +174,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
- }
-
-+ if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
-+ goto discard;
-+
- l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
- tunnel->recv_payload_hook);
- return 0;
-diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
-index 94d05806a9a2..f0ecaec1ff3d 100644
---- a/net/netrom/nr_timer.c
-+++ b/net/netrom/nr_timer.c
-@@ -53,21 +53,21 @@ void nr_start_t1timer(struct sock *sk)
- {
- struct nr_sock *nr = nr_sk(sk);
-
-- mod_timer(&nr->t1timer, jiffies + nr->t1);
-+ sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);
- }
-
- void nr_start_t2timer(struct sock *sk)
- {
- struct nr_sock *nr = nr_sk(sk);
-
-- mod_timer(&nr->t2timer, jiffies + nr->t2);
-+ sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);
- }
-
- void nr_start_t4timer(struct sock *sk)
- {
- struct nr_sock *nr = nr_sk(sk);
-
-- mod_timer(&nr->t4timer, jiffies + nr->t4);
-+ sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);
- }
-
- void nr_start_idletimer(struct sock *sk)
-@@ -75,37 +75,37 @@ void nr_start_idletimer(struct sock *sk)
- struct nr_sock *nr = nr_sk(sk);
-
- if (nr->idle > 0)
-- mod_timer(&nr->idletimer, jiffies + nr->idle);
-+ sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);
- }
-
- void nr_start_heartbeat(struct sock *sk)
- {
-- mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
-+ sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);
- }
-
- void nr_stop_t1timer(struct sock *sk)
- {
-- del_timer(&nr_sk(sk)->t1timer);
-+ sk_stop_timer(sk, &nr_sk(sk)->t1timer);
- }
-
- void nr_stop_t2timer(struct sock *sk)
- {
-- del_timer(&nr_sk(sk)->t2timer);
-+ sk_stop_timer(sk, &nr_sk(sk)->t2timer);
- }
-
- void nr_stop_t4timer(struct sock *sk)
- {
-- del_timer(&nr_sk(sk)->t4timer);
-+ sk_stop_timer(sk, &nr_sk(sk)->t4timer);
- }
-
- void nr_stop_idletimer(struct sock *sk)
- {
-- del_timer(&nr_sk(sk)->idletimer);
-+ sk_stop_timer(sk, &nr_sk(sk)->idletimer);
- }
-
- void nr_stop_heartbeat(struct sock *sk)
- {
-- del_timer(&sk->sk_timer);
-+ sk_stop_timer(sk, &sk->sk_timer);
- }
-
- int nr_t1timer_running(struct sock *sk)
-diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
-index 624c4719e404..537917dfa83a 100644
---- a/net/openvswitch/flow_netlink.c
-+++ b/net/openvswitch/flow_netlink.c
-@@ -409,7 +409,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
- return -EINVAL;
- }
-
-- if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
-+ if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
- attrs |= 1 << type;
- a[type] = nla;
- }
-diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
-index 0fc76d845103..9f704a7f2a28 100644
---- a/net/rose/rose_route.c
-+++ b/net/rose/rose_route.c
-@@ -848,6 +848,7 @@ void rose_link_device_down(struct net_device *dev)
-
- /*
- * Route a frame to an appropriate AX.25 connection.
-+ * A NULL ax25_cb indicates an internally generated frame.
- */
- int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
- {
-@@ -865,6 +866,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
-
- if (skb->len < ROSE_MIN_LEN)
- return res;
-+
-+ if (!ax25)
-+ return rose_loopback_queue(skb, NULL);
-+
- frametype = skb->data[2];
- lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
- if (frametype == ROSE_CALL_REQUEST &&
-diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
-index 6d340cd6e2a7..b379c330a338 100644
---- a/net/sched/sch_api.c
-+++ b/net/sched/sch_api.c
-@@ -1823,7 +1823,6 @@ done:
- int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
- struct tcf_result *res, bool compat_mode)
- {
-- __be16 protocol = tc_skb_protocol(skb);
- #ifdef CONFIG_NET_CLS_ACT
- const struct tcf_proto *old_tp = tp;
- int limit = 0;
-@@ -1831,6 +1830,7 @@ int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
- reclassify:
- #endif
- for (; tp; tp = rcu_dereference_bh(tp->next)) {
-+ __be16 protocol = tc_skb_protocol(skb);
- int err;
-
- if (tp->protocol != protocol &&
-@@ -1857,7 +1857,6 @@ reset:
- }
-
- tp = old_tp;
-- protocol = tc_skb_protocol(skb);
- goto reclassify;
- #endif
- }
-diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
-index 2b96b11fbe71..1d9dfb92b3b4 100644
---- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
-+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
-@@ -398,7 +398,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
- {
-- snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-+ int ret;
-+
-+ ret =
-+ snd_pcm_lib_malloc_pages(substream,
-+ params_buffer_bytes(params));
-+ if (ret)
-+ return ret;
- memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
- return 0;
- }
-diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
-index 60edec383281..bf5ee8906fb2 100644
---- a/tools/perf/util/unwind-libdw.c
-+++ b/tools/perf/util/unwind-libdw.c
-@@ -41,13 +41,13 @@ static int __report_module(struct addr_location *al, u64 ip,
- Dwarf_Addr s;
-
- dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
-- if (s != al->map->start)
-+ if (s != al->map->start - al->map->pgoff)
- mod = 0;
- }
-
- if (!mod)
- mod = dwfl_report_elf(ui->dwfl, dso->short_name,
-- dso->long_name, -1, al->map->start,
-+ (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff,
- false);
-
- return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.173-174.patch b/patch/kernel/rk3399-default/04-patch-4.4.173-174.patch
deleted file mode 100644
index 3060cab79..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.173-174.patch
+++ /dev/null
@@ -1,3075 +0,0 @@
-diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
-index 2ea4c45cf1c8..7c229f59016f 100644
---- a/Documentation/networking/ip-sysctl.txt
-+++ b/Documentation/networking/ip-sysctl.txt
-@@ -112,14 +112,11 @@ min_adv_mss - INTEGER
-
- IP Fragmentation:
-
--ipfrag_high_thresh - INTEGER
-- Maximum memory used to reassemble IP fragments. When
-- ipfrag_high_thresh bytes of memory is allocated for this purpose,
-- the fragment handler will toss packets until ipfrag_low_thresh
-- is reached. This also serves as a maximum limit to namespaces
-- different from the initial one.
--
--ipfrag_low_thresh - INTEGER
-+ipfrag_high_thresh - LONG INTEGER
-+ Maximum memory used to reassemble IP fragments.
-+
-+ipfrag_low_thresh - LONG INTEGER
-+ (Obsolete since linux-4.17)
- Maximum memory used to reassemble IP fragments before the kernel
- begins to remove incomplete fragment queues to free up resources.
- The kernel still accepts new fragments for defragmentation.
-diff --git a/Makefile b/Makefile
-index db7665e32da8..1fa281069379 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 173
-+SUBLEVEL = 174
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
-index e50b31d18462..e97cdfd6cba9 100644
---- a/include/linux/rhashtable.h
-+++ b/include/linux/rhashtable.h
-@@ -133,23 +133,23 @@ struct rhashtable_params {
- /**
- * struct rhashtable - Hash table handle
- * @tbl: Bucket table
-- * @nelems: Number of elements in table
- * @key_len: Key length for hashfn
- * @elasticity: Maximum chain length before rehash
- * @p: Configuration parameters
- * @run_work: Deferred worker to expand/shrink asynchronously
- * @mutex: Mutex to protect current/future table swapping
- * @lock: Spin lock to protect walker list
-+ * @nelems: Number of elements in table
- */
- struct rhashtable {
- struct bucket_table __rcu *tbl;
-- atomic_t nelems;
- unsigned int key_len;
- unsigned int elasticity;
- struct rhashtable_params p;
- struct work_struct run_work;
- struct mutex mutex;
- spinlock_t lock;
-+ atomic_t nelems;
- };
-
- /**
-@@ -343,7 +343,8 @@ int rhashtable_init(struct rhashtable *ht,
- struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
- const void *key,
- struct rhash_head *obj,
-- struct bucket_table *old_tbl);
-+ struct bucket_table *old_tbl,
-+ void **data);
- int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl);
-
- int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter);
-@@ -514,18 +515,8 @@ static inline int rhashtable_compare(struct rhashtable_compare_arg *arg,
- return memcmp(ptr + ht->p.key_offset, arg->key, ht->p.key_len);
- }
-
--/**
-- * rhashtable_lookup_fast - search hash table, inlined version
-- * @ht: hash table
-- * @key: the pointer to the key
-- * @params: hash table parameters
-- *
-- * Computes the hash value for the key and traverses the bucket chain looking
-- * for a entry with an identical key. The first matching entry is returned.
-- *
-- * Returns the first entry on which the compare function returned true.
-- */
--static inline void *rhashtable_lookup_fast(
-+/* Internal function, do not use. */
-+static inline struct rhash_head *__rhashtable_lookup(
- struct rhashtable *ht, const void *key,
- const struct rhashtable_params params)
- {
-@@ -537,8 +528,6 @@ static inline void *rhashtable_lookup_fast(
- struct rhash_head *he;
- unsigned int hash;
-
-- rcu_read_lock();
--
- tbl = rht_dereference_rcu(ht->tbl, ht);
- restart:
- hash = rht_key_hashfn(ht, tbl, key, params);
-@@ -547,8 +536,7 @@ restart:
- params.obj_cmpfn(&arg, rht_obj(ht, he)) :
- rhashtable_compare(&arg, rht_obj(ht, he)))
- continue;
-- rcu_read_unlock();
-- return rht_obj(ht, he);
-+ return he;
- }
-
- /* Ensure we see any new tables. */
-@@ -557,13 +545,64 @@ restart:
- tbl = rht_dereference_rcu(tbl->future_tbl, ht);
- if (unlikely(tbl))
- goto restart;
-- rcu_read_unlock();
-
- return NULL;
- }
-
--/* Internal function, please use rhashtable_insert_fast() instead */
--static inline int __rhashtable_insert_fast(
-+/**
-+ * rhashtable_lookup - search hash table
-+ * @ht: hash table
-+ * @key: the pointer to the key
-+ * @params: hash table parameters
-+ *
-+ * Computes the hash value for the key and traverses the bucket chain looking
-+ * for a entry with an identical key. The first matching entry is returned.
-+ *
-+ * This must only be called under the RCU read lock.
-+ *
-+ * Returns the first entry on which the compare function returned true.
-+ */
-+static inline void *rhashtable_lookup(
-+ struct rhashtable *ht, const void *key,
-+ const struct rhashtable_params params)
-+{
-+ struct rhash_head *he = __rhashtable_lookup(ht, key, params);
-+
-+ return he ? rht_obj(ht, he) : NULL;
-+}
-+
-+/**
-+ * rhashtable_lookup_fast - search hash table, without RCU read lock
-+ * @ht: hash table
-+ * @key: the pointer to the key
-+ * @params: hash table parameters
-+ *
-+ * Computes the hash value for the key and traverses the bucket chain looking
-+ * for a entry with an identical key. The first matching entry is returned.
-+ *
-+ * Only use this function when you have other mechanisms guaranteeing
-+ * that the object won't go away after the RCU read lock is released.
-+ *
-+ * Returns the first entry on which the compare function returned true.
-+ */
-+static inline void *rhashtable_lookup_fast(
-+ struct rhashtable *ht, const void *key,
-+ const struct rhashtable_params params)
-+{
-+ void *obj;
-+
-+ rcu_read_lock();
-+ obj = rhashtable_lookup(ht, key, params);
-+ rcu_read_unlock();
-+
-+ return obj;
-+}
-+
-+/* Internal function, please use rhashtable_insert_fast() instead. This
-+ * function returns the existing element already in hashes in there is a clash,
-+ * otherwise it returns an error via ERR_PTR().
-+ */
-+static inline void *__rhashtable_insert_fast(
- struct rhashtable *ht, const void *key, struct rhash_head *obj,
- const struct rhashtable_params params)
- {
-@@ -576,6 +615,7 @@ static inline int __rhashtable_insert_fast(
- spinlock_t *lock;
- unsigned int elasticity;
- unsigned int hash;
-+ void *data = NULL;
- int err;
-
- restart:
-@@ -600,11 +640,14 @@ restart:
-
- new_tbl = rht_dereference_rcu(tbl->future_tbl, ht);
- if (unlikely(new_tbl)) {
-- tbl = rhashtable_insert_slow(ht, key, obj, new_tbl);
-+ tbl = rhashtable_insert_slow(ht, key, obj, new_tbl, &data);
- if (!IS_ERR_OR_NULL(tbl))
- goto slow_path;
-
- err = PTR_ERR(tbl);
-+ if (err == -EEXIST)
-+ err = 0;
-+
- goto out;
- }
-
-@@ -618,25 +661,25 @@ slow_path:
- err = rhashtable_insert_rehash(ht, tbl);
- rcu_read_unlock();
- if (err)
-- return err;
-+ return ERR_PTR(err);
-
- goto restart;
- }
-
-- err = -EEXIST;
-+ err = 0;
- elasticity = ht->elasticity;
- rht_for_each(head, tbl, hash) {
- if (key &&
- unlikely(!(params.obj_cmpfn ?
- params.obj_cmpfn(&arg, rht_obj(ht, head)) :
-- rhashtable_compare(&arg, rht_obj(ht, head)))))
-+ rhashtable_compare(&arg, rht_obj(ht, head))))) {
-+ data = rht_obj(ht, head);
- goto out;
-+ }
- if (!--elasticity)
- goto slow_path;
- }
-
-- err = 0;
--
- head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash);
-
- RCU_INIT_POINTER(obj->next, head);
-@@ -651,7 +694,7 @@ out:
- spin_unlock_bh(lock);
- rcu_read_unlock();
-
-- return err;
-+ return err ? ERR_PTR(err) : data;
- }
-
- /**
-@@ -674,7 +717,13 @@ static inline int rhashtable_insert_fast(
- struct rhashtable *ht, struct rhash_head *obj,
- const struct rhashtable_params params)
- {
-- return __rhashtable_insert_fast(ht, NULL, obj, params);
-+ void *ret;
-+
-+ ret = __rhashtable_insert_fast(ht, NULL, obj, params);
-+ if (IS_ERR(ret))
-+ return PTR_ERR(ret);
-+
-+ return ret == NULL ? 0 : -EEXIST;
- }
-
- /**
-@@ -703,11 +752,15 @@ static inline int rhashtable_lookup_insert_fast(
- const struct rhashtable_params params)
- {
- const char *key = rht_obj(ht, obj);
-+ void *ret;
-
- BUG_ON(ht->p.obj_hashfn);
-
-- return __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj,
-- params);
-+ ret = __rhashtable_insert_fast(ht, key + ht->p.key_offset, obj, params);
-+ if (IS_ERR(ret))
-+ return PTR_ERR(ret);
-+
-+ return ret == NULL ? 0 : -EEXIST;
- }
-
- /**
-@@ -735,6 +788,32 @@ static inline int rhashtable_lookup_insert_fast(
- static inline int rhashtable_lookup_insert_key(
- struct rhashtable *ht, const void *key, struct rhash_head *obj,
- const struct rhashtable_params params)
-+{
-+ void *ret;
-+
-+ BUG_ON(!ht->p.obj_hashfn || !key);
-+
-+ ret = __rhashtable_insert_fast(ht, key, obj, params);
-+ if (IS_ERR(ret))
-+ return PTR_ERR(ret);
-+
-+ return ret == NULL ? 0 : -EEXIST;
-+}
-+
-+/**
-+ * rhashtable_lookup_get_insert_key - lookup and insert object into hash table
-+ * @ht: hash table
-+ * @obj: pointer to hash head inside object
-+ * @params: hash table parameters
-+ * @data: pointer to element data already in hashes
-+ *
-+ * Just like rhashtable_lookup_insert_key(), but this function returns the
-+ * object if it exists, NULL if it does not and the insertion was successful,
-+ * and an ERR_PTR otherwise.
-+ */
-+static inline void *rhashtable_lookup_get_insert_key(
-+ struct rhashtable *ht, const void *key, struct rhash_head *obj,
-+ const struct rhashtable_params params)
- {
- BUG_ON(!ht->p.obj_hashfn || !key);
-
-diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index 6d39d81d3c38..502787c29ce9 100644
---- a/include/linux/skbuff.h
-+++ b/include/linux/skbuff.h
-@@ -556,9 +556,14 @@ struct sk_buff {
- struct skb_mstamp skb_mstamp;
- };
- };
-- struct rb_node rbnode; /* used in netem & tcp stack */
-+ struct rb_node rbnode; /* used in netem, ip4 defrag, and tcp stack */
- };
-- struct sock *sk;
-+
-+ union {
-+ struct sock *sk;
-+ int ip_defrag_offset;
-+ };
-+
- struct net_device *dev;
-
- /*
-@@ -2273,7 +2278,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
- kfree_skb(skb);
- }
-
--void skb_rbtree_purge(struct rb_root *root);
-+unsigned int skb_rbtree_purge(struct rb_root *root);
-
- void *netdev_alloc_frag(unsigned int fragsz);
-
-@@ -2791,6 +2796,7 @@ static inline unsigned char *skb_push_rcsum(struct sk_buff *skb,
- return skb->data;
- }
-
-+int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len);
- /**
- * pskb_trim_rcsum - trim received skb and update checksum
- * @skb: buffer to trim
-@@ -2805,9 +2811,7 @@ 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);
-+ return pskb_trim_rcsum_slow(skb, len);
- }
-
- #define rb_to_skb(rb) rb_entry_safe(rb, struct sk_buff, rbnode)
-diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
-index c26a6e4dc306..6260ec146142 100644
---- a/include/net/inet_frag.h
-+++ b/include/net/inet_frag.h
-@@ -1,13 +1,19 @@
- #ifndef __NET_FRAG_H__
- #define __NET_FRAG_H__
-
-+#include
-+
- struct netns_frags {
-- /* Keep atomic mem on separate cachelines in structs that include it */
-- atomic_t mem ____cacheline_aligned_in_smp;
- /* sysctls */
-+ long high_thresh;
-+ long low_thresh;
- int timeout;
-- int high_thresh;
-- int low_thresh;
-+ struct inet_frags *f;
-+
-+ struct rhashtable rhashtable ____cacheline_aligned_in_smp;
-+
-+ /* Keep atomic mem on separate cachelines in structs that include it */
-+ atomic_long_t mem ____cacheline_aligned_in_smp;
- };
-
- /**
-@@ -23,74 +29,68 @@ enum {
- INET_FRAG_COMPLETE = BIT(2),
- };
-
-+struct frag_v4_compare_key {
-+ __be32 saddr;
-+ __be32 daddr;
-+ u32 user;
-+ u32 vif;
-+ __be16 id;
-+ u16 protocol;
-+};
-+
-+struct frag_v6_compare_key {
-+ struct in6_addr saddr;
-+ struct in6_addr daddr;
-+ u32 user;
-+ __be32 id;
-+ u32 iif;
-+};
-+
- /**
- * struct inet_frag_queue - fragment queue
- *
-- * @lock: spinlock protecting the queue
-+ * @node: rhash node
-+ * @key: keys identifying this frag.
- * @timer: queue expiration timer
-- * @list: hash bucket list
-+ * @lock: spinlock protecting this frag
- * @refcnt: reference count of the queue
- * @fragments: received fragments head
-+ * @rb_fragments: received fragments rb-tree root
- * @fragments_tail: received fragments tail
-+ * @last_run_head: the head of the last "run". see ip_fragment.c
- * @stamp: timestamp of the last received fragment
- * @len: total length of the original datagram
- * @meat: length of received fragments so far
- * @flags: fragment queue flags
- * @max_size: maximum received fragment size
- * @net: namespace that this frag belongs to
-- * @list_evictor: list of queues to forcefully evict (e.g. due to low memory)
-+ * @rcu: rcu head for freeing deferall
- */
- struct inet_frag_queue {
-- spinlock_t lock;
-+ struct rhash_head node;
-+ union {
-+ struct frag_v4_compare_key v4;
-+ struct frag_v6_compare_key v6;
-+ } key;
- struct timer_list timer;
-- struct hlist_node list;
-+ spinlock_t lock;
- atomic_t refcnt;
-- struct sk_buff *fragments;
-+ struct sk_buff *fragments; /* Used in IPv6. */
-+ struct rb_root rb_fragments; /* Used in IPv4. */
- struct sk_buff *fragments_tail;
-+ struct sk_buff *last_run_head;
- ktime_t stamp;
- int len;
- int meat;
- __u8 flags;
- u16 max_size;
-- struct netns_frags *net;
-- struct hlist_node list_evictor;
--};
--
--#define INETFRAGS_HASHSZ 1024
--
--/* averaged:
-- * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
-- * rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
-- * struct frag_queue))
-- */
--#define INETFRAGS_MAXDEPTH 128
--
--struct inet_frag_bucket {
-- struct hlist_head chain;
-- spinlock_t chain_lock;
-+ struct netns_frags *net;
-+ struct rcu_head rcu;
- };
-
- struct inet_frags {
-- struct inet_frag_bucket hash[INETFRAGS_HASHSZ];
--
-- struct work_struct frags_work;
-- unsigned int next_bucket;
-- unsigned long last_rebuild_jiffies;
-- bool rebuild;
--
-- /* The first call to hashfn is responsible to initialize
-- * rnd. This is best done with net_get_random_once.
-- *
-- * rnd_seqlock is used to let hash insertion detect
-- * when it needs to re-lookup the hash chain to use.
-- */
-- u32 rnd;
-- seqlock_t rnd_seqlock;
- int qsize;
-
-- unsigned int (*hashfn)(const struct inet_frag_queue *);
-- bool (*match)(const struct inet_frag_queue *q,
-- const void *arg);
- void (*constructor)(struct inet_frag_queue *q,
- const void *arg);
- void (*destructor)(struct inet_frag_queue *);
-@@ -98,56 +98,47 @@ struct inet_frags {
- void (*frag_expire)(unsigned long data);
- struct kmem_cache *frags_cachep;
- const char *frags_cache_name;
-+ struct rhashtable_params rhash_params;
- };
-
- int inet_frags_init(struct inet_frags *);
- void inet_frags_fini(struct inet_frags *);
-
--static inline void inet_frags_init_net(struct netns_frags *nf)
-+static inline int inet_frags_init_net(struct netns_frags *nf)
- {
-- atomic_set(&nf->mem, 0);
-+ atomic_long_set(&nf->mem, 0);
-+ return rhashtable_init(&nf->rhashtable, &nf->f->rhash_params);
- }
--void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
-+void inet_frags_exit_net(struct netns_frags *nf);
-
--void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
--void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f);
--struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
-- struct inet_frags *f, void *key, unsigned int hash);
-+void inet_frag_kill(struct inet_frag_queue *q);
-+void inet_frag_destroy(struct inet_frag_queue *q);
-+struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key);
-
--void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
-- const char *prefix);
-+/* Free all skbs in the queue; return the sum of their truesizes. */
-+unsigned int inet_frag_rbtree_purge(struct rb_root *root);
-
--static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
-+static inline void inet_frag_put(struct inet_frag_queue *q)
- {
- if (atomic_dec_and_test(&q->refcnt))
-- inet_frag_destroy(q, f);
--}
--
--static inline bool inet_frag_evicting(struct inet_frag_queue *q)
--{
-- return !hlist_unhashed(&q->list_evictor);
-+ inet_frag_destroy(q);
- }
-
- /* Memory Tracking Functions. */
-
--static inline int frag_mem_limit(struct netns_frags *nf)
--{
-- return atomic_read(&nf->mem);
--}
--
--static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
-+static inline long frag_mem_limit(const struct netns_frags *nf)
- {
-- atomic_sub(i, &nf->mem);
-+ return atomic_long_read(&nf->mem);
- }
-
--static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
-+static inline void sub_frag_mem_limit(struct netns_frags *nf, long val)
- {
-- atomic_add(i, &nf->mem);
-+ atomic_long_sub(val, &nf->mem);
- }
-
--static inline int sum_frag_mem_limit(struct netns_frags *nf)
-+static inline void add_frag_mem_limit(struct netns_frags *nf, long val)
- {
-- return atomic_read(&nf->mem);
-+ atomic_long_add(val, &nf->mem);
- }
-
- /* RFC 3168 support :
-diff --git a/include/net/ip.h b/include/net/ip.h
-index 0530bcdbc212..7b968927477d 100644
---- a/include/net/ip.h
-+++ b/include/net/ip.h
-@@ -524,7 +524,6 @@ static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *s
- return skb;
- }
- #endif
--int ip_frag_mem(struct net *net);
-
- /*
- * Functions provided by ip_forward.c
-diff --git a/include/net/ipv6.h b/include/net/ipv6.h
-index 0e01d570fa22..c07cf9596b6f 100644
---- a/include/net/ipv6.h
-+++ b/include/net/ipv6.h
-@@ -320,13 +320,6 @@ static inline bool ipv6_accept_ra(struct inet6_dev *idev)
- idev->cnf.accept_ra;
- }
-
--#if IS_ENABLED(CONFIG_IPV6)
--static inline int ip6_frag_mem(struct net *net)
--{
-- return sum_frag_mem_limit(&net->ipv6.frags);
--}
--#endif
--
- #define IPV6_FRAG_HIGH_THRESH (4 * 1024*1024) /* 4194304 */
- #define IPV6_FRAG_LOW_THRESH (3 * 1024*1024) /* 3145728 */
- #define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */
-@@ -505,17 +498,8 @@ enum ip6_defrag_users {
- __IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
- };
-
--struct ip6_create_arg {
-- __be32 id;
-- u32 user;
-- const struct in6_addr *src;
-- const struct in6_addr *dst;
-- int iif;
-- u8 ecn;
--};
--
- void ip6_frag_init(struct inet_frag_queue *q, const void *a);
--bool ip6_frag_match(const struct inet_frag_queue *q, const void *a);
-+extern const struct rhashtable_params ip6_rhash_params;
-
- /*
- * Equivalent of ipv4 struct ip
-@@ -523,19 +507,13 @@ bool ip6_frag_match(const struct inet_frag_queue *q, const void *a);
- struct frag_queue {
- struct inet_frag_queue q;
-
-- __be32 id; /* fragment id */
-- u32 user;
-- struct in6_addr saddr;
-- struct in6_addr daddr;
--
- int iif;
- unsigned int csum;
- __u16 nhoffset;
- u8 ecn;
- };
-
--void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
-- struct inet_frags *frags);
-+void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq);
-
- static inline bool ipv6_addr_any(const struct in6_addr *a)
- {
-diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
-index 25a9ad8bcef1..9de808ebce05 100644
---- a/include/uapi/linux/snmp.h
-+++ b/include/uapi/linux/snmp.h
-@@ -55,6 +55,7 @@ enum
- IPSTATS_MIB_ECT1PKTS, /* InECT1Pkts */
- IPSTATS_MIB_ECT0PKTS, /* InECT0Pkts */
- IPSTATS_MIB_CEPKTS, /* InCEPkts */
-+ IPSTATS_MIB_REASM_OVERLAPS, /* ReasmOverlaps */
- __IPSTATS_MIB_MAX
- };
-
-diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
-index 8a62cbfe1f2f..4e886ccd40db 100644
---- a/kernel/rcu/tree.c
-+++ b/kernel/rcu/tree.c
-@@ -3817,7 +3817,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp)
- continue;
- rdp = per_cpu_ptr(rsp->rda, cpu);
- pr_cont(" %d-%c%c%c", cpu,
-- "O."[cpu_online(cpu)],
-+ "O."[!!cpu_online(cpu)],
- "o."[!!(rdp->grpmask & rnp->expmaskinit)],
- "N."[!!(rdp->grpmask & rnp->expmaskinitnext)]);
- }
-diff --git a/lib/rhashtable.c b/lib/rhashtable.c
-index 37ea94b636a3..7bb8649429bf 100644
---- a/lib/rhashtable.c
-+++ b/lib/rhashtable.c
-@@ -250,8 +250,10 @@ static int rhashtable_rehash_table(struct rhashtable *ht)
- if (!new_tbl)
- return 0;
-
-- for (old_hash = 0; old_hash < old_tbl->size; old_hash++)
-+ for (old_hash = 0; old_hash < old_tbl->size; old_hash++) {
- rhashtable_rehash_chain(ht, old_hash);
-+ cond_resched();
-+ }
-
- /* Publish the new table pointer. */
- rcu_assign_pointer(ht->tbl, new_tbl);
-@@ -441,7 +443,8 @@ EXPORT_SYMBOL_GPL(rhashtable_insert_rehash);
- struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
- const void *key,
- struct rhash_head *obj,
-- struct bucket_table *tbl)
-+ struct bucket_table *tbl,
-+ void **data)
- {
- struct rhash_head *head;
- unsigned int hash;
-@@ -452,8 +455,11 @@ struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
- spin_lock_nested(rht_bucket_lock(tbl, hash), SINGLE_DEPTH_NESTING);
-
- err = -EEXIST;
-- if (key && rhashtable_lookup_fast(ht, key, ht->p))
-- goto exit;
-+ if (key) {
-+ *data = rhashtable_lookup_fast(ht, key, ht->p);
-+ if (*data)
-+ goto exit;
-+ }
-
- err = -E2BIG;
- if (unlikely(rht_grow_above_max(ht, tbl)))
-@@ -838,6 +844,7 @@ void rhashtable_free_and_destroy(struct rhashtable *ht,
- for (i = 0; i < tbl->size; i++) {
- struct rhash_head *pos, *next;
-
-+ cond_resched();
- for (pos = rht_dereference(tbl->buckets[i], ht),
- next = !rht_is_a_nulls(pos) ?
- rht_dereference(pos->next, ht) : NULL;
-diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index 8a57bbaf7452..fea7c24e99d0 100644
---- a/net/core/skbuff.c
-+++ b/net/core/skbuff.c
-@@ -1502,6 +1502,21 @@ done:
- }
- EXPORT_SYMBOL(___pskb_trim);
-
-+/* Note : use pskb_trim_rcsum() instead of calling this directly
-+ */
-+int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
-+{
-+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
-+ int delta = skb->len - len;
-+
-+ skb->csum = csum_block_sub(skb->csum,
-+ skb_checksum(skb, len, delta, 0),
-+ len);
-+ }
-+ return __pskb_trim(skb, len);
-+}
-+EXPORT_SYMBOL(pskb_trim_rcsum_slow);
-+
- /**
- * __pskb_pull_tail - advance tail of skb header
- * @skb: buffer to reallocate
-@@ -2380,23 +2395,27 @@ EXPORT_SYMBOL(skb_queue_purge);
- /**
- * skb_rbtree_purge - empty a skb rbtree
- * @root: root of the rbtree to empty
-+ * Return value: the sum of truesizes of all purged skbs.
- *
- * Delete all buffers on an &sk_buff rbtree. Each buffer is removed from
- * the list and one reference dropped. This function does not take
- * any lock. Synchronization should be handled by the caller (e.g., TCP
- * out-of-order queue is protected by the socket lock).
- */
--void skb_rbtree_purge(struct rb_root *root)
-+unsigned int skb_rbtree_purge(struct rb_root *root)
- {
- struct rb_node *p = rb_first(root);
-+ unsigned int sum = 0;
-
- while (p) {
- struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode);
-
- p = rb_next(p);
- rb_erase(&skb->rbnode, root);
-+ sum += skb->truesize;
- kfree_skb(skb);
- }
-+ return sum;
- }
-
- /**
-diff --git a/net/ieee802154/6lowpan/6lowpan_i.h b/net/ieee802154/6lowpan/6lowpan_i.h
-index b4e17a7c0df0..fdbebe51446f 100644
---- a/net/ieee802154/6lowpan/6lowpan_i.h
-+++ b/net/ieee802154/6lowpan/6lowpan_i.h
-@@ -16,37 +16,19 @@ typedef unsigned __bitwise__ lowpan_rx_result;
- #define LOWPAN_DISPATCH_FRAG1 0xc0
- #define LOWPAN_DISPATCH_FRAGN 0xe0
-
--struct lowpan_create_arg {
-+struct frag_lowpan_compare_key {
- u16 tag;
- u16 d_size;
-- const struct ieee802154_addr *src;
-- const struct ieee802154_addr *dst;
-+ struct ieee802154_addr src;
-+ struct ieee802154_addr dst;
- };
-
--/* Equivalent of ipv4 struct ip
-+/* Equivalent of ipv4 struct ipq
- */
- struct lowpan_frag_queue {
- struct inet_frag_queue q;
--
-- u16 tag;
-- u16 d_size;
-- struct ieee802154_addr saddr;
-- struct ieee802154_addr daddr;
- };
-
--static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a)
--{
-- switch (a->mode) {
-- case IEEE802154_ADDR_LONG:
-- return (((__force u64)a->extended_addr) >> 32) ^
-- (((__force u64)a->extended_addr) & 0xffffffff);
-- case IEEE802154_ADDR_SHORT:
-- return (__force u32)(a->short_addr);
-- default:
-- return 0;
-- }
--}
--
- /* private device info */
- struct lowpan_dev_info {
- struct net_device *wdev; /* wpan device ptr */
-diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
-index 12e8cf4bda9f..6183730d38db 100644
---- a/net/ieee802154/6lowpan/reassembly.c
-+++ b/net/ieee802154/6lowpan/reassembly.c
-@@ -37,47 +37,15 @@ static struct inet_frags lowpan_frags;
- static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
- struct sk_buff *prev, struct net_device *ldev);
-
--static unsigned int lowpan_hash_frag(u16 tag, u16 d_size,
-- const struct ieee802154_addr *saddr,
-- const struct ieee802154_addr *daddr)
--{
-- net_get_random_once(&lowpan_frags.rnd, sizeof(lowpan_frags.rnd));
-- return jhash_3words(ieee802154_addr_hash(saddr),
-- ieee802154_addr_hash(daddr),
-- (__force u32)(tag + (d_size << 16)),
-- lowpan_frags.rnd);
--}
--
--static unsigned int lowpan_hashfn(const struct inet_frag_queue *q)
--{
-- const struct lowpan_frag_queue *fq;
--
-- fq = container_of(q, struct lowpan_frag_queue, q);
-- return lowpan_hash_frag(fq->tag, fq->d_size, &fq->saddr, &fq->daddr);
--}
--
--static bool lowpan_frag_match(const struct inet_frag_queue *q, const void *a)
--{
-- const struct lowpan_frag_queue *fq;
-- const struct lowpan_create_arg *arg = a;
--
-- fq = container_of(q, struct lowpan_frag_queue, q);
-- return fq->tag == arg->tag && fq->d_size == arg->d_size &&
-- ieee802154_addr_equal(&fq->saddr, arg->src) &&
-- ieee802154_addr_equal(&fq->daddr, arg->dst);
--}
--
- static void lowpan_frag_init(struct inet_frag_queue *q, const void *a)
- {
-- const struct lowpan_create_arg *arg = a;
-+ const struct frag_lowpan_compare_key *key = a;
- struct lowpan_frag_queue *fq;
-
- fq = container_of(q, struct lowpan_frag_queue, q);
-
-- fq->tag = arg->tag;
-- fq->d_size = arg->d_size;
-- fq->saddr = *arg->src;
-- fq->daddr = *arg->dst;
-+ BUILD_BUG_ON(sizeof(*key) > sizeof(q->key));
-+ memcpy(&q->key, key, sizeof(*key));
- }
-
- static void lowpan_frag_expire(unsigned long data)
-@@ -93,10 +61,10 @@ static void lowpan_frag_expire(unsigned long data)
- if (fq->q.flags & INET_FRAG_COMPLETE)
- goto out;
-
-- inet_frag_kill(&fq->q, &lowpan_frags);
-+ inet_frag_kill(&fq->q);
- out:
- spin_unlock(&fq->q.lock);
-- inet_frag_put(&fq->q, &lowpan_frags);
-+ inet_frag_put(&fq->q);
- }
-
- static inline struct lowpan_frag_queue *
-@@ -104,25 +72,20 @@ fq_find(struct net *net, const struct lowpan_802154_cb *cb,
- const struct ieee802154_addr *src,
- const struct ieee802154_addr *dst)
- {
-- struct inet_frag_queue *q;
-- struct lowpan_create_arg arg;
-- unsigned int hash;
- struct netns_ieee802154_lowpan *ieee802154_lowpan =
- net_ieee802154_lowpan(net);
-+ struct frag_lowpan_compare_key key = {};
-+ struct inet_frag_queue *q;
-
-- arg.tag = cb->d_tag;
-- arg.d_size = cb->d_size;
-- arg.src = src;
-- arg.dst = dst;
--
-- hash = lowpan_hash_frag(cb->d_tag, cb->d_size, src, dst);
-+ key.tag = cb->d_tag;
-+ key.d_size = cb->d_size;
-+ key.src = *src;
-+ key.dst = *dst;
-
-- q = inet_frag_find(&ieee802154_lowpan->frags,
-- &lowpan_frags, &arg, hash);
-- if (IS_ERR_OR_NULL(q)) {
-- inet_frag_maybe_warn_overflow(q, pr_fmt());
-+ q = inet_frag_find(&ieee802154_lowpan->frags, &key);
-+ if (!q)
- return NULL;
-- }
-+
- return container_of(q, struct lowpan_frag_queue, q);
- }
-
-@@ -229,7 +192,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev,
- struct sk_buff *fp, *head = fq->q.fragments;
- int sum_truesize;
-
-- inet_frag_kill(&fq->q, &lowpan_frags);
-+ inet_frag_kill(&fq->q);
-
- /* Make the one we just received the head. */
- if (prev) {
-@@ -408,7 +371,7 @@ int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type)
- struct lowpan_frag_queue *fq;
- struct net *net = dev_net(skb->dev);
- struct lowpan_802154_cb *cb = lowpan_802154_cb(skb);
-- struct ieee802154_hdr hdr;
-+ struct ieee802154_hdr hdr = {};
- int err;
-
- if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
-@@ -437,7 +400,7 @@ int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type)
- ret = lowpan_frag_queue(fq, skb, frag_type);
- spin_unlock(&fq->q.lock);
-
-- inet_frag_put(&fq->q, &lowpan_frags);
-+ inet_frag_put(&fq->q);
- return ret;
- }
-
-@@ -447,24 +410,22 @@ err:
- }
-
- #ifdef CONFIG_SYSCTL
--static int zero;
-
- static struct ctl_table lowpan_frags_ns_ctl_table[] = {
- {
- .procname = "6lowpanfrag_high_thresh",
- .data = &init_net.ieee802154_lowpan.frags.high_thresh,
-- .maxlen = sizeof(int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra1 = &init_net.ieee802154_lowpan.frags.low_thresh
- },
- {
- .procname = "6lowpanfrag_low_thresh",
- .data = &init_net.ieee802154_lowpan.frags.low_thresh,
-- .maxlen = sizeof(int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-- .extra1 = &zero,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra2 = &init_net.ieee802154_lowpan.frags.high_thresh
- },
- {
-@@ -580,14 +541,20 @@ static int __net_init lowpan_frags_init_net(struct net *net)
- {
- struct netns_ieee802154_lowpan *ieee802154_lowpan =
- net_ieee802154_lowpan(net);
-+ int res;
-
- ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
- ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH;
- ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT;
-+ ieee802154_lowpan->frags.f = &lowpan_frags;
-
-- inet_frags_init_net(&ieee802154_lowpan->frags);
--
-- return lowpan_frags_ns_sysctl_register(net);
-+ res = inet_frags_init_net(&ieee802154_lowpan->frags);
-+ if (res < 0)
-+ return res;
-+ res = lowpan_frags_ns_sysctl_register(net);
-+ if (res < 0)
-+ inet_frags_exit_net(&ieee802154_lowpan->frags);
-+ return res;
- }
-
- static void __net_exit lowpan_frags_exit_net(struct net *net)
-@@ -596,7 +563,7 @@ static void __net_exit lowpan_frags_exit_net(struct net *net)
- net_ieee802154_lowpan(net);
-
- lowpan_frags_ns_sysctl_unregister(net);
-- inet_frags_exit_net(&ieee802154_lowpan->frags, &lowpan_frags);
-+ inet_frags_exit_net(&ieee802154_lowpan->frags);
- }
-
- static struct pernet_operations lowpan_frags_ops = {
-@@ -604,33 +571,64 @@ static struct pernet_operations lowpan_frags_ops = {
- .exit = lowpan_frags_exit_net,
- };
-
--int __init lowpan_net_frag_init(void)
-+static u32 lowpan_key_hashfn(const void *data, u32 len, u32 seed)
- {
-- int ret;
-+ return jhash2(data,
-+ sizeof(struct frag_lowpan_compare_key) / sizeof(u32), seed);
-+}
-
-- ret = lowpan_frags_sysctl_register();
-- if (ret)
-- return ret;
-+static u32 lowpan_obj_hashfn(const void *data, u32 len, u32 seed)
-+{
-+ const struct inet_frag_queue *fq = data;
-
-- ret = register_pernet_subsys(&lowpan_frags_ops);
-- if (ret)
-- goto err_pernet;
-+ return jhash2((const u32 *)&fq->key,
-+ sizeof(struct frag_lowpan_compare_key) / sizeof(u32), seed);
-+}
-+
-+static int lowpan_obj_cmpfn(struct rhashtable_compare_arg *arg, const void *ptr)
-+{
-+ const struct frag_lowpan_compare_key *key = arg->key;
-+ const struct inet_frag_queue *fq = ptr;
-+
-+ return !!memcmp(&fq->key, key, sizeof(*key));
-+}
-+
-+static const struct rhashtable_params lowpan_rhash_params = {
-+ .head_offset = offsetof(struct inet_frag_queue, node),
-+ .hashfn = lowpan_key_hashfn,
-+ .obj_hashfn = lowpan_obj_hashfn,
-+ .obj_cmpfn = lowpan_obj_cmpfn,
-+ .automatic_shrinking = true,
-+};
-+
-+int __init lowpan_net_frag_init(void)
-+{
-+ int ret;
-
-- lowpan_frags.hashfn = lowpan_hashfn;
- lowpan_frags.constructor = lowpan_frag_init;
- lowpan_frags.destructor = NULL;
- lowpan_frags.skb_free = NULL;
- lowpan_frags.qsize = sizeof(struct frag_queue);
-- lowpan_frags.match = lowpan_frag_match;
- lowpan_frags.frag_expire = lowpan_frag_expire;
- lowpan_frags.frags_cache_name = lowpan_frags_cache_name;
-+ lowpan_frags.rhash_params = lowpan_rhash_params;
- ret = inet_frags_init(&lowpan_frags);
- if (ret)
-- goto err_pernet;
-+ goto out;
-
-+ ret = lowpan_frags_sysctl_register();
-+ if (ret)
-+ goto err_sysctl;
-+
-+ ret = register_pernet_subsys(&lowpan_frags_ops);
-+ if (ret)
-+ goto err_pernet;
-+out:
- return ret;
- err_pernet:
- lowpan_frags_sysctl_unregister();
-+err_sysctl:
-+ inet_frags_fini(&lowpan_frags);
- return ret;
- }
-
-diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
-index b2001b20e029..c03e5f5859e1 100644
---- a/net/ipv4/inet_fragment.c
-+++ b/net/ipv4/inet_fragment.c
-@@ -25,12 +25,6 @@
- #include
- #include
-
--#define INETFRAGS_EVICT_BUCKETS 128
--#define INETFRAGS_EVICT_MAX 512
--
--/* don't rebuild inetfrag table with new secret more often than this */
--#define INETFRAGS_MIN_REBUILD_INTERVAL (5 * HZ)
--
- /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements
- * Value : 0xff if frame should be dropped.
- * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field
-@@ -52,157 +46,8 @@ const u8 ip_frag_ecn_table[16] = {
- };
- EXPORT_SYMBOL(ip_frag_ecn_table);
-
--static unsigned int
--inet_frag_hashfn(const struct inet_frags *f, const struct inet_frag_queue *q)
--{
-- return f->hashfn(q) & (INETFRAGS_HASHSZ - 1);
--}
--
--static bool inet_frag_may_rebuild(struct inet_frags *f)
--{
-- return time_after(jiffies,
-- f->last_rebuild_jiffies + INETFRAGS_MIN_REBUILD_INTERVAL);
--}
--
--static void inet_frag_secret_rebuild(struct inet_frags *f)
--{
-- int i;
--
-- write_seqlock_bh(&f->rnd_seqlock);
--
-- if (!inet_frag_may_rebuild(f))
-- goto out;
--
-- get_random_bytes(&f->rnd, sizeof(u32));
--
-- for (i = 0; i < INETFRAGS_HASHSZ; i++) {
-- struct inet_frag_bucket *hb;
-- struct inet_frag_queue *q;
-- struct hlist_node *n;
--
-- hb = &f->hash[i];
-- spin_lock(&hb->chain_lock);
--
-- hlist_for_each_entry_safe(q, n, &hb->chain, list) {
-- unsigned int hval = inet_frag_hashfn(f, q);
--
-- if (hval != i) {
-- struct inet_frag_bucket *hb_dest;
--
-- hlist_del(&q->list);
--
-- /* Relink to new hash chain. */
-- hb_dest = &f->hash[hval];
--
-- /* This is the only place where we take
-- * another chain_lock while already holding
-- * one. As this will not run concurrently,
-- * we cannot deadlock on hb_dest lock below, if its
-- * already locked it will be released soon since
-- * other caller cannot be waiting for hb lock
-- * that we've taken above.
-- */
-- spin_lock_nested(&hb_dest->chain_lock,
-- SINGLE_DEPTH_NESTING);
-- hlist_add_head(&q->list, &hb_dest->chain);
-- spin_unlock(&hb_dest->chain_lock);
-- }
-- }
-- spin_unlock(&hb->chain_lock);
-- }
--
-- f->rebuild = false;
-- f->last_rebuild_jiffies = jiffies;
--out:
-- write_sequnlock_bh(&f->rnd_seqlock);
--}
--
--static bool inet_fragq_should_evict(const struct inet_frag_queue *q)
--{
-- if (!hlist_unhashed(&q->list_evictor))
-- return false;
--
-- return q->net->low_thresh == 0 ||
-- frag_mem_limit(q->net) >= q->net->low_thresh;
--}
--
--static unsigned int
--inet_evict_bucket(struct inet_frags *f, struct inet_frag_bucket *hb)
--{
-- struct inet_frag_queue *fq;
-- struct hlist_node *n;
-- unsigned int evicted = 0;
-- HLIST_HEAD(expired);
--
-- spin_lock(&hb->chain_lock);
--
-- hlist_for_each_entry_safe(fq, n, &hb->chain, list) {
-- if (!inet_fragq_should_evict(fq))
-- continue;
--
-- if (!del_timer(&fq->timer))
-- continue;
--
-- hlist_add_head(&fq->list_evictor, &expired);
-- ++evicted;
-- }
--
-- spin_unlock(&hb->chain_lock);
--
-- hlist_for_each_entry_safe(fq, n, &expired, list_evictor)
-- f->frag_expire((unsigned long) fq);
--
-- return evicted;
--}
--
--static void inet_frag_worker(struct work_struct *work)
--{
-- unsigned int budget = INETFRAGS_EVICT_BUCKETS;
-- unsigned int i, evicted = 0;
-- struct inet_frags *f;
--
-- f = container_of(work, struct inet_frags, frags_work);
--
-- BUILD_BUG_ON(INETFRAGS_EVICT_BUCKETS >= INETFRAGS_HASHSZ);
--
-- local_bh_disable();
--
-- for (i = ACCESS_ONCE(f->next_bucket); budget; --budget) {
-- evicted += inet_evict_bucket(f, &f->hash[i]);
-- i = (i + 1) & (INETFRAGS_HASHSZ - 1);
-- if (evicted > INETFRAGS_EVICT_MAX)
-- break;
-- }
--
-- f->next_bucket = i;
--
-- local_bh_enable();
--
-- if (f->rebuild && inet_frag_may_rebuild(f))
-- inet_frag_secret_rebuild(f);
--}
--
--static void inet_frag_schedule_worker(struct inet_frags *f)
--{
-- if (unlikely(!work_pending(&f->frags_work)))
-- schedule_work(&f->frags_work);
--}
--
- int inet_frags_init(struct inet_frags *f)
- {
-- int i;
--
-- INIT_WORK(&f->frags_work, inet_frag_worker);
--
-- for (i = 0; i < INETFRAGS_HASHSZ; i++) {
-- struct inet_frag_bucket *hb = &f->hash[i];
--
-- spin_lock_init(&hb->chain_lock);
-- INIT_HLIST_HEAD(&hb->chain);
-- }
--
-- seqlock_init(&f->rnd_seqlock);
-- f->last_rebuild_jiffies = 0;
- f->frags_cachep = kmem_cache_create(f->frags_cache_name, f->qsize, 0, 0,
- NULL);
- if (!f->frags_cachep)
-@@ -214,73 +59,53 @@ EXPORT_SYMBOL(inet_frags_init);
-
- void inet_frags_fini(struct inet_frags *f)
- {
-- cancel_work_sync(&f->frags_work);
-+ /* We must wait that all inet_frag_destroy_rcu() have completed. */
-+ rcu_barrier();
-+
- kmem_cache_destroy(f->frags_cachep);
-+ f->frags_cachep = NULL;
- }
- EXPORT_SYMBOL(inet_frags_fini);
-
--void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
-+static void inet_frags_free_cb(void *ptr, void *arg)
- {
-- unsigned int seq;
-- int i;
-+ struct inet_frag_queue *fq = ptr;
-
-- nf->low_thresh = 0;
--
--evict_again:
-- local_bh_disable();
-- seq = read_seqbegin(&f->rnd_seqlock);
--
-- for (i = 0; i < INETFRAGS_HASHSZ ; i++)
-- inet_evict_bucket(f, &f->hash[i]);
--
-- local_bh_enable();
-- cond_resched();
--
-- if (read_seqretry(&f->rnd_seqlock, seq) ||
-- sum_frag_mem_limit(nf))
-- goto evict_again;
--}
--EXPORT_SYMBOL(inet_frags_exit_net);
--
--static struct inet_frag_bucket *
--get_frag_bucket_locked(struct inet_frag_queue *fq, struct inet_frags *f)
--__acquires(hb->chain_lock)
--{
-- struct inet_frag_bucket *hb;
-- unsigned int seq, hash;
--
-- restart:
-- seq = read_seqbegin(&f->rnd_seqlock);
--
-- hash = inet_frag_hashfn(f, fq);
-- hb = &f->hash[hash];
-+ /* If we can not cancel the timer, it means this frag_queue
-+ * is already disappearing, we have nothing to do.
-+ * Otherwise, we own a refcount until the end of this function.
-+ */
-+ if (!del_timer(&fq->timer))
-+ return;
-
-- spin_lock(&hb->chain_lock);
-- if (read_seqretry(&f->rnd_seqlock, seq)) {
-- spin_unlock(&hb->chain_lock);
-- goto restart;
-+ spin_lock_bh(&fq->lock);
-+ if (!(fq->flags & INET_FRAG_COMPLETE)) {
-+ fq->flags |= INET_FRAG_COMPLETE;
-+ atomic_dec(&fq->refcnt);
- }
-+ spin_unlock_bh(&fq->lock);
-
-- return hb;
-+ inet_frag_put(fq);
- }
-
--static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
-+void inet_frags_exit_net(struct netns_frags *nf)
- {
-- struct inet_frag_bucket *hb;
-+ nf->high_thresh = 0; /* prevent creation of new frags */
-
-- hb = get_frag_bucket_locked(fq, f);
-- hlist_del(&fq->list);
-- fq->flags |= INET_FRAG_COMPLETE;
-- spin_unlock(&hb->chain_lock);
-+ rhashtable_free_and_destroy(&nf->rhashtable, inet_frags_free_cb, NULL);
- }
-+EXPORT_SYMBOL(inet_frags_exit_net);
-
--void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
-+void inet_frag_kill(struct inet_frag_queue *fq)
- {
- if (del_timer(&fq->timer))
- atomic_dec(&fq->refcnt);
-
- if (!(fq->flags & INET_FRAG_COMPLETE)) {
-- fq_unlink(fq, f);
-+ struct netns_frags *nf = fq->net;
-+
-+ fq->flags |= INET_FRAG_COMPLETE;
-+ rhashtable_remove_fast(&nf->rhashtable, &fq->node, nf->f->rhash_params);
- atomic_dec(&fq->refcnt);
- }
- }
-@@ -294,11 +119,23 @@ static inline void frag_kfree_skb(struct netns_frags *nf, struct inet_frags *f,
- kfree_skb(skb);
- }
-
--void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f)
-+static void inet_frag_destroy_rcu(struct rcu_head *head)
-+{
-+ struct inet_frag_queue *q = container_of(head, struct inet_frag_queue,
-+ rcu);
-+ struct inet_frags *f = q->net->f;
-+
-+ if (f->destructor)
-+ f->destructor(q);
-+ kmem_cache_free(f->frags_cachep, q);
-+}
-+
-+void inet_frag_destroy(struct inet_frag_queue *q)
- {
- struct sk_buff *fp;
- struct netns_frags *nf;
- unsigned int sum, sum_truesize = 0;
-+ struct inet_frags *f;
-
- WARN_ON(!(q->flags & INET_FRAG_COMPLETE));
- WARN_ON(del_timer(&q->timer) != 0);
-@@ -306,64 +143,35 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f)
- /* Release all fragment data. */
- fp = q->fragments;
- nf = q->net;
-- while (fp) {
-- struct sk_buff *xp = fp->next;
--
-- sum_truesize += fp->truesize;
-- frag_kfree_skb(nf, f, fp);
-- fp = xp;
-+ f = nf->f;
-+ if (fp) {
-+ do {
-+ struct sk_buff *xp = fp->next;
-+
-+ sum_truesize += fp->truesize;
-+ frag_kfree_skb(nf, f, fp);
-+ fp = xp;
-+ } while (fp);
-+ } else {
-+ sum_truesize = inet_frag_rbtree_purge(&q->rb_fragments);
- }
- sum = sum_truesize + f->qsize;
-
-- if (f->destructor)
-- f->destructor(q);
-- kmem_cache_free(f->frags_cachep, q);
-+ call_rcu(&q->rcu, inet_frag_destroy_rcu);
-
- sub_frag_mem_limit(nf, sum);
- }
- EXPORT_SYMBOL(inet_frag_destroy);
-
--static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
-- struct inet_frag_queue *qp_in,
-- struct inet_frags *f,
-- void *arg)
--{
-- struct inet_frag_bucket *hb = get_frag_bucket_locked(qp_in, f);
-- struct inet_frag_queue *qp;
--
--#ifdef CONFIG_SMP
-- /* With SMP race we have to recheck hash table, because
-- * such entry could have been created on other cpu before
-- * we acquired hash bucket lock.
-- */
-- hlist_for_each_entry(qp, &hb->chain, list) {
-- if (qp->net == nf && f->match(qp, arg)) {
-- atomic_inc(&qp->refcnt);
-- spin_unlock(&hb->chain_lock);
-- qp_in->flags |= INET_FRAG_COMPLETE;
-- inet_frag_put(qp_in, f);
-- return qp;
-- }
-- }
--#endif
-- qp = qp_in;
-- if (!mod_timer(&qp->timer, jiffies + nf->timeout))
-- atomic_inc(&qp->refcnt);
--
-- atomic_inc(&qp->refcnt);
-- hlist_add_head(&qp->list, &hb->chain);
--
-- spin_unlock(&hb->chain_lock);
--
-- return qp;
--}
--
- static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
- struct inet_frags *f,
- void *arg)
- {
- struct inet_frag_queue *q;
-
-+ if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh)
-+ return NULL;
-+
- q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC);
- if (!q)
- return NULL;
-@@ -374,75 +182,52 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
-
- setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
- spin_lock_init(&q->lock);
-- atomic_set(&q->refcnt, 1);
-+ atomic_set(&q->refcnt, 3);
-
- return q;
- }
-
- static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
-- struct inet_frags *f,
-- void *arg)
-+ void *arg,
-+ struct inet_frag_queue **prev)
- {
-+ struct inet_frags *f = nf->f;
- struct inet_frag_queue *q;
-
- q = inet_frag_alloc(nf, f, arg);
-- if (!q)
-- return NULL;
--
-- return inet_frag_intern(nf, q, f, arg);
--}
--
--struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
-- struct inet_frags *f, void *key,
-- unsigned int hash)
--{
-- struct inet_frag_bucket *hb;
-- struct inet_frag_queue *q;
-- int depth = 0;
--
-- if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) {
-- inet_frag_schedule_worker(f);
-+ if (!q) {
-+ *prev = ERR_PTR(-ENOMEM);
- return NULL;
- }
--
-- if (frag_mem_limit(nf) > nf->low_thresh)
-- inet_frag_schedule_worker(f);
--
-- hash &= (INETFRAGS_HASHSZ - 1);
-- hb = &f->hash[hash];
--
-- spin_lock(&hb->chain_lock);
-- hlist_for_each_entry(q, &hb->chain, list) {
-- if (q->net == nf && f->match(q, key)) {
-- atomic_inc(&q->refcnt);
-- spin_unlock(&hb->chain_lock);
-- return q;
-- }
-- depth++;
-- }
-- spin_unlock(&hb->chain_lock);
--
-- if (depth <= INETFRAGS_MAXDEPTH)
-- return inet_frag_create(nf, f, key);
--
-- if (inet_frag_may_rebuild(f)) {
-- if (!f->rebuild)
-- f->rebuild = true;
-- inet_frag_schedule_worker(f);
-+ mod_timer(&q->timer, jiffies + nf->timeout);
-+
-+ *prev = rhashtable_lookup_get_insert_key(&nf->rhashtable, &q->key,
-+ &q->node, f->rhash_params);
-+ if (*prev) {
-+ q->flags |= INET_FRAG_COMPLETE;
-+ inet_frag_kill(q);
-+ inet_frag_destroy(q);
-+ return NULL;
- }
--
-- return ERR_PTR(-ENOBUFS);
-+ return q;
- }
--EXPORT_SYMBOL(inet_frag_find);
-+EXPORT_SYMBOL(inet_frag_create);
-
--void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
-- const char *prefix)
-+/* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */
-+struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key)
- {
-- static const char msg[] = "inet_frag_find: Fragment hash bucket"
-- " list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
-- ". Dropping fragment.\n";
-+ struct inet_frag_queue *fq = NULL, *prev;
-
-- if (PTR_ERR(q) == -ENOBUFS)
-- net_dbg_ratelimited("%s%s", prefix, msg);
-+ rcu_read_lock();
-+ prev = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params);
-+ if (!prev)
-+ fq = inet_frag_create(nf, key, &prev);
-+ if (prev && !IS_ERR(prev)) {
-+ fq = prev;
-+ if (!atomic_inc_not_zero(&fq->refcnt))
-+ fq = NULL;
-+ }
-+ rcu_read_unlock();
-+ return fq;
- }
--EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);
-+EXPORT_SYMBOL(inet_frag_find);
-diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
-index 72915658a6b1..9b09a9b5a4fe 100644
---- a/net/ipv4/ip_fragment.c
-+++ b/net/ipv4/ip_fragment.c
-@@ -58,27 +58,64 @@
- static int sysctl_ipfrag_max_dist __read_mostly = 64;
- static const char ip_frag_cache_name[] = "ip4-frags";
-
--struct ipfrag_skb_cb
--{
-+/* Use skb->cb to track consecutive/adjacent fragments coming at
-+ * the end of the queue. Nodes in the rb-tree queue will
-+ * contain "runs" of one or more adjacent fragments.
-+ *
-+ * Invariants:
-+ * - next_frag is NULL at the tail of a "run";
-+ * - the head of a "run" has the sum of all fragment lengths in frag_run_len.
-+ */
-+struct ipfrag_skb_cb {
- struct inet_skb_parm h;
-- int offset;
-+ struct sk_buff *next_frag;
-+ int frag_run_len;
- };
-
--#define FRAG_CB(skb) ((struct ipfrag_skb_cb *)((skb)->cb))
-+#define FRAG_CB(skb) ((struct ipfrag_skb_cb *)((skb)->cb))
-+
-+static void ip4_frag_init_run(struct sk_buff *skb)
-+{
-+ BUILD_BUG_ON(sizeof(struct ipfrag_skb_cb) > sizeof(skb->cb));
-+
-+ FRAG_CB(skb)->next_frag = NULL;
-+ FRAG_CB(skb)->frag_run_len = skb->len;
-+}
-+
-+/* Append skb to the last "run". */
-+static void ip4_frag_append_to_last_run(struct inet_frag_queue *q,
-+ struct sk_buff *skb)
-+{
-+ RB_CLEAR_NODE(&skb->rbnode);
-+ FRAG_CB(skb)->next_frag = NULL;
-+
-+ FRAG_CB(q->last_run_head)->frag_run_len += skb->len;
-+ FRAG_CB(q->fragments_tail)->next_frag = skb;
-+ q->fragments_tail = skb;
-+}
-+
-+/* Create a new "run" with the skb. */
-+static void ip4_frag_create_run(struct inet_frag_queue *q, struct sk_buff *skb)
-+{
-+ if (q->last_run_head)
-+ rb_link_node(&skb->rbnode, &q->last_run_head->rbnode,
-+ &q->last_run_head->rbnode.rb_right);
-+ else
-+ rb_link_node(&skb->rbnode, NULL, &q->rb_fragments.rb_node);
-+ rb_insert_color(&skb->rbnode, &q->rb_fragments);
-+
-+ ip4_frag_init_run(skb);
-+ q->fragments_tail = skb;
-+ q->last_run_head = skb;
-+}
-
- /* Describe an entry in the "incomplete datagrams" queue. */
- struct ipq {
- struct inet_frag_queue q;
-
-- u32 user;
-- __be32 saddr;
-- __be32 daddr;
-- __be16 id;
-- u8 protocol;
- u8 ecn; /* RFC3168 support */
- u16 max_df_size; /* largest frag with DF set seen */
- int iif;
-- int vif; /* L3 master device index */
- unsigned int rid;
- struct inet_peer *peer;
- };
-@@ -90,49 +127,9 @@ static u8 ip4_frag_ecn(u8 tos)
-
- static struct inet_frags ip4_frags;
-
--int ip_frag_mem(struct net *net)
--{
-- return sum_frag_mem_limit(&net->ipv4.frags);
--}
--
--static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
-- struct net_device *dev);
--
--struct ip4_create_arg {
-- struct iphdr *iph;
-- u32 user;
-- int vif;
--};
-+static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
-+ struct sk_buff *prev_tail, struct net_device *dev);
-
--static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
--{
-- net_get_random_once(&ip4_frags.rnd, sizeof(ip4_frags.rnd));
-- return jhash_3words((__force u32)id << 16 | prot,
-- (__force u32)saddr, (__force u32)daddr,
-- ip4_frags.rnd);
--}
--
--static unsigned int ip4_hashfn(const struct inet_frag_queue *q)
--{
-- const struct ipq *ipq;
--
-- ipq = container_of(q, struct ipq, q);
-- return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol);
--}
--
--static bool ip4_frag_match(const struct inet_frag_queue *q, const void *a)
--{
-- const struct ipq *qp;
-- const struct ip4_create_arg *arg = a;
--
-- qp = container_of(q, struct ipq, q);
-- return qp->id == arg->iph->id &&
-- qp->saddr == arg->iph->saddr &&
-- qp->daddr == arg->iph->daddr &&
-- qp->protocol == arg->iph->protocol &&
-- qp->user == arg->user &&
-- qp->vif == arg->vif;
--}
-
- static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
- {
-@@ -141,17 +138,12 @@ static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
- frags);
- struct net *net = container_of(ipv4, struct net, ipv4);
-
-- const struct ip4_create_arg *arg = a;
-+ const struct frag_v4_compare_key *key = a;
-
-- qp->protocol = arg->iph->protocol;
-- qp->id = arg->iph->id;
-- qp->ecn = ip4_frag_ecn(arg->iph->tos);
-- qp->saddr = arg->iph->saddr;
-- qp->daddr = arg->iph->daddr;
-- qp->vif = arg->vif;
-- qp->user = arg->user;
-+ q->key.v4 = *key;
-+ qp->ecn = 0;
- qp->peer = sysctl_ipfrag_max_dist ?
-- inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, arg->vif, 1) :
-+ inet_getpeer_v4(net->ipv4.peers, key->saddr, key->vif, 1) :
- NULL;
- }
-
-@@ -169,7 +161,7 @@ static void ip4_frag_free(struct inet_frag_queue *q)
-
- static void ipq_put(struct ipq *ipq)
- {
-- inet_frag_put(&ipq->q, &ip4_frags);
-+ inet_frag_put(&ipq->q);
- }
-
- /* Kill ipq entry. It is not destroyed immediately,
-@@ -177,7 +169,7 @@ static void ipq_put(struct ipq *ipq)
- */
- static void ipq_kill(struct ipq *ipq)
- {
-- inet_frag_kill(&ipq->q, &ip4_frags);
-+ inet_frag_kill(&ipq->q);
- }
-
- static bool frag_expire_skip_icmp(u32 user)
-@@ -194,8 +186,11 @@ static bool frag_expire_skip_icmp(u32 user)
- */
- static void ip_expire(unsigned long arg)
- {
-- struct ipq *qp;
-+ const struct iphdr *iph;
-+ struct sk_buff *head = NULL;
- struct net *net;
-+ struct ipq *qp;
-+ int err;
-
- qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
- net = container_of(qp->q.net, struct net, ipv4.frags);
-@@ -208,51 +203,65 @@ static void ip_expire(unsigned long arg)
-
- ipq_kill(qp);
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
-+ IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT);
-
-- if (!inet_frag_evicting(&qp->q)) {
-- struct sk_buff *clone, *head = qp->q.fragments;
-- const struct iphdr *iph;
-- int err;
--
-- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT);
-+ if (!(qp->q.flags & INET_FRAG_FIRST_IN))
-+ goto out;
-
-- if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments)
-+ /* sk_buff::dev and sk_buff::rbnode are unionized. So we
-+ * pull the head out of the tree in order to be able to
-+ * deal with head->dev.
-+ */
-+ if (qp->q.fragments) {
-+ head = qp->q.fragments;
-+ qp->q.fragments = head->next;
-+ } else {
-+ head = skb_rb_first(&qp->q.rb_fragments);
-+ if (!head)
- goto out;
-+ if (FRAG_CB(head)->next_frag)
-+ rb_replace_node(&head->rbnode,
-+ &FRAG_CB(head)->next_frag->rbnode,
-+ &qp->q.rb_fragments);
-+ else
-+ rb_erase(&head->rbnode, &qp->q.rb_fragments);
-+ memset(&head->rbnode, 0, sizeof(head->rbnode));
-+ barrier();
-+ }
-+ if (head == qp->q.fragments_tail)
-+ qp->q.fragments_tail = NULL;
-
-- head->dev = dev_get_by_index_rcu(net, qp->iif);
-- if (!head->dev)
-- goto out;
-+ sub_frag_mem_limit(qp->q.net, head->truesize);
-+
-+ head->dev = dev_get_by_index_rcu(net, qp->iif);
-+ if (!head->dev)
-+ goto out;
-
-
-- /* skb has no dst, perform route lookup again */
-- iph = ip_hdr(head);
-- err = ip_route_input_noref(head, iph->daddr, iph->saddr,
-+ /* skb has no dst, perform route lookup again */
-+ iph = ip_hdr(head);
-+ err = ip_route_input_noref(head, iph->daddr, iph->saddr,
- iph->tos, head->dev);
-- if (err)
-- goto out;
-+ if (err)
-+ goto out;
-
-- /* Only an end host needs to send an ICMP
-- * "Fragment Reassembly Timeout" message, per RFC792.
-- */
-- if (frag_expire_skip_icmp(qp->user) &&
-- (skb_rtable(head)->rt_type != RTN_LOCAL))
-- goto out;
-+ /* Only an end host needs to send an ICMP
-+ * "Fragment Reassembly Timeout" message, per RFC792.
-+ */
-+ if (frag_expire_skip_icmp(qp->q.key.v4.user) &&
-+ (skb_rtable(head)->rt_type != RTN_LOCAL))
-+ goto out;
-
-- clone = skb_clone(head, GFP_ATOMIC);
-+ spin_unlock(&qp->q.lock);
-+ icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
-+ goto out_rcu_unlock;
-
-- /* Send an ICMP "Fragment Reassembly Timeout" message. */
-- if (clone) {
-- spin_unlock(&qp->q.lock);
-- icmp_send(clone, ICMP_TIME_EXCEEDED,
-- ICMP_EXC_FRAGTIME, 0);
-- consume_skb(clone);
-- goto out_rcu_unlock;
-- }
-- }
- out:
- spin_unlock(&qp->q.lock);
- out_rcu_unlock:
- rcu_read_unlock();
-+ if (head)
-+ kfree_skb(head);
- ipq_put(qp);
- }
-
-@@ -262,21 +271,20 @@ out_rcu_unlock:
- static struct ipq *ip_find(struct net *net, struct iphdr *iph,
- u32 user, int vif)
- {
-+ struct frag_v4_compare_key key = {
-+ .saddr = iph->saddr,
-+ .daddr = iph->daddr,
-+ .user = user,
-+ .vif = vif,
-+ .id = iph->id,
-+ .protocol = iph->protocol,
-+ };
- struct inet_frag_queue *q;
-- struct ip4_create_arg arg;
-- unsigned int hash;
--
-- arg.iph = iph;
-- arg.user = user;
-- arg.vif = vif;
--
-- hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
-
-- q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
-- if (IS_ERR_OR_NULL(q)) {
-- inet_frag_maybe_warn_overflow(q, pr_fmt());
-+ q = inet_frag_find(&net->ipv4.frags, &key);
-+ if (!q)
- return NULL;
-- }
-+
- return container_of(q, struct ipq, q);
- }
-
-@@ -296,7 +304,7 @@ static int ip_frag_too_far(struct ipq *qp)
- end = atomic_inc_return(&peer->rid);
- qp->rid = end;
-
-- rc = qp->q.fragments && (end - start) > max;
-+ rc = qp->q.fragments_tail && (end - start) > max;
-
- if (rc) {
- struct net *net;
-@@ -310,7 +318,6 @@ static int ip_frag_too_far(struct ipq *qp)
-
- static int ip_frag_reinit(struct ipq *qp)
- {
-- struct sk_buff *fp;
- unsigned int sum_truesize = 0;
-
- if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) {
-@@ -318,21 +325,16 @@ static int ip_frag_reinit(struct ipq *qp)
- return -ETIMEDOUT;
- }
-
-- fp = qp->q.fragments;
-- do {
-- struct sk_buff *xp = fp->next;
--
-- sum_truesize += fp->truesize;
-- kfree_skb(fp);
-- fp = xp;
-- } while (fp);
-+ sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments);
- sub_frag_mem_limit(qp->q.net, sum_truesize);
-
- qp->q.flags = 0;
- qp->q.len = 0;
- qp->q.meat = 0;
- qp->q.fragments = NULL;
-+ qp->q.rb_fragments = RB_ROOT;
- qp->q.fragments_tail = NULL;
-+ qp->q.last_run_head = NULL;
- qp->iif = 0;
- qp->ecn = 0;
-
-@@ -342,11 +344,13 @@ static int ip_frag_reinit(struct ipq *qp)
- /* Add new segment to existing queue. */
- static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
- {
-- struct sk_buff *prev, *next;
-+ struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
-+ struct rb_node **rbn, *parent;
-+ struct sk_buff *skb1, *prev_tail;
-+ int ihl, end, skb1_run_end;
- struct net_device *dev;
- unsigned int fragsize;
- int flags, offset;
-- int ihl, end;
- int err = -ENOENT;
- u8 ecn;
-
-@@ -405,94 +409,68 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
- if (err)
- goto err;
-
-- /* Find out which fragments are in front and at the back of us
-- * in the chain of fragments so far. We must know where to put
-- * this fragment, right?
-- */
-- prev = qp->q.fragments_tail;
-- if (!prev || FRAG_CB(prev)->offset < offset) {
-- next = NULL;
-- goto found;
-- }
-- prev = NULL;
-- for (next = qp->q.fragments; next != NULL; next = next->next) {
-- if (FRAG_CB(next)->offset >= offset)
-- break; /* bingo! */
-- prev = next;
-- }
--
--found:
-- /* We found where to put this one. Check for overlap with
-- * preceding fragment, and, if needed, align things so that
-- * any overlaps are eliminated.
-+ /* Note : skb->rbnode and skb->dev share the same location. */
-+ dev = skb->dev;
-+ /* Makes sure compiler wont do silly aliasing games */
-+ barrier();
-+
-+ /* RFC5722, Section 4, amended by Errata ID : 3089
-+ * When reassembling an IPv6 datagram, if
-+ * one or more its constituent fragments is determined to be an
-+ * overlapping fragment, the entire datagram (and any constituent
-+ * fragments) MUST be silently discarded.
-+ *
-+ * We do the same here for IPv4 (and increment an snmp counter) but
-+ * we do not want to drop the whole queue in response to a duplicate
-+ * fragment.
- */
-- if (prev) {
-- int i = (FRAG_CB(prev)->offset + prev->len) - offset;
--
-- if (i > 0) {
-- offset += i;
-- err = -EINVAL;
-- if (end <= offset)
-- goto err;
-- err = -ENOMEM;
-- if (!pskb_pull(skb, i))
-- goto err;
-- if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-- skb->ip_summed = CHECKSUM_NONE;
-- }
-- }
-
-- err = -ENOMEM;
--
-- while (next && FRAG_CB(next)->offset < end) {
-- int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
--
-- if (i < next->len) {
-- /* Eat head of the next overlapped fragment
-- * and leave the loop. The next ones cannot overlap.
-- */
-- if (!pskb_pull(next, i))
-- goto err;
-- FRAG_CB(next)->offset += i;
-- qp->q.meat -= i;
-- if (next->ip_summed != CHECKSUM_UNNECESSARY)
-- next->ip_summed = CHECKSUM_NONE;
-- break;
-- } else {
-- struct sk_buff *free_it = next;
--
-- /* Old fragment is completely overridden with
-- * new one drop it.
-- */
-- next = next->next;
--
-- if (prev)
-- prev->next = next;
-+ err = -EINVAL;
-+ /* Find out where to put this fragment. */
-+ prev_tail = qp->q.fragments_tail;
-+ if (!prev_tail)
-+ ip4_frag_create_run(&qp->q, skb); /* First fragment. */
-+ else if (prev_tail->ip_defrag_offset + prev_tail->len < end) {
-+ /* This is the common case: skb goes to the end. */
-+ /* Detect and discard overlaps. */
-+ if (offset < prev_tail->ip_defrag_offset + prev_tail->len)
-+ goto discard_qp;
-+ if (offset == prev_tail->ip_defrag_offset + prev_tail->len)
-+ ip4_frag_append_to_last_run(&qp->q, skb);
-+ else
-+ ip4_frag_create_run(&qp->q, skb);
-+ } else {
-+ /* Binary search. Note that skb can become the first fragment,
-+ * but not the last (covered above).
-+ */
-+ rbn = &qp->q.rb_fragments.rb_node;
-+ do {
-+ parent = *rbn;
-+ skb1 = rb_to_skb(parent);
-+ skb1_run_end = skb1->ip_defrag_offset +
-+ FRAG_CB(skb1)->frag_run_len;
-+ if (end <= skb1->ip_defrag_offset)
-+ rbn = &parent->rb_left;
-+ else if (offset >= skb1_run_end)
-+ rbn = &parent->rb_right;
-+ else if (offset >= skb1->ip_defrag_offset &&
-+ end <= skb1_run_end)
-+ goto err; /* No new data, potential duplicate */
- else
-- qp->q.fragments = next;
--
-- qp->q.meat -= free_it->len;
-- sub_frag_mem_limit(qp->q.net, free_it->truesize);
-- kfree_skb(free_it);
-- }
-+ goto discard_qp; /* Found an overlap */
-+ } while (*rbn);
-+ /* Here we have parent properly set, and rbn pointing to
-+ * one of its NULL left/right children. Insert skb.
-+ */
-+ ip4_frag_init_run(skb);
-+ rb_link_node(&skb->rbnode, parent, rbn);
-+ rb_insert_color(&skb->rbnode, &qp->q.rb_fragments);
- }
-
-- FRAG_CB(skb)->offset = offset;
--
-- /* Insert this fragment in the chain of fragments. */
-- skb->next = next;
-- if (!next)
-- qp->q.fragments_tail = skb;
-- if (prev)
-- prev->next = skb;
-- else
-- qp->q.fragments = skb;
--
-- dev = skb->dev;
-- if (dev) {
-+ if (dev)
- qp->iif = dev->ifindex;
-- skb->dev = NULL;
-- }
-+ skb->ip_defrag_offset = offset;
-+
- qp->q.stamp = skb->tstamp;
- qp->q.meat += skb->len;
- qp->ecn |= ecn;
-@@ -514,7 +492,7 @@ found:
- unsigned long orefdst = skb->_skb_refdst;
-
- skb->_skb_refdst = 0UL;
-- err = ip_frag_reasm(qp, prev, dev);
-+ err = ip_frag_reasm(qp, skb, prev_tail, dev);
- skb->_skb_refdst = orefdst;
- return err;
- }
-@@ -522,20 +500,23 @@ found:
- skb_dst_drop(skb);
- return -EINPROGRESS;
-
-+discard_qp:
-+ inet_frag_kill(&qp->q);
-+ IP_INC_STATS_BH(net, IPSTATS_MIB_REASM_OVERLAPS);
- err:
- kfree_skb(skb);
- return err;
- }
-
--
- /* Build a new IP datagram from all its fragments. */
--
--static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
-- struct net_device *dev)
-+static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
-+ struct sk_buff *prev_tail, struct net_device *dev)
- {
- struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
- struct iphdr *iph;
-- struct sk_buff *fp, *head = qp->q.fragments;
-+ struct sk_buff *fp, *head = skb_rb_first(&qp->q.rb_fragments);
-+ struct sk_buff **nextp; /* To build frag_list. */
-+ struct rb_node *rbn;
- int len;
- int ihlen;
- int err;
-@@ -549,26 +530,27 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
- goto out_fail;
- }
- /* Make the one we just received the head. */
-- if (prev) {
-- head = prev->next;
-- fp = skb_clone(head, GFP_ATOMIC);
-+ if (head != skb) {
-+ fp = skb_clone(skb, GFP_ATOMIC);
- if (!fp)
- goto out_nomem;
--
-- fp->next = head->next;
-- if (!fp->next)
-+ FRAG_CB(fp)->next_frag = FRAG_CB(skb)->next_frag;
-+ if (RB_EMPTY_NODE(&skb->rbnode))
-+ FRAG_CB(prev_tail)->next_frag = fp;
-+ else
-+ rb_replace_node(&skb->rbnode, &fp->rbnode,
-+ &qp->q.rb_fragments);
-+ if (qp->q.fragments_tail == skb)
- qp->q.fragments_tail = fp;
-- prev->next = fp;
--
-- skb_morph(head, qp->q.fragments);
-- head->next = qp->q.fragments->next;
--
-- consume_skb(qp->q.fragments);
-- qp->q.fragments = head;
-+ skb_morph(skb, head);
-+ FRAG_CB(skb)->next_frag = FRAG_CB(head)->next_frag;
-+ rb_replace_node(&head->rbnode, &skb->rbnode,
-+ &qp->q.rb_fragments);
-+ consume_skb(head);
-+ head = skb;
- }
-
-- WARN_ON(!head);
-- WARN_ON(FRAG_CB(head)->offset != 0);
-+ WARN_ON(head->ip_defrag_offset != 0);
-
- /* Allocate a new buffer for the datagram. */
- ihlen = ip_hdrlen(head);
-@@ -592,35 +574,61 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
- clone = alloc_skb(0, GFP_ATOMIC);
- if (!clone)
- goto out_nomem;
-- clone->next = head->next;
-- head->next = clone;
- skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
- skb_frag_list_init(head);
- for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
- plen += skb_frag_size(&skb_shinfo(head)->frags[i]);
- clone->len = clone->data_len = head->data_len - plen;
-- head->data_len -= clone->len;
-- head->len -= clone->len;
-+ head->truesize += clone->truesize;
- clone->csum = 0;
- clone->ip_summed = head->ip_summed;
- add_frag_mem_limit(qp->q.net, clone->truesize);
-+ skb_shinfo(head)->frag_list = clone;
-+ nextp = &clone->next;
-+ } else {
-+ nextp = &skb_shinfo(head)->frag_list;
- }
-
-- skb_shinfo(head)->frag_list = head->next;
- skb_push(head, head->data - skb_network_header(head));
-
-- for (fp=head->next; fp; fp = fp->next) {
-- head->data_len += fp->len;
-- head->len += fp->len;
-- if (head->ip_summed != fp->ip_summed)
-- head->ip_summed = CHECKSUM_NONE;
-- else if (head->ip_summed == CHECKSUM_COMPLETE)
-- head->csum = csum_add(head->csum, fp->csum);
-- head->truesize += fp->truesize;
-+ /* Traverse the tree in order, to build frag_list. */
-+ fp = FRAG_CB(head)->next_frag;
-+ rbn = rb_next(&head->rbnode);
-+ rb_erase(&head->rbnode, &qp->q.rb_fragments);
-+ while (rbn || fp) {
-+ /* fp points to the next sk_buff in the current run;
-+ * rbn points to the next run.
-+ */
-+ /* Go through the current run. */
-+ while (fp) {
-+ *nextp = fp;
-+ nextp = &fp->next;
-+ fp->prev = NULL;
-+ memset(&fp->rbnode, 0, sizeof(fp->rbnode));
-+ fp->sk = NULL;
-+ head->data_len += fp->len;
-+ head->len += fp->len;
-+ if (head->ip_summed != fp->ip_summed)
-+ head->ip_summed = CHECKSUM_NONE;
-+ else if (head->ip_summed == CHECKSUM_COMPLETE)
-+ head->csum = csum_add(head->csum, fp->csum);
-+ head->truesize += fp->truesize;
-+ fp = FRAG_CB(fp)->next_frag;
-+ }
-+ /* Move to the next run. */
-+ if (rbn) {
-+ struct rb_node *rbnext = rb_next(rbn);
-+
-+ fp = rb_to_skb(rbn);
-+ rb_erase(rbn, &qp->q.rb_fragments);
-+ rbn = rbnext;
-+ }
- }
- sub_frag_mem_limit(qp->q.net, head->truesize);
-
-+ *nextp = NULL;
- head->next = NULL;
-+ head->prev = NULL;
- head->dev = dev;
- head->tstamp = qp->q.stamp;
- IPCB(head)->frag_max_size = max(qp->max_df_size, qp->q.max_size);
-@@ -648,7 +656,9 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
-
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
- qp->q.fragments = NULL;
-+ qp->q.rb_fragments = RB_ROOT;
- qp->q.fragments_tail = NULL;
-+ qp->q.last_run_head = NULL;
- return 0;
-
- out_nomem:
-@@ -656,7 +666,7 @@ out_nomem:
- err = -ENOMEM;
- goto out_fail;
- out_oversize:
-- net_info_ratelimited("Oversized IP packet from %pI4\n", &qp->saddr);
-+ net_info_ratelimited("Oversized IP packet from %pI4\n", &qp->q.key.v4.saddr);
- out_fail:
- IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
- return err;
-@@ -734,25 +744,46 @@ struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
- }
- EXPORT_SYMBOL(ip_check_defrag);
-
-+unsigned int inet_frag_rbtree_purge(struct rb_root *root)
-+{
-+ struct rb_node *p = rb_first(root);
-+ unsigned int sum = 0;
-+
-+ while (p) {
-+ struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode);
-+
-+ p = rb_next(p);
-+ rb_erase(&skb->rbnode, root);
-+ while (skb) {
-+ struct sk_buff *next = FRAG_CB(skb)->next_frag;
-+
-+ sum += skb->truesize;
-+ kfree_skb(skb);
-+ skb = next;
-+ }
-+ }
-+ return sum;
-+}
-+EXPORT_SYMBOL(inet_frag_rbtree_purge);
-+
- #ifdef CONFIG_SYSCTL
--static int zero;
-+static int dist_min;
-
- static struct ctl_table ip4_frags_ns_ctl_table[] = {
- {
- .procname = "ipfrag_high_thresh",
- .data = &init_net.ipv4.frags.high_thresh,
-- .maxlen = sizeof(int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra1 = &init_net.ipv4.frags.low_thresh
- },
- {
- .procname = "ipfrag_low_thresh",
- .data = &init_net.ipv4.frags.low_thresh,
-- .maxlen = sizeof(int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-- .extra1 = &zero,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra2 = &init_net.ipv4.frags.high_thresh
- },
- {
-@@ -781,7 +812,7 @@ static struct ctl_table ip4_frags_ctl_table[] = {
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
-- .extra1 = &zero
-+ .extra1 = &dist_min,
- },
- { }
- };
-@@ -853,6 +884,8 @@ static void __init ip4_frags_ctl_register(void)
-
- static int __net_init ipv4_frags_init_net(struct net *net)
- {
-+ int res;
-+
- /* Fragment cache limits.
- *
- * The fragment memory accounting code, (tries to) account for
-@@ -876,15 +909,21 @@ static int __net_init ipv4_frags_init_net(struct net *net)
- */
- net->ipv4.frags.timeout = IP_FRAG_TIME;
-
-- inet_frags_init_net(&net->ipv4.frags);
-+ net->ipv4.frags.f = &ip4_frags;
-
-- return ip4_frags_ns_ctl_register(net);
-+ res = inet_frags_init_net(&net->ipv4.frags);
-+ if (res < 0)
-+ return res;
-+ res = ip4_frags_ns_ctl_register(net);
-+ if (res < 0)
-+ inet_frags_exit_net(&net->ipv4.frags);
-+ return res;
- }
-
- static void __net_exit ipv4_frags_exit_net(struct net *net)
- {
- ip4_frags_ns_ctl_unregister(net);
-- inet_frags_exit_net(&net->ipv4.frags, &ip4_frags);
-+ inet_frags_exit_net(&net->ipv4.frags);
- }
-
- static struct pernet_operations ip4_frags_ops = {
-@@ -892,18 +931,50 @@ static struct pernet_operations ip4_frags_ops = {
- .exit = ipv4_frags_exit_net,
- };
-
-+
-+static u32 ip4_key_hashfn(const void *data, u32 len, u32 seed)
-+{
-+ return jhash2(data,
-+ sizeof(struct frag_v4_compare_key) / sizeof(u32), seed);
-+}
-+
-+static u32 ip4_obj_hashfn(const void *data, u32 len, u32 seed)
-+{
-+ const struct inet_frag_queue *fq = data;
-+
-+ return jhash2((const u32 *)&fq->key.v4,
-+ sizeof(struct frag_v4_compare_key) / sizeof(u32), seed);
-+}
-+
-+static int ip4_obj_cmpfn(struct rhashtable_compare_arg *arg, const void *ptr)
-+{
-+ const struct frag_v4_compare_key *key = arg->key;
-+ const struct inet_frag_queue *fq = ptr;
-+
-+ return !!memcmp(&fq->key, key, sizeof(*key));
-+}
-+
-+static const struct rhashtable_params ip4_rhash_params = {
-+ .head_offset = offsetof(struct inet_frag_queue, node),
-+ .key_offset = offsetof(struct inet_frag_queue, key),
-+ .key_len = sizeof(struct frag_v4_compare_key),
-+ .hashfn = ip4_key_hashfn,
-+ .obj_hashfn = ip4_obj_hashfn,
-+ .obj_cmpfn = ip4_obj_cmpfn,
-+ .automatic_shrinking = true,
-+};
-+
- void __init ipfrag_init(void)
- {
-- ip4_frags_ctl_register();
-- register_pernet_subsys(&ip4_frags_ops);
-- ip4_frags.hashfn = ip4_hashfn;
- ip4_frags.constructor = ip4_frag_init;
- ip4_frags.destructor = ip4_frag_free;
- ip4_frags.skb_free = NULL;
- ip4_frags.qsize = sizeof(struct ipq);
-- ip4_frags.match = ip4_frag_match;
- ip4_frags.frag_expire = ip_expire;
- ip4_frags.frags_cache_name = ip_frag_cache_name;
-+ ip4_frags.rhash_params = ip4_rhash_params;
- if (inet_frags_init(&ip4_frags))
- panic("IP: failed to allocate ip4_frags cache\n");
-+ ip4_frags_ctl_register();
-+ register_pernet_subsys(&ip4_frags_ops);
- }
-diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
-index 3abd9d7a3adf..b001ad668108 100644
---- a/net/ipv4/proc.c
-+++ b/net/ipv4/proc.c
-@@ -52,7 +52,6 @@
- static int sockstat_seq_show(struct seq_file *seq, void *v)
- {
- struct net *net = seq->private;
-- unsigned int frag_mem;
- int orphans, sockets;
-
- local_bh_disable();
-@@ -72,8 +71,9 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
- sock_prot_inuse_get(net, &udplite_prot));
- seq_printf(seq, "RAW: inuse %d\n",
- sock_prot_inuse_get(net, &raw_prot));
-- frag_mem = ip_frag_mem(net);
-- seq_printf(seq, "FRAG: inuse %u memory %u\n", !!frag_mem, frag_mem);
-+ seq_printf(seq, "FRAG: inuse %u memory %lu\n",
-+ atomic_read(&net->ipv4.frags.rhashtable.nelems),
-+ frag_mem_limit(&net->ipv4.frags));
- return 0;
- }
-
-@@ -132,6 +132,7 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
- SNMP_MIB_ITEM("InECT1Pkts", IPSTATS_MIB_ECT1PKTS),
- SNMP_MIB_ITEM("InECT0Pkts", IPSTATS_MIB_ECT0PKTS),
- SNMP_MIB_ITEM("InCEPkts", IPSTATS_MIB_CEPKTS),
-+ SNMP_MIB_ITEM("ReasmOverlaps", IPSTATS_MIB_REASM_OVERLAPS),
- SNMP_MIB_SENTINEL
- };
-
-diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
-index 5a9ae56e7868..664c84e47bab 100644
---- a/net/ipv6/netfilter/nf_conntrack_reasm.c
-+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
-@@ -64,7 +64,6 @@ struct nf_ct_frag6_skb_cb
- static struct inet_frags nf_frags;
-
- #ifdef CONFIG_SYSCTL
--static int zero;
-
- static struct ctl_table nf_ct_frag6_sysctl_table[] = {
- {
-@@ -77,18 +76,17 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
- {
- .procname = "nf_conntrack_frag6_low_thresh",
- .data = &init_net.nf_frag.frags.low_thresh,
-- .maxlen = sizeof(unsigned int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-- .extra1 = &zero,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra2 = &init_net.nf_frag.frags.high_thresh
- },
- {
- .procname = "nf_conntrack_frag6_high_thresh",
- .data = &init_net.nf_frag.frags.high_thresh,
-- .maxlen = sizeof(unsigned int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra1 = &init_net.nf_frag.frags.low_thresh
- },
- { }
-@@ -153,23 +151,6 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h)
- return 1 << (ipv6_get_dsfield(ipv6h) & INET_ECN_MASK);
- }
-
--static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr,
-- const struct in6_addr *daddr)
--{
-- net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd));
-- return jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr),
-- (__force u32)id, nf_frags.rnd);
--}
--
--
--static unsigned int nf_hashfn(const struct inet_frag_queue *q)
--{
-- const struct frag_queue *nq;
--
-- nq = container_of(q, struct frag_queue, q);
-- return nf_hash_frag(nq->id, &nq->saddr, &nq->daddr);
--}
--
- static void nf_skb_free(struct sk_buff *skb)
- {
- if (NFCT_FRAG6_CB(skb)->orig)
-@@ -184,34 +165,26 @@ static void nf_ct_frag6_expire(unsigned long data)
- fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
- net = container_of(fq->q.net, struct net, nf_frag.frags);
-
-- ip6_expire_frag_queue(net, fq, &nf_frags);
-+ ip6_expire_frag_queue(net, fq);
- }
-
- /* Creation primitives. */
--static inline struct frag_queue *fq_find(struct net *net, __be32 id,
-- u32 user, struct in6_addr *src,
-- struct in6_addr *dst, int iif, u8 ecn)
-+static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user,
-+ const struct ipv6hdr *hdr, int iif)
- {
-+ struct frag_v6_compare_key key = {
-+ .id = id,
-+ .saddr = hdr->saddr,
-+ .daddr = hdr->daddr,
-+ .user = user,
-+ .iif = iif,
-+ };
- struct inet_frag_queue *q;
-- struct ip6_create_arg arg;
-- unsigned int hash;
--
-- arg.id = id;
-- arg.user = user;
-- arg.src = src;
-- arg.dst = dst;
-- arg.iif = iif;
-- arg.ecn = ecn;
--
-- local_bh_disable();
-- hash = nf_hash_frag(id, src, dst);
--
-- q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
-- local_bh_enable();
-- if (IS_ERR_OR_NULL(q)) {
-- inet_frag_maybe_warn_overflow(q, pr_fmt());
-+
-+ q = inet_frag_find(&net->nf_frag.frags, &key);
-+ if (!q)
- return NULL;
-- }
-+
- return container_of(q, struct frag_queue, q);
- }
-
-@@ -362,7 +335,7 @@ found:
- return 0;
-
- discard_fq:
-- inet_frag_kill(&fq->q, &nf_frags);
-+ inet_frag_kill(&fq->q);
- err:
- return -1;
- }
-@@ -383,7 +356,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev)
- int payload_len;
- u8 ecn;
-
-- inet_frag_kill(&fq->q, &nf_frags);
-+ inet_frag_kill(&fq->q);
-
- WARN_ON(head == NULL);
- WARN_ON(NFCT_FRAG6_CB(head)->offset != 0);
-@@ -454,6 +427,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev)
- else if (head->ip_summed == CHECKSUM_COMPLETE)
- head->csum = csum_add(head->csum, fp->csum);
- head->truesize += fp->truesize;
-+ fp->sk = NULL;
- }
- sub_frag_mem_limit(fq->q.net, head->truesize);
-
-@@ -472,6 +446,7 @@ nf_ct_frag6_reasm(struct frag_queue *fq, struct net_device *dev)
- head->csum);
-
- fq->q.fragments = NULL;
-+ fq->q.rb_fragments = RB_ROOT;
- fq->q.fragments_tail = NULL;
-
- /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */
-@@ -601,9 +576,13 @@ struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 use
- hdr = ipv6_hdr(clone);
- fhdr = (struct frag_hdr *)skb_transport_header(clone);
-
-+ if (clone->len - skb_network_offset(clone) < IPV6_MIN_MTU &&
-+ fhdr->frag_off & htons(IP6_MF))
-+ goto ret_orig;
-+
- skb_orphan(skb);
-- fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr,
-- skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr));
-+ fq = fq_find(net, fhdr->identification, user, hdr,
-+ skb->dev ? skb->dev->ifindex : 0);
- if (fq == NULL) {
- pr_debug("Can't find and can't create new queue\n");
- goto ret_orig;
-@@ -614,7 +593,7 @@ struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 use
- if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) {
- spin_unlock_bh(&fq->q.lock);
- pr_debug("Can't insert skb to queue\n");
-- inet_frag_put(&fq->q, &nf_frags);
-+ inet_frag_put(&fq->q);
- goto ret_orig;
- }
-
-@@ -626,7 +605,7 @@ struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 use
- }
- spin_unlock_bh(&fq->q.lock);
-
-- inet_frag_put(&fq->q, &nf_frags);
-+ inet_frag_put(&fq->q);
- return ret_skb;
-
- ret_orig:
-@@ -650,18 +629,26 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig);
-
- static int nf_ct_net_init(struct net *net)
- {
-+ int res;
-+
- net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
- net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
- net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT;
-- inet_frags_init_net(&net->nf_frag.frags);
--
-- return nf_ct_frag6_sysctl_register(net);
-+ net->nf_frag.frags.f = &nf_frags;
-+
-+ res = inet_frags_init_net(&net->nf_frag.frags);
-+ if (res < 0)
-+ return res;
-+ res = nf_ct_frag6_sysctl_register(net);
-+ if (res < 0)
-+ inet_frags_exit_net(&net->nf_frag.frags);
-+ return res;
- }
-
- static void nf_ct_net_exit(struct net *net)
- {
- nf_ct_frags6_sysctl_unregister(net);
-- inet_frags_exit_net(&net->nf_frag.frags, &nf_frags);
-+ inet_frags_exit_net(&net->nf_frag.frags);
- }
-
- static struct pernet_operations nf_ct_net_ops = {
-@@ -673,14 +660,13 @@ int nf_ct_frag6_init(void)
- {
- int ret = 0;
-
-- nf_frags.hashfn = nf_hashfn;
- nf_frags.constructor = ip6_frag_init;
- nf_frags.destructor = NULL;
- nf_frags.skb_free = nf_skb_free;
- nf_frags.qsize = sizeof(struct frag_queue);
-- nf_frags.match = ip6_frag_match;
- nf_frags.frag_expire = nf_ct_frag6_expire;
- nf_frags.frags_cache_name = nf_frags_cache_name;
-+ nf_frags.rhash_params = ip6_rhash_params;
- ret = inet_frags_init(&nf_frags);
- if (ret)
- goto out;
-diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
-index 679253d0af84..73e766e7bc37 100644
---- a/net/ipv6/proc.c
-+++ b/net/ipv6/proc.c
-@@ -33,7 +33,6 @@
- static int sockstat6_seq_show(struct seq_file *seq, void *v)
- {
- struct net *net = seq->private;
-- unsigned int frag_mem = ip6_frag_mem(net);
-
- seq_printf(seq, "TCP6: inuse %d\n",
- sock_prot_inuse_get(net, &tcpv6_prot));
-@@ -43,7 +42,9 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
- sock_prot_inuse_get(net, &udplitev6_prot));
- seq_printf(seq, "RAW6: inuse %d\n",
- sock_prot_inuse_get(net, &rawv6_prot));
-- seq_printf(seq, "FRAG6: inuse %u memory %u\n", !!frag_mem, frag_mem);
-+ seq_printf(seq, "FRAG6: inuse %u memory %lu\n",
-+ atomic_read(&net->ipv6.frags.rhashtable.nelems),
-+ frag_mem_limit(&net->ipv6.frags));
- return 0;
- }
-
-diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
-index 58f2139ebb5e..ec917f58d105 100644
---- a/net/ipv6/reassembly.c
-+++ b/net/ipv6/reassembly.c
-@@ -79,94 +79,58 @@ static struct inet_frags ip6_frags;
- static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
- struct net_device *dev);
-
--/*
-- * callers should be careful not to use the hash value outside the ipfrag_lock
-- * as doing so could race with ipfrag_hash_rnd being recalculated.
-- */
--static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
-- const struct in6_addr *daddr)
--{
-- net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd));
-- return jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr),
-- (__force u32)id, ip6_frags.rnd);
--}
--
--static unsigned int ip6_hashfn(const struct inet_frag_queue *q)
--{
-- const struct frag_queue *fq;
--
-- fq = container_of(q, struct frag_queue, q);
-- return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr);
--}
--
--bool ip6_frag_match(const struct inet_frag_queue *q, const void *a)
--{
-- const struct frag_queue *fq;
-- const struct ip6_create_arg *arg = a;
--
-- fq = container_of(q, struct frag_queue, q);
-- return fq->id == arg->id &&
-- fq->user == arg->user &&
-- ipv6_addr_equal(&fq->saddr, arg->src) &&
-- ipv6_addr_equal(&fq->daddr, arg->dst) &&
-- (arg->iif == fq->iif ||
-- !(ipv6_addr_type(arg->dst) & (IPV6_ADDR_MULTICAST |
-- IPV6_ADDR_LINKLOCAL)));
--}
--EXPORT_SYMBOL(ip6_frag_match);
--
- void ip6_frag_init(struct inet_frag_queue *q, const void *a)
- {
- struct frag_queue *fq = container_of(q, struct frag_queue, q);
-- const struct ip6_create_arg *arg = a;
-+ const struct frag_v6_compare_key *key = a;
-
-- fq->id = arg->id;
-- fq->user = arg->user;
-- fq->saddr = *arg->src;
-- fq->daddr = *arg->dst;
-- fq->ecn = arg->ecn;
-+ q->key.v6 = *key;
-+ fq->ecn = 0;
- }
- EXPORT_SYMBOL(ip6_frag_init);
-
--void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
-- struct inet_frags *frags)
-+void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq)
- {
- struct net_device *dev = NULL;
-+ struct sk_buff *head;
-
-+ rcu_read_lock();
- spin_lock(&fq->q.lock);
-
- if (fq->q.flags & INET_FRAG_COMPLETE)
- goto out;
-
-- inet_frag_kill(&fq->q, frags);
-+ inet_frag_kill(&fq->q);
-
-- rcu_read_lock();
- dev = dev_get_by_index_rcu(net, fq->iif);
- if (!dev)
-- goto out_rcu_unlock;
-+ goto out;
-
- IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
--
-- if (inet_frag_evicting(&fq->q))
-- goto out_rcu_unlock;
--
- IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
-
- /* Don't send error if the first segment did not arrive. */
-- if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !fq->q.fragments)
-- goto out_rcu_unlock;
-+ head = fq->q.fragments;
-+ if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !head)
-+ goto out;
-
- /* But use as source device on which LAST ARRIVED
- * segment was received. And do not use fq->dev
- * pointer directly, device might already disappeared.
- */
-- fq->q.fragments->dev = dev;
-- icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0);
--out_rcu_unlock:
-- rcu_read_unlock();
-+ head->dev = dev;
-+ skb_get(head);
-+ spin_unlock(&fq->q.lock);
-+
-+ icmpv6_send(head, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0);
-+ kfree_skb(head);
-+ goto out_rcu_unlock;
-+
- out:
- spin_unlock(&fq->q.lock);
-- inet_frag_put(&fq->q, frags);
-+out_rcu_unlock:
-+ rcu_read_unlock();
-+ inet_frag_put(&fq->q);
- }
- EXPORT_SYMBOL(ip6_expire_frag_queue);
-
-@@ -178,31 +142,29 @@ static void ip6_frag_expire(unsigned long data)
- fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
- net = container_of(fq->q.net, struct net, ipv6.frags);
-
-- ip6_expire_frag_queue(net, fq, &ip6_frags);
-+ ip6_expire_frag_queue(net, fq);
- }
-
- static struct frag_queue *
--fq_find(struct net *net, __be32 id, const struct in6_addr *src,
-- const struct in6_addr *dst, int iif, u8 ecn)
-+fq_find(struct net *net, __be32 id, const struct ipv6hdr *hdr, int iif)
- {
-+ struct frag_v6_compare_key key = {
-+ .id = id,
-+ .saddr = hdr->saddr,
-+ .daddr = hdr->daddr,
-+ .user = IP6_DEFRAG_LOCAL_DELIVER,
-+ .iif = iif,
-+ };
- struct inet_frag_queue *q;
-- struct ip6_create_arg arg;
-- unsigned int hash;
-
-- arg.id = id;
-- arg.user = IP6_DEFRAG_LOCAL_DELIVER;
-- arg.src = src;
-- arg.dst = dst;
-- arg.iif = iif;
-- arg.ecn = ecn;
-+ if (!(ipv6_addr_type(&hdr->daddr) & (IPV6_ADDR_MULTICAST |
-+ IPV6_ADDR_LINKLOCAL)))
-+ key.iif = 0;
-
-- hash = inet6_hash_frag(id, src, dst);
--
-- q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
-- if (IS_ERR_OR_NULL(q)) {
-- inet_frag_maybe_warn_overflow(q, pr_fmt());
-+ q = inet_frag_find(&net->ipv6.frags, &key);
-+ if (!q)
- return NULL;
-- }
-+
- return container_of(q, struct frag_queue, q);
- }
-
-@@ -359,7 +321,7 @@ found:
- return -1;
-
- discard_fq:
-- inet_frag_kill(&fq->q, &ip6_frags);
-+ inet_frag_kill(&fq->q);
- err:
- IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
- IPSTATS_MIB_REASMFAILS);
-@@ -386,7 +348,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
- int sum_truesize;
- u8 ecn;
-
-- inet_frag_kill(&fq->q, &ip6_frags);
-+ inet_frag_kill(&fq->q);
-
- ecn = ip_frag_ecn_table[fq->ecn];
- if (unlikely(ecn == 0xff))
-@@ -503,6 +465,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
- IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS);
- rcu_read_unlock();
- fq->q.fragments = NULL;
-+ fq->q.rb_fragments = RB_ROOT;
- fq->q.fragments_tail = NULL;
- return 1;
-
-@@ -524,6 +487,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
- struct frag_queue *fq;
- const struct ipv6hdr *hdr = ipv6_hdr(skb);
- struct net *net = dev_net(skb_dst(skb)->dev);
-+ int iif;
-
- if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
- goto fail_hdr;
-@@ -552,17 +516,22 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
- return 1;
- }
-
-- fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr,
-- skb->dev ? skb->dev->ifindex : 0, ip6_frag_ecn(hdr));
-+ if (skb->len - skb_network_offset(skb) < IPV6_MIN_MTU &&
-+ fhdr->frag_off & htons(IP6_MF))
-+ goto fail_hdr;
-+
-+ iif = skb->dev ? skb->dev->ifindex : 0;
-+ fq = fq_find(net, fhdr->identification, hdr, iif);
- if (fq) {
- int ret;
-
- spin_lock(&fq->q.lock);
-
-+ fq->iif = iif;
- ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
-
- spin_unlock(&fq->q.lock);
-- inet_frag_put(&fq->q, &ip6_frags);
-+ inet_frag_put(&fq->q);
- return ret;
- }
-
-@@ -583,24 +552,22 @@ static const struct inet6_protocol frag_protocol = {
- };
-
- #ifdef CONFIG_SYSCTL
--static int zero;
-
- static struct ctl_table ip6_frags_ns_ctl_table[] = {
- {
- .procname = "ip6frag_high_thresh",
- .data = &init_net.ipv6.frags.high_thresh,
-- .maxlen = sizeof(int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra1 = &init_net.ipv6.frags.low_thresh
- },
- {
- .procname = "ip6frag_low_thresh",
- .data = &init_net.ipv6.frags.low_thresh,
-- .maxlen = sizeof(int),
-+ .maxlen = sizeof(unsigned long),
- .mode = 0644,
-- .proc_handler = proc_dointvec_minmax,
-- .extra1 = &zero,
-+ .proc_handler = proc_doulongvec_minmax,
- .extra2 = &init_net.ipv6.frags.high_thresh
- },
- {
-@@ -708,19 +675,27 @@ static void ip6_frags_sysctl_unregister(void)
-
- static int __net_init ipv6_frags_init_net(struct net *net)
- {
-+ int res;
-+
- net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
- net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
- net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT;
-+ net->ipv6.frags.f = &ip6_frags;
-
-- inet_frags_init_net(&net->ipv6.frags);
-+ res = inet_frags_init_net(&net->ipv6.frags);
-+ if (res < 0)
-+ return res;
-
-- return ip6_frags_ns_sysctl_register(net);
-+ res = ip6_frags_ns_sysctl_register(net);
-+ if (res < 0)
-+ inet_frags_exit_net(&net->ipv6.frags);
-+ return res;
- }
-
- static void __net_exit ipv6_frags_exit_net(struct net *net)
- {
- ip6_frags_ns_sysctl_unregister(net);
-- inet_frags_exit_net(&net->ipv6.frags, &ip6_frags);
-+ inet_frags_exit_net(&net->ipv6.frags);
- }
-
- static struct pernet_operations ip6_frags_ops = {
-@@ -728,14 +703,55 @@ static struct pernet_operations ip6_frags_ops = {
- .exit = ipv6_frags_exit_net,
- };
-
-+static u32 ip6_key_hashfn(const void *data, u32 len, u32 seed)
-+{
-+ return jhash2(data,
-+ sizeof(struct frag_v6_compare_key) / sizeof(u32), seed);
-+}
-+
-+static u32 ip6_obj_hashfn(const void *data, u32 len, u32 seed)
-+{
-+ const struct inet_frag_queue *fq = data;
-+
-+ return jhash2((const u32 *)&fq->key.v6,
-+ sizeof(struct frag_v6_compare_key) / sizeof(u32), seed);
-+}
-+
-+static int ip6_obj_cmpfn(struct rhashtable_compare_arg *arg, const void *ptr)
-+{
-+ const struct frag_v6_compare_key *key = arg->key;
-+ const struct inet_frag_queue *fq = ptr;
-+
-+ return !!memcmp(&fq->key, key, sizeof(*key));
-+}
-+
-+const struct rhashtable_params ip6_rhash_params = {
-+ .head_offset = offsetof(struct inet_frag_queue, node),
-+ .hashfn = ip6_key_hashfn,
-+ .obj_hashfn = ip6_obj_hashfn,
-+ .obj_cmpfn = ip6_obj_cmpfn,
-+ .automatic_shrinking = true,
-+};
-+EXPORT_SYMBOL(ip6_rhash_params);
-+
- int __init ipv6_frag_init(void)
- {
- int ret;
-
-- ret = inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT);
-+ ip6_frags.constructor = ip6_frag_init;
-+ ip6_frags.destructor = NULL;
-+ ip6_frags.qsize = sizeof(struct frag_queue);
-+ ip6_frags.frag_expire = ip6_frag_expire;
-+ ip6_frags.frags_cache_name = ip6_frag_cache_name;
-+ ip6_frags.rhash_params = ip6_rhash_params;
-+ ret = inet_frags_init(&ip6_frags);
- if (ret)
- goto out;
-
-+ ret = inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT);
-+ if (ret)
-+ goto err_protocol;
-+
- ret = ip6_frags_sysctl_register();
- if (ret)
- goto err_sysctl;
-@@ -744,17 +760,6 @@ int __init ipv6_frag_init(void)
- if (ret)
- goto err_pernet;
-
-- ip6_frags.hashfn = ip6_hashfn;
-- ip6_frags.constructor = ip6_frag_init;
-- ip6_frags.destructor = NULL;
-- ip6_frags.skb_free = NULL;
-- ip6_frags.qsize = sizeof(struct frag_queue);
-- ip6_frags.match = ip6_frag_match;
-- ip6_frags.frag_expire = ip6_frag_expire;
-- ip6_frags.frags_cache_name = ip6_frag_cache_name;
-- ret = inet_frags_init(&ip6_frags);
-- if (ret)
-- goto err_pernet;
- out:
- return ret;
-
-@@ -762,6 +767,8 @@ err_pernet:
- ip6_frags_sysctl_unregister();
- err_sysctl:
- inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT);
-+err_protocol:
-+ inet_frags_fini(&ip6_frags);
- goto out;
- }
-
diff --git a/patch/kernel/rk3399-default/04-patch-4.4.174-175.patch b/patch/kernel/rk3399-default/04-patch-4.4.174-175.patch
deleted file mode 100644
index 0dc0f4507..000000000
--- a/patch/kernel/rk3399-default/04-patch-4.4.174-175.patch
+++ /dev/null
@@ -1,3518 +0,0 @@
-diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
-index 7c229f59016f..2fb35658d151 100644
---- a/Documentation/networking/ip-sysctl.txt
-+++ b/Documentation/networking/ip-sysctl.txt
-@@ -116,7 +116,7 @@ ipfrag_high_thresh - LONG INTEGER
- Maximum memory used to reassemble IP fragments.
-
- ipfrag_low_thresh - LONG INTEGER
-- (Obsolete since linux-4.17)
-+ (Obsolete since linux-4.4.174, backported from linux-4.17)
- Maximum memory used to reassemble IP fragments before the kernel
- begins to remove incomplete fragment queues to free up resources.
- The kernel still accepts new fragments for defragmentation.
-diff --git a/Makefile b/Makefile
-index 1fa281069379..5f0bdef2af99 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1,6 +1,6 @@
- VERSION = 4
- PATCHLEVEL = 4
--SUBLEVEL = 174
-+SUBLEVEL = 175
- EXTRAVERSION =
- NAME = Blurry Fish Butt
-
-diff --git a/arch/alpha/include/asm/irq.h b/arch/alpha/include/asm/irq.h
-index 06377400dc09..469642801a68 100644
---- a/arch/alpha/include/asm/irq.h
-+++ b/arch/alpha/include/asm/irq.h
-@@ -55,15 +55,15 @@
-
- #elif defined(CONFIG_ALPHA_DP264) || \
- defined(CONFIG_ALPHA_LYNX) || \
-- defined(CONFIG_ALPHA_SHARK) || \
-- defined(CONFIG_ALPHA_EIGER)
-+ defined(CONFIG_ALPHA_SHARK)
- # define NR_IRQS 64
-
- #elif defined(CONFIG_ALPHA_TITAN)
- #define NR_IRQS 80
-
- #elif defined(CONFIG_ALPHA_RAWHIDE) || \
-- defined(CONFIG_ALPHA_TAKARA)
-+ defined(CONFIG_ALPHA_TAKARA) || \
-+ defined(CONFIG_ALPHA_EIGER)
- # define NR_IRQS 128
-
- #elif defined(CONFIG_ALPHA_WILDFIRE)
-diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
-index 4a905bd667e2..0f68f0de9b5e 100644
---- a/arch/alpha/mm/fault.c
-+++ b/arch/alpha/mm/fault.c
-@@ -77,7 +77,7 @@ __load_new_mm_context(struct mm_struct *next_mm)
- /* Macro for exception fixup code to access integer registers. */
- #define dpf_reg(r) \
- (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \
-- (r) <= 18 ? (r)+8 : (r)-10])
-+ (r) <= 18 ? (r)+10 : (r)-10])
-
- asmlinkage void
- do_page_fault(unsigned long address, unsigned long mmcsr,
-diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
-index 6881757b03e8..67369f284b91 100644
---- a/arch/arm/boot/dts/da850-evm.dts
-+++ b/arch/arm/boot/dts/da850-evm.dts
-@@ -147,7 +147,7 @@
-
- sound {
- compatible = "simple-audio-card";
-- simple-audio-card,name = "DA850/OMAP-L138 EVM";
-+ simple-audio-card,name = "DA850-OMAPL138 EVM";
- simple-audio-card,widgets =
- "Line", "Line In",
- "Line", "Line Out";
-diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
-index 113dcf056dcf..1b2dacfa6132 100644
---- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
-+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
-@@ -35,8 +35,8 @@
- compatible = "gpio-fan";
- pinctrl-0 = <&pmx_fan_high_speed &pmx_fan_low_speed>;
- pinctrl-names = "default";
-- gpios = <&gpio1 14 GPIO_ACTIVE_LOW
-- &gpio1 13 GPIO_ACTIVE_LOW>;
-+ gpios = <&gpio1 14 GPIO_ACTIVE_HIGH
-+ &gpio1 13 GPIO_ACTIVE_HIGH>;
- gpio-fan,speed-map = <0 0
- 3000 1
- 6000 2>;
-diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
-index 766bbb8495b6..47e5b63339d1 100644
---- a/arch/arm/boot/dts/mmp2.dtsi
-+++ b/arch/arm/boot/dts/mmp2.dtsi
-@@ -220,12 +220,15 @@
- status = "disabled";
- };
-
-- twsi2: i2c@d4025000 {
-+ twsi2: i2c@d4031000 {
- compatible = "mrvl,mmp-twsi";
-- reg = <0xd4025000 0x1000>;
-- interrupts = <58>;
-+ reg = <0xd4031000 0x1000>;
-+ interrupt-parent = <&intcmux17>;
-+ interrupts = <0>;
- clocks = <&soc_clocks MMP2_CLK_TWSI1>;
- resets = <&soc_clocks MMP2_CLK_TWSI1>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
- status = "disabled";
- };
-
-diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
-index f0bdc41f8eff..235d1493f8aa 100644
---- a/arch/arm/boot/dts/omap4-sdp.dts
-+++ b/arch/arm/boot/dts/omap4-sdp.dts
-@@ -33,6 +33,7 @@
- gpio = <&gpio2 16 GPIO_ACTIVE_HIGH>; /* gpio line 48 */
- enable-active-high;
- regulator-boot-on;
-+ startup-delay-us = <25000>;
- };
-
- vbat: fixedregulator-vbat {
-diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
-index b26361355dae..e42be5800f37 100644
---- a/arch/arm/kernel/smp.c
-+++ b/arch/arm/kernel/smp.c
-@@ -687,6 +687,21 @@ void smp_send_stop(void)
- pr_warn("SMP: failed to stop secondary CPUs\n");
- }
-
-+/* In case panic() and panic() called at the same time on CPU1 and CPU2,
-+ * and CPU 1 calls panic_smp_self_stop() before crash_smp_send_stop()
-+ * CPU1 can't receive the ipi irqs from CPU2, CPU1 will be always online,
-+ * kdump fails. So split out the panic_smp_self_stop() and add
-+ * set_cpu_online(smp_processor_id(), false).
-+ */
-+void panic_smp_self_stop(void)
-+{
-+ pr_debug("CPU %u will stop doing anything useful since another CPU has paniced\n",
-+ smp_processor_id());
-+ set_cpu_online(smp_processor_id(), false);
-+ while (1)
-+ cpu_relax();
-+}
-+
- /*
- * not supported here
- */
-diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
-index 387ee2a11e36..885cd0e0015b 100644
---- a/arch/arm/kvm/mmio.c
-+++ b/arch/arm/kvm/mmio.c
-@@ -118,6 +118,12 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
- vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data);
- }
-
-+ /*
-+ * The MMIO instruction is emulated and should not be re-executed
-+ * in the guest.
-+ */
-+ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-+
- return 0;
- }
-
-@@ -151,11 +157,6 @@ static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len)
- vcpu->arch.mmio_decode.sign_extend = sign_extend;
- vcpu->arch.mmio_decode.rt = rt;
-
-- /*
-- * The MMIO instruction is emulated and should not be re-executed
-- * in the guest.
-- */
-- kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
- return 0;
- }
-
-diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
-index 38b0da300dd5..423a88ff908c 100644
---- a/arch/arm/mach-integrator/impd1.c
-+++ b/arch/arm/mach-integrator/impd1.c
-@@ -394,7 +394,11 @@ static int __init_refok impd1_probe(struct lm_device *dev)
- sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
- GFP_KERNEL);
- chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
-- mmciname = kasprintf(GFP_KERNEL, "lm%x:00700", dev->id);
-+ mmciname = devm_kasprintf(&dev->dev, GFP_KERNEL,
-+ "lm%x:00700", dev->id);
-+ if (!lookup || !chipname || !mmciname)
-+ return -ENOMEM;
-+
- lookup->dev_id = mmciname;
- /*
- * Offsets on GPIO block 1:
-diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
-index c1cd80ecc219..a904244264ce 100644
---- a/arch/arm/mach-iop32x/n2100.c
-+++ b/arch/arm/mach-iop32x/n2100.c
-@@ -75,8 +75,7 @@ void __init n2100_map_io(void)
- /*
- * N2100 PCI.
- */
--static int __init
--n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+static int n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
- {
- int irq;
-
-diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
-index 147c90e70b2e..36706d32d656 100644
---- a/arch/arm/mach-omap2/omap_hwmod.c
-+++ b/arch/arm/mach-omap2/omap_hwmod.c
-@@ -2526,7 +2526,7 @@ static int __init _init(struct omap_hwmod *oh, void *data)
- * a stub; implementing this properly requires iclk autoidle usecounting in
- * the clock code. No return value.
- */
--static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
-+static void _setup_iclk_autoidle(struct omap_hwmod *oh)
- {
- struct omap_hwmod_ocp_if *os;
- struct list_head *p;
-@@ -2561,7 +2561,7 @@ static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
- * reset. Returns 0 upon success or a negative error code upon
- * failure.
- */
--static int __init _setup_reset(struct omap_hwmod *oh)
-+static int _setup_reset(struct omap_hwmod *oh)
- {
- int r;
-
-@@ -2622,7 +2622,7 @@ static int __init _setup_reset(struct omap_hwmod *oh)
- *
- * No return value.
- */
--static void __init _setup_postsetup(struct omap_hwmod *oh)
-+static void _setup_postsetup(struct omap_hwmod *oh)
- {
- u8 postsetup_state;
-
-diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
-index a7dae60810e8..307fc18edede 100644
---- a/arch/arm/mach-pxa/cm-x300.c
-+++ b/arch/arm/mach-pxa/cm-x300.c
-@@ -547,7 +547,7 @@ static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
- .exit = cm_x300_u2d_exit,
- };
-
--static void cm_x300_init_u2d(void)
-+static void __init cm_x300_init_u2d(void)
- {
- pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
- }
-diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
-index 5d665588c7eb..05aa7071efd6 100644
---- a/arch/arm/mach-pxa/littleton.c
-+++ b/arch/arm/mach-pxa/littleton.c
-@@ -183,7 +183,7 @@ static struct pxafb_mach_info littleton_lcd_info = {
- .lcd_conn = LCD_COLOR_TFT_16BPP,
- };
-
--static void littleton_init_lcd(void)
-+static void __init littleton_init_lcd(void)
- {
- pxa_set_fb_info(NULL, &littleton_lcd_info);
- }
-diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
-index d757cfb5f8a6..4da2458d7f32 100644
---- a/arch/arm/mach-pxa/zeus.c
-+++ b/arch/arm/mach-pxa/zeus.c
-@@ -558,7 +558,7 @@ static struct pxaohci_platform_data zeus_ohci_platform_data = {
- .flags = ENABLE_PORT_ALL | POWER_SENSE_LOW,
- };
-
--static void zeus_register_ohci(void)
-+static void __init zeus_register_ohci(void)
- {
- /* Port 2 is shared between host and client interface. */
- UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
-diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
-index 0f03a8fe2314..d18d15810d19 100644
---- a/arch/arm64/kernel/entry-ftrace.S
-+++ b/arch/arm64/kernel/entry-ftrace.S
-@@ -78,7 +78,6 @@
- .macro mcount_get_lr reg
- ldr \reg, [x29]
- ldr \reg, [\reg, #8]
-- mcount_adjust_addr \reg, \reg
- .endm
-
- .macro mcount_get_lr_addr reg
-diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
-index 1b6f2f219298..9db764b51ffe 100644
---- a/arch/mips/include/uapi/asm/inst.h
-+++ b/arch/mips/include/uapi/asm/inst.h
-@@ -290,8 +290,8 @@ enum mm_32a_minor_op {
- mm_ext_op = 0x02c,
- mm_pool32axf_op = 0x03c,
- mm_srl32_op = 0x040,
-+ mm_srlv32_op = 0x050,
- mm_sra_op = 0x080,
-- mm_srlv32_op = 0x090,
- mm_rotr_op = 0x0c0,
- mm_lwxs_op = 0x118,
- mm_addu32_op = 0x150,
-diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
-index 1448c1f43d4e..76f18c56141c 100644
---- a/arch/mips/kernel/mips-cm.c
-+++ b/arch/mips/kernel/mips-cm.c
-@@ -424,5 +424,5 @@ void mips_cm_error_report(void)
- }
-
- /* reprime cause register */
-- write_gcr_error_cause(0);
-+ write_gcr_error_cause(cm_error);
- }
-diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
-index c258cd406fbb..b36bbda31058 100644
---- a/arch/mips/pci/pci-octeon.c
-+++ b/arch/mips/pci/pci-octeon.c
-@@ -571,6 +571,11 @@ static int __init octeon_pci_setup(void)
- if (octeon_has_feature(OCTEON_FEATURE_PCIE))
- return 0;
-
-+ if (!octeon_is_pci_host()) {
-+ pr_notice("Not in host mode, PCI Controller not initialized\n");
-+ return 0;
-+ }
-+
- /* Point pcibios_map_irq() to the PCI version of it */
- octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
-
-@@ -582,11 +587,6 @@ static int __init octeon_pci_setup(void)
- else
- octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
-
-- if (!octeon_is_pci_host()) {
-- pr_notice("Not in host mode, PCI Controller not initialized\n");
-- return 0;
-- }
--
- /* PCI I/O and PCI MEM values */
- set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
- ioport_resource.start = 0;
-diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
-index 6c7d78546eee..886005b1e87d 100644
---- a/arch/mips/vdso/Makefile
-+++ b/arch/mips/vdso/Makefile
-@@ -107,7 +107,7 @@ $(obj)/%-o32.o: $(src)/%.c FORCE
- $(call cmd,force_checksrc)
- $(call if_changed_rule,cc_o_c)
-
--$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
-+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=32
- $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
- $(call if_changed_dep,cpp_lds_S)
-
-@@ -143,7 +143,7 @@ $(obj)/%-n32.o: $(src)/%.c FORCE
- $(call cmd,force_checksrc)
- $(call if_changed_rule,cc_o_c)
-
--$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
-+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=n32
- $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
- $(call if_changed_dep,cpp_lds_S)
-
-diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
-index a5ffe0207c16..05f1389228d2 100644
---- a/arch/powerpc/include/asm/uaccess.h
-+++ b/arch/powerpc/include/asm/uaccess.h
-@@ -59,7 +59,7 @@
- #endif
-
- #define access_ok(type, addr, size) \
-- (__chk_user_ptr(addr), \
-+ (__chk_user_ptr(addr), (void)(type), \
- __access_ok((__force unsigned long)(addr), (size), get_fs()))
-
- /*
-diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
-index 96536c969c9c..a8efed3b4691 100644
---- a/arch/powerpc/platforms/pseries/dlpar.c
-+++ b/arch/powerpc/platforms/pseries/dlpar.c
-@@ -280,6 +280,8 @@ int dlpar_detach_node(struct device_node *dn)
- if (rc)
- return rc;
-
-+ of_node_put(dn);
-+
- return 0;
- }
-
-diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
-index 18eb9924dda3..aeb430212947 100644
---- a/arch/um/include/asm/pgtable.h
-+++ b/arch/um/include/asm/pgtable.h
-@@ -197,12 +197,17 @@ static inline pte_t pte_mkold(pte_t pte)
-
- static inline pte_t pte_wrprotect(pte_t pte)
- {
-- pte_clear_bits(pte, _PAGE_RW);
-+ if (likely(pte_get_bits(pte, _PAGE_RW)))
-+ pte_clear_bits(pte, _PAGE_RW);
-+ else
-+ return pte;
- return(pte_mknewprot(pte));
- }
-
- static inline pte_t pte_mkread(pte_t pte)
- {
-+ if (unlikely(pte_get_bits(pte, _PAGE_USER)))
-+ return pte;
- pte_set_bits(pte, _PAGE_USER);
- return(pte_mknewprot(pte));
- }
-@@ -221,6 +226,8 @@ static inline pte_t pte_mkyoung(pte_t pte)
-
- static inline pte_t pte_mkwrite(pte_t pte)
- {
-+ if (unlikely(pte_get_bits(pte, _PAGE_RW)))
-+ return pte;
- pte_set_bits(pte, _PAGE_RW);
- return(pte_mknewprot(pte));
- }
-diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
-index ae6aad1d24f7..b348c4641312 100644
---- a/arch/x86/ia32/ia32_aout.c
-+++ b/arch/x86/ia32/ia32_aout.c
-@@ -50,7 +50,7 @@ static unsigned long get_dr(int n)
- /*
- * fill in the user structure for a core dump..
- */
--static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
-+static void fill_dump(struct pt_regs *regs, struct user32 *dump)
- {
- u32 fs, gs;
- memset(dump, 0, sizeof(*dump));
-@@ -156,10 +156,12 @@ static int aout_core_dump(struct coredump_params *cprm)
- fs = get_fs();
- set_fs(KERNEL_DS);
- has_dumped = 1;
-+
-+ fill_dump(cprm->regs, &dump);
-+
- strncpy(dump.u_comm, current->comm, sizeof(current->comm));
- dump.u_ar0 = offsetof(struct user32, regs);
- dump.signal = cprm->siginfo->si_signo;
-- dump_thread32(cprm->regs, &dump);
-
- /*
- * If the size of the dump file exceeds the rlimit, then see
-diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
-index 16825dda18dc..66a5e60f60c4 100644
---- a/arch/x86/include/asm/fpu/internal.h
-+++ b/arch/x86/include/asm/fpu/internal.h
-@@ -94,6 +94,9 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu);
- #define user_insn(insn, output, input...) \
- ({ \
- int err; \
-+ \
-+ might_fault(); \
-+ \
- asm volatile(ASM_STAC "\n" \
- "1:" #insn "\n\t" \
- "2: " ASM_CLAC "\n" \
-diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
-index 71605c7d5c5c..8b7594f2d48f 100644
---- a/arch/x86/include/asm/uv/bios.h
-+++ b/arch/x86/include/asm/uv/bios.h
-@@ -48,7 +48,8 @@ enum {
- BIOS_STATUS_SUCCESS = 0,
- BIOS_STATUS_UNIMPLEMENTED = -ENOSYS,
- BIOS_STATUS_EINVAL = -EINVAL,
-- BIOS_STATUS_UNAVAIL = -EBUSY
-+ BIOS_STATUS_UNAVAIL = -EBUSY,
-+ BIOS_STATUS_ABORT = -EINTR,
- };
-
- /*
-@@ -111,4 +112,9 @@ extern long system_serial_number;
-
- extern struct kobject *sgi_uv_kobj; /* /sys/firmware/sgi_uv */
-
-+/*
-+ * EFI runtime lock; cf. firmware/efi/runtime-wrappers.c for details
-+ */
-+extern struct semaphore __efi_uv_runtime_lock;
-+
- #endif /* _ASM_X86_UV_BIOS_H */
-diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
-index 7b8c8c838191..77f7580e22c6 100644
---- a/arch/x86/kernel/cpu/mcheck/mce.c
-+++ b/arch/x86/kernel/cpu/mcheck/mce.c
-@@ -670,6 +670,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
- }
-
- if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
-+ m->bank = i;
- *msg = tmp;
- ret = 1;
- }
-diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
-index f0f4fcba252e..947579425861 100644
---- a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
-+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
-@@ -1081,6 +1081,8 @@ static struct pci_driver snbep_uncore_pci_driver = {
- .id_table = snbep_uncore_pci_ids,
- };
-
-+#define NODE_ID_MASK 0x7
-+
- /*
- * build pci bus to socket mapping
- */
-@@ -1102,7 +1104,7 @@ static int snbep_pci2phy_map_init(int devid)
- err = pci_read_config_dword(ubox_dev, 0x40, &config);
- if (err)
- break;
-- nodeid = config;
-+ nodeid = config & NODE_ID_MASK;
- /* get the Node ID mapping */
- err = pci_read_config_dword(ubox_dev, 0x54, &config);
- if (err)
-diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
-index ecdf724da371..7ce1a19d9d8b 100644
---- a/arch/x86/kvm/svm.c
-+++ b/arch/x86/kvm/svm.c
-@@ -4156,6 +4156,13 @@ static bool svm_cpu_has_accelerated_tpr(void)
-
- static bool svm_has_emulated_msr(int index)
- {
-+ switch (index) {
-+ case MSR_IA32_MCG_EXT_CTL:
-+ return false;
-+ default:
-+ break;
-+ }
-+
- return true;
- }
-
-diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
-index 3bdb2e747b89..aee2886a387c 100644
---- a/arch/x86/kvm/vmx.c
-+++ b/arch/x86/kvm/vmx.c
-@@ -6965,6 +6965,7 @@ static void free_nested(struct vcpu_vmx *vmx)
- if (!vmx->nested.vmxon)
- return;
-
-+ hrtimer_cancel(&vmx->nested.preemption_timer);
- vmx->nested.vmxon = false;
- free_vpid(vmx->nested.vpid02);
- nested_release_vmcs12(vmx);
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index 758e2b39567d..6bd0538d8ebf 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -4247,6 +4247,13 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
- {
- u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
-
-+ /*
-+ * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
-+ * is returned, but our callers are not ready for that and they blindly
-+ * call kvm_inject_page_fault. Ensure that they at least do not leak
-+ * uninitialized kernel stack memory into cr2 and error code.
-+ */
-+ memset(exception, 0, sizeof(*exception));
- return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
- exception);
- }
-diff --git a/arch/x86/pci/broadcom_bus.c b/arch/x86/pci/broadcom_bus.c
-index 526536c81ddc..ca1e8e6dccc8 100644
---- a/arch/x86/pci/broadcom_bus.c
-+++ b/arch/x86/pci/broadcom_bus.c
-@@ -50,8 +50,8 @@ static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
- word1 = read_pci_config_16(bus, slot, func, 0xc0);
- word2 = read_pci_config_16(bus, slot, func, 0xc2);
- if (word1 != word2) {
-- res.start = (word1 << 16) | 0x0000;
-- res.end = (word2 << 16) | 0xffff;
-+ res.start = ((resource_size_t) word1 << 16) | 0x0000;
-+ res.end = ((resource_size_t) word2 << 16) | 0xffff;
- res.flags = IORESOURCE_MEM;
- update_res(info, res.start, res.end, res.flags, 0);
- }
-diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
-index 1584cbed0dce..a45a1c5aabea 100644
---- a/arch/x86/platform/uv/bios_uv.c
-+++ b/arch/x86/platform/uv/bios_uv.c
-@@ -28,7 +28,8 @@
-
- static struct uv_systab uv_systab;
-
--s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
-+static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
-+ u64 a4, u64 a5)
- {
- struct uv_systab *tab = &uv_systab;
- s64 ret;
-@@ -43,6 +44,19 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
- a1, a2, a3, a4, a5);
- return ret;
- }
-+
-+s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
-+{
-+ s64 ret;
-+
-+ if (down_interruptible(&__efi_uv_runtime_lock))
-+ return BIOS_STATUS_ABORT;
-+
-+ ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
-+ up(&__efi_uv_runtime_lock);
-+
-+ return ret;
-+}
- EXPORT_SYMBOL_GPL(uv_bios_call);
-
- s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
-@@ -51,10 +65,15 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
- unsigned long bios_flags;
- s64 ret;
-
-+ if (down_interruptible(&__efi_uv_runtime_lock))
-+ return BIOS_STATUS_ABORT;
-+
- local_irq_save(bios_flags);
-- ret = uv_bios_call(which, a1, a2, a3, a4, a5);
-+ ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
- local_irq_restore(bios_flags);
-
-+ up(&__efi_uv_runtime_lock);
-+
- return ret;
- }
-
-diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
-index 8804127b108c..21b80f5ee092 100644
---- a/drivers/ata/sata_rcar.c
-+++ b/drivers/ata/sata_rcar.c
-@@ -875,7 +875,9 @@ static int sata_rcar_probe(struct platform_device *pdev)
- int ret = 0;
-
- irq = platform_get_irq(pdev, 0);
-- if (irq <= 0)
-+ if (irq < 0)
-+ return irq;
-+ if (!irq)
- return -EINVAL;
-
- priv = devm_kzalloc(&pdev->dev, sizeof(struct sata_rcar_priv),
-diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
-index e80cbefbc2b5..27e1abcf5710 100644
---- a/drivers/block/drbd/drbd_nl.c
-+++ b/drivers/block/drbd/drbd_nl.c
-@@ -632,14 +632,15 @@ drbd_set_role(struct drbd_device *const device, enum drbd_role new_role, int for
- if (rv == SS_TWO_PRIMARIES) {
- /* Maybe the peer is detected as dead very soon...
- retry at most once more in this case. */
-- int timeo;
-- rcu_read_lock();
-- nc = rcu_dereference(connection->net_conf);
-- timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
-- rcu_read_unlock();
-- schedule_timeout_interruptible(timeo);
-- if (try < max_tries)
-+ if (try < max_tries) {
-+ int timeo;
- try = max_tries - 1;
-+ rcu_read_lock();
-+ nc = rcu_dereference(connection->net_conf);
-+ timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
-+ rcu_read_unlock();
-+ schedule_timeout_interruptible(timeo);
-+ }
- continue;
- }
- if (rv < SS_SUCCESS) {
-diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
-index b4b5680ac6ad..b1ee358edd3b 100644
---- a/drivers/block/drbd/drbd_receiver.c
-+++ b/drivers/block/drbd/drbd_receiver.c
-@@ -3126,7 +3126,7 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
- enum drbd_conns rv = C_MASK;
- enum drbd_disk_state mydisk;
- struct net_conf *nc;
-- int hg, rule_nr, rr_conflict, tentative;
-+ int hg, rule_nr, rr_conflict, tentative, always_asbp;
-
- mydisk = device->state.disk;
- if (mydisk == D_NEGOTIATING)
-@@ -3168,8 +3168,12 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
-
- rcu_read_lock();
- nc = rcu_dereference(peer_device->connection->net_conf);
-+ always_asbp = nc->always_asbp;
-+ rr_conflict = nc->rr_conflict;
-+ tentative = nc->tentative;
-+ rcu_read_unlock();
-
-- if (hg == 100 || (hg == -100 && nc->always_asbp)) {
-+ if (hg == 100 || (hg == -100 && always_asbp)) {
- int pcount = (device->state.role == R_PRIMARY)
- + (peer_role == R_PRIMARY);
- int forced = (hg == -100);
-@@ -3208,9 +3212,6 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
- "Sync from %s node\n",
- (hg < 0) ? "peer" : "this");
- }
-- rr_conflict = nc->rr_conflict;
-- tentative = nc->tentative;
-- rcu_read_unlock();
-
- if (hg == -100) {
- /* FIXME this log message is not correct if we end up here
-@@ -3889,7 +3890,7 @@ static int receive_uuids(struct drbd_connection *connection, struct packet_info
- kfree(device->p_uuid);
- device->p_uuid = p_uuid;
-
-- if (device->state.conn < C_CONNECTED &&
-+ if ((device->state.conn < C_CONNECTED || device->state.pdsk == D_DISKLESS) &&
- device->state.disk < D_INCONSISTENT &&
- device->state.role == R_PRIMARY &&
- (device->ed_uuid & ~((u64)1)) != (p_uuid[UI_CURRENT] & ~((u64)1))) {
-diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
-index 4b911ed96ea3..31219fb9e7f4 100644
---- a/drivers/block/sunvdc.c
-+++ b/drivers/block/sunvdc.c
-@@ -40,6 +40,8 @@ MODULE_VERSION(DRV_MODULE_VERSION);
- #define WAITING_FOR_GEN_CMD 0x04
- #define WAITING_FOR_ANY -1
-
-+#define VDC_MAX_RETRIES 10
-+
- static struct workqueue_struct *sunvdc_wq;
-
- struct vdc_req_entry {
-@@ -419,6 +421,7 @@ static int __vdc_tx_trigger(struct vdc_port *port)
- .end_idx = dr->prod,
- };
- int err, delay;
-+ int retries = 0;
-
- hdr.seq = dr->snd_nxt;
- delay = 1;
-@@ -431,6 +434,8 @@ static int __vdc_tx_trigger(struct vdc_port *port)
- udelay(delay);
- if ((delay <<= 1) > 128)
- delay = 128;
-+ if (retries++ > VDC_MAX_RETRIES)
-+ break;
- } while (err == -EAGAIN);
-
- if (err == -ENOTCONN)
-diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
-index c264f2d284a7..2e0a9e2531cb 100644
---- a/drivers/block/swim3.c
-+++ b/drivers/block/swim3.c
-@@ -1027,7 +1027,11 @@ static void floppy_release(struct gendisk *disk, fmode_t mode)
- struct swim3 __iomem *sw = fs->swim3;
-
- mutex_lock(&swim3_mutex);
-- if (fs->ref_count > 0 && --fs->ref_count == 0) {
-+ if (fs->ref_count > 0)
-+ --fs->ref_count;
-+ else if (fs->ref_count == -1)
-+ fs->ref_count = 0;
-+ if (fs->ref_count == 0) {
- swim3_action(fs, MOTOR_OFF);
- out_8(&sw->control_bic, 0xff);
- swim3_select(fs, RELAX);
-diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
-index e2808fefbb78..1852d19d0d7b 100644
---- a/drivers/cdrom/gdrom.c
-+++ b/drivers/cdrom/gdrom.c
-@@ -882,6 +882,7 @@ static void __exit exit_gdrom(void)
- platform_device_unregister(pd);
- platform_driver_unregister(&gdrom_driver);
- kfree(gd.toc);
-+ kfree(gd.cd_info);
- }
-
- module_init(init_gdrom);
-diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c
-index 1be6230a07af..8b6306dc5fc6 100644
---- a/drivers/clk/imx/clk-imx6sl.c
-+++ b/drivers/clk/imx/clk-imx6sl.c
-@@ -17,6 +17,8 @@
-
- #include "clk.h"
-
-+#define CCDR 0x4
-+#define BM_CCM_CCDR_MMDC_CH0_MASK (1 << 17)
- #define CCSR 0xc
- #define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2)
- #define CACRR 0x10
-@@ -414,6 +416,10 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
- clks[IMX6SL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
- clks[IMX6SL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8);
-
-+ /* Ensure the MMDC CH0 handshake is bypassed */
-+ writel_relaxed(readl_relaxed(base + CCDR) |
-+ BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
-+
- imx_check_clocks(clks, ARRAY_SIZE(clks));
-
- clk_data.clks = clks;
-diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
-index db2ede565f1a..b44476a1b7ad 100644
---- a/drivers/cpuidle/cpuidle-big_little.c
-+++ b/drivers/cpuidle/cpuidle-big_little.c
-@@ -167,6 +167,7 @@ static int __init bl_idle_init(void)
- {
- int ret;
- struct device_node *root = of_find_node_by_path("/");
-+ const struct of_device_id *match_id;
-
- if (!root)
- return -ENODEV;
-@@ -174,7 +175,11 @@ static int __init bl_idle_init(void)
- /*
- * Initialize the driver just for a compliant set of machines
- */
-- if (!of_match_node(compatible_machine_match, root))
-+ match_id = of_match_node(compatible_machine_match, root);
-+
-+ of_node_put(root);
-+
-+ if (!match_id)
- return -ENODEV;
-
- if (!mcpm_is_available())
-diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
-index 790f7cadc1ed..efebc484e371 100644
---- a/drivers/crypto/ux500/cryp/cryp_core.c
-+++ b/drivers/crypto/ux500/cryp/cryp_core.c
-@@ -555,7 +555,7 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx,
- desc = dmaengine_prep_slave_sg(channel,
- ctx->device->dma.sg_src,
- ctx->device->dma.sg_src_len,
-- direction, DMA_CTRL_ACK);
-+ DMA_MEM_TO_DEV, DMA_CTRL_ACK);
- break;
-
- case DMA_FROM_DEVICE:
-@@ -579,7 +579,7 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx,
- desc = dmaengine_prep_slave_sg(channel,
- ctx->device->dma.sg_dst,
- ctx->device->dma.sg_dst_len,
-- direction,
-+ DMA_DEV_TO_MEM,
- DMA_CTRL_ACK |
- DMA_PREP_INTERRUPT);
-
-diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
-index cd4398498495..bca6b701c067 100644
---- a/drivers/crypto/ux500/hash/hash_core.c
-+++ b/drivers/crypto/ux500/hash/hash_core.c
-@@ -181,7 +181,7 @@ static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg,
- __func__);
- desc = dmaengine_prep_slave_sg(channel,
- ctx->device->dma.sg, ctx->device->dma.sg_len,
-- direction, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
-+ DMA_MEM_TO_DEV, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
- if (!desc) {
- dev_err(ctx->device->dev,
- "%s: dmaengine_prep_slave_sg() failed!\n", __func__);
-diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
-index 48d85f8b95fe..dfa337ae06fc 100644
---- a/drivers/dma/imx-dma.c
-+++ b/drivers/dma/imx-dma.c
-@@ -619,7 +619,7 @@ static void imxdma_tasklet(unsigned long data)
- {
- struct imxdma_channel *imxdmac = (void *)data;
- struct imxdma_engine *imxdma = imxdmac->imxdma;
-- struct imxdma_desc *desc;
-+ struct imxdma_desc *desc, *next_desc;
- unsigned long flags;
-
- spin_lock_irqsave(&imxdma->lock, flags);
-@@ -649,10 +649,10 @@ static void imxdma_tasklet(unsigned long data)
- list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
-
- if (!list_empty(&imxdmac->ld_queue)) {
-- desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
-- node);
-+ next_desc = list_first_entry(&imxdmac->ld_queue,
-+ struct imxdma_desc, node);
- list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
-- if (imxdma_xfer_desc(desc) < 0)
-+ if (imxdma_xfer_desc(next_desc) < 0)
- dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
- __func__, imxdmac->channel);
- }
-diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
-index 228bbf910461..906d0224f50d 100644
---- a/drivers/firmware/efi/runtime-wrappers.c
-+++ b/drivers/firmware/efi/runtime-wrappers.c
-@@ -87,6 +87,13 @@ static DEFINE_SPINLOCK(efi_runtime_lock);
- * context through efi_pstore_write().
- */
-
-+/*
-+ * Expose the EFI runtime lock to the UV platform
-+ */
-+#ifdef CONFIG_X86_UV
-+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
-+#endif
-+
- /*
- * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
- * the EFI specification requires that callers of the time related runtime
-diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
-index f1a204d253cc..ac22b8d86249 100644
---- a/drivers/gpu/drm/drm_bufs.c
-+++ b/drivers/gpu/drm/drm_bufs.c
-@@ -36,6 +36,8 @@
- #include
- #include "drm_legacy.h"
-
-+#include
-+
- static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
- struct drm_local_map *map)
- {
-@@ -1332,6 +1334,7 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data,
- idx, dma->buf_count - 1);
- return -EINVAL;
- }
-+ idx = array_index_nospec(idx, dma->buf_count);
- buf = dma->buflist[idx];
- if (buf->file_priv != file_priv) {
- DRM_ERROR("Process %d freeing buffer not owned\n",
-diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
-index 71a10f08522e..a5b052203c2c 100644
---- a/drivers/gpu/drm/drm_modes.c
-+++ b/drivers/gpu/drm/drm_modes.c
-@@ -722,7 +722,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
- if (mode->hsync)
- return mode->hsync;
-
-- if (mode->htotal < 0)
-+ if (mode->htotal <= 0)
- return 0;
-
- calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
-diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
-index be3971b22a02..ed92b9ac01b2 100644
---- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
-+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
-@@ -594,13 +594,16 @@ out_fixup:
- static int vmw_dma_masks(struct vmw_private *dev_priv)
- {
- struct drm_device *dev = dev_priv->dev;
-+ int ret = 0;
-
-- if (intel_iommu_enabled &&
-+ ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
-+ if (dev_priv->map_mode != vmw_dma_phys &&
- (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
- DRM_INFO("Restricting DMA addresses to 44 bits.\n");
-- return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
-+ return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
- }
-- return 0;
-+
-+ return ret;
- }
- #else
- static int vmw_dma_masks(struct vmw_private *dev_priv)
-diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
-index fda8e85dd5a2..ad0dd566aded 100644
---- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
-+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
-@@ -3663,7 +3663,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
- *p_fence = NULL;
- }
-
-- return 0;
-+ return ret;
- }
-
- /**
-diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
-index 6c60f4b63d21..d7179dd3c9ef 100644
---- a/drivers/hid/hid-debug.c
-+++ b/drivers/hid/hid-debug.c
-@@ -30,6 +30,7 @@
-
- #include
- #include
-+#include
- #include
- #include
- #include
-@@ -455,7 +456,7 @@ static char *resolv_usage_page(unsigned page, struct seq_file *f) {
- char *buf = NULL;
-
- if (!f) {
-- buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
-+ buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC);
- if (!buf)
- return ERR_PTR(-ENOMEM);
- }
-@@ -659,17 +660,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
- /* enqueue string to 'events' ring buffer */
- void hid_debug_event(struct hid_device *hdev, char *buf)
- {
-- int i;
- struct hid_debug_list *list;
- unsigned long flags;
-
- spin_lock_irqsave(&hdev->debug_list_lock, flags);
-- list_for_each_entry(list, &hdev->debug_list, node) {
-- for (i = 0; i < strlen(buf); i++)
-- list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
-- buf[i];
-- list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
-- }
-+ list_for_each_entry(list, &hdev->debug_list, node)
-+ kfifo_in(&list->hid_debug_fifo, buf, strlen(buf));
- spin_unlock_irqrestore(&hdev->debug_list_lock, flags);
-
- wake_up_interruptible(&hdev->debug_wait);
-@@ -720,8 +716,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
- hid_debug_event(hdev, buf);
-
- kfree(buf);
-- wake_up_interruptible(&hdev->debug_wait);
--
-+ wake_up_interruptible(&hdev->debug_wait);
- }
- EXPORT_SYMBOL_GPL(hid_dump_input);
-
-@@ -1086,8 +1081,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
- goto out;
- }
-
-- if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
-- err = -ENOMEM;
-+ err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL);
-+ if (err) {
- kfree(list);
- goto out;
- }
-@@ -1107,77 +1102,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
- size_t count, loff_t *ppos)
- {
- struct hid_debug_list *list = file->private_data;
-- int ret = 0, len;
-+ int ret = 0, copied;
- DECLARE_WAITQUEUE(wait, current);
-
- mutex_lock(&list->read_mutex);
-- while (ret == 0) {
-- if (list->head == list->tail) {
-- add_wait_queue(&list->hdev->debug_wait, &wait);
-- set_current_state(TASK_INTERRUPTIBLE);
--
-- while (list->head == list->tail) {
-- if (file->f_flags & O_NONBLOCK) {
-- ret = -EAGAIN;
-- break;
-- }
-- if (signal_pending(current)) {
-- ret = -ERESTARTSYS;
-- break;
-- }
-+ if (kfifo_is_empty(&list->hid_debug_fifo)) {
-+ add_wait_queue(&list->hdev->debug_wait, &wait);
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ while (kfifo_is_empty(&list->hid_debug_fifo)) {
-+ if (file->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ break;
-+ }
-
-- if (!list->hdev || !list->hdev->debug) {
-- ret = -EIO;
-- set_current_state(TASK_RUNNING);
-- goto out;
-- }
-+ if (signal_pending(current)) {
-+ ret = -ERESTARTSYS;
-+ break;
-+ }
-
-- /* allow O_NONBLOCK from other threads */
-- mutex_unlock(&list->read_mutex);
-- schedule();
-- mutex_lock(&list->read_mutex);
-- set_current_state(TASK_INTERRUPTIBLE);
-+ /* if list->hdev is NULL we cannot remove_wait_queue().
-+ * if list->hdev->debug is 0 then hid_debug_unregister()
-+ * was already called and list->hdev is being destroyed.
-+ * if we add remove_wait_queue() here we can hit a race.
-+ */
-+ if (!list->hdev || !list->hdev->debug) {
-+ ret = -EIO;
-+ set_current_state(TASK_RUNNING);
-+ goto out;
- }
-
-- set_current_state(TASK_RUNNING);
-- remove_wait_queue(&list->hdev->debug_wait, &wait);
-+ /* allow O_NONBLOCK from other threads */
-+ mutex_unlock(&list->read_mutex);
-+ schedule();
-+ mutex_lock(&list->read_mutex);
-+ set_current_state(TASK_INTERRUPTIBLE);
- }
-
-- if (ret)
-- goto out;
-+ __set_current_state(TASK_RUNNING);
-+ remove_wait_queue(&list->hdev->debug_wait, &wait);
-
-- /* pass the ringbuffer contents to userspace */
--copy_rest:
-- if (list->tail == list->head)
-+ if (ret)
- goto out;
-- if (list->tail > list->head) {
-- len = list->tail - list->head;
-- if (len > count)
-- len = count;
--
-- if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
-- ret = -EFAULT;
-- goto out;
-- }
-- ret += len;
-- list->head += len;
-- } else {
-- len = HID_DEBUG_BUFSIZE - list->head;
-- if (len > count)
-- len = count;
--
-- if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
-- ret = -EFAULT;
-- goto out;
-- }
-- list->head = 0;
-- ret += len;
-- count -= len;
-- if (count > 0)
-- goto copy_rest;
-- }
--
- }
-+
-+ /* pass the fifo content to userspace, locking is not needed with only
-+ * one concurrent reader and one concurrent writer
-+ */
-+ ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied);
-+ if (ret)
-+ goto out;
-+ ret = copied;
- out:
- mutex_unlock(&list->read_mutex);
- return ret;
-@@ -1188,7 +1163,7 @@ static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait)
- struct hid_debug_list *list = file->private_data;
-
- poll_wait(file, &list->hdev->debug_wait, wait);
-- if (list->head != list->tail)
-+ if (!kfifo_is_empty(&list->hid_debug_fifo))
- return POLLIN | POLLRDNORM;
- if (!list->hdev->debug)
- return POLLERR | POLLHUP;
-@@ -1203,7 +1178,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
- spin_lock_irqsave(&list->hdev->debug_list_lock, flags);
- list_del(&list->node);
- spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
-- kfree(list->hid_debug_buf);
-+ kfifo_free(&list->hid_debug_fifo);
- kfree(list);
-
- return 0;
-@@ -1254,4 +1229,3 @@ void hid_debug_exit(void)
- {
- debugfs_remove_recursive(hid_debug_root);
- }
--
-diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
-index 8979f1fd5208..24a4a23bdc90 100644
---- a/drivers/hid/hid-lenovo.c
-+++ b/drivers/hid/hid-lenovo.c
-@@ -703,7 +703,9 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
- data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
- data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
- data_pointer->led_mute.dev = dev;
-- led_classdev_register(dev, &data_pointer->led_mute);
-+ ret = led_classdev_register(dev, &data_pointer->led_mute);
-+ if (ret < 0)
-+ goto err;
-
- data_pointer->led_micmute.name = name_micmute;
- data_pointer->led_micmute.brightness_get =
-@@ -711,7 +713,11 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
- data_pointer->led_micmute.brightness_set =
- lenovo_led_brightness_set_tpkbd;
- data_pointer->led_micmute.dev = dev;
-- led_classdev_register(dev, &data_pointer->led_micmute);
-+ ret = led_classdev_register(dev, &data_pointer->led_micmute);
-+ if (ret < 0) {
-+ led_classdev_unregister(&data_pointer->led_mute);
-+ goto err;
-+ }
-
- lenovo_features_set_tpkbd(hdev);
-
-diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
-index 4bcd9b882948..cb6606a0470d 100644
---- a/drivers/hwmon/lm80.c
-+++ b/drivers/hwmon/lm80.c
-@@ -360,9 +360,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
- struct i2c_client *client = data->client;
- unsigned long min, val;
- u8 reg;
-- int err = kstrtoul(buf, 10, &val);
-- if (err < 0)
-- return err;
-+ int rv;
-+
-+ rv = kstrtoul(buf, 10, &val);
-+ if (rv < 0)
-+ return rv;
-
- /* Save fan_min */
- mutex_lock(&data->update_lock);
-@@ -390,8 +392,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
- return -EINVAL;
- }
-
-- reg = (lm80_read_value(client, LM80_REG_FANDIV) &
-- ~(3 << (2 * (nr + 1)))) | (data->fan_div[nr] << (2 * (nr + 1)));
-+ rv = lm80_read_value(client, LM80_REG_FANDIV);
-+ if (rv < 0)
-+ return rv;
-+ reg = (rv & ~(3 << (2 * (nr + 1))))
-+ | (data->fan_div[nr] << (2 * (nr + 1)));
- lm80_write_value(client, LM80_REG_FANDIV, reg);
-
- /* Restore fan_min */
-@@ -623,6 +628,7 @@ static int lm80_probe(struct i2c_client *client,
- struct device *dev = &client->dev;
- struct device *hwmon_dev;
- struct lm80_data *data;
-+ int rv;
-
- data = devm_kzalloc(dev, sizeof(struct lm80_data), GFP_KERNEL);
- if (!data)
-@@ -635,8 +641,14 @@ static int lm80_probe(struct i2c_client *client,
- lm80_init_client(client);
-
- /* A few vars need to be filled upon startup */
-- data->fan[f_min][0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
-- data->fan[f_min][1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
-+ rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
-+ if (rv < 0)
-+ return rv;
-+ data->fan[f_min][0] = rv;
-+ rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
-+ if (rv < 0)
-+ return rv;
-+ data->fan[f_min][1] = rv;
-
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
- data, lm80_groups);
-diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
-index 9c9fd2e87a4b..1c68b05c8649 100644
---- a/drivers/i2c/busses/i2c-axxia.c
-+++ b/drivers/i2c/busses/i2c-axxia.c
-@@ -296,22 +296,7 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
- i2c_int_disable(idev, MST_STATUS_TFL);
- }
-
-- if (status & MST_STATUS_SCC) {
-- /* Stop completed */
-- i2c_int_disable(idev, ~MST_STATUS_TSS);
-- complete(&idev->msg_complete);
-- } else if (status & MST_STATUS_SNS) {
-- /* Transfer done */
-- i2c_int_disable(idev, ~MST_STATUS_TSS);
-- if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
-- axxia_i2c_empty_rx_fifo(idev);
-- complete(&idev->msg_complete);
-- } else if (status & MST_STATUS_TSS) {
-- /* Transfer timeout */
-- idev->msg_err = -ETIMEDOUT;
-- i2c_int_disable(idev, ~MST_STATUS_TSS);
-- complete(&idev->msg_complete);
-- } else if (unlikely(status & MST_STATUS_ERR)) {
-+ if (unlikely(status & MST_STATUS_ERR)) {
- /* Transfer error */
- i2c_int_disable(idev, ~0);
- if (status & MST_STATUS_AL)
-@@ -328,6 +313,21 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
- readl(idev->base + MST_TX_BYTES_XFRD),
- readl(idev->base + MST_TX_XFER));
- complete(&idev->msg_complete);
-+ } else if (status & MST_STATUS_SCC) {
-+ /* Stop completed */
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
-+ complete(&idev->msg_complete);
-+ } else if (status & MST_STATUS_SNS) {
-+ /* Transfer done */
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
-+ if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
-+ axxia_i2c_empty_rx_fifo(idev);
-+ complete(&idev->msg_complete);
-+ } else if (status & MST_STATUS_TSS) {
-+ /* Transfer timeout */
-+ idev->msg_err = -ETIMEDOUT;
-+ i2c_int_disable(idev, ~MST_STATUS_TSS);
-+ complete(&idev->msg_complete);
- }
-
- out:
-diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
-index 1d0e61d7c131..b6c1d1d482c1 100644
---- a/drivers/input/misc/bma150.c
-+++ b/drivers/input/misc/bma150.c
-@@ -482,13 +482,14 @@ static int bma150_register_input_device(struct bma150_data *bma150)
- idev->close = bma150_irq_close;
- input_set_drvdata(idev, bma150);
-
-+ bma150->input = idev;
-+
- error = input_register_device(idev);
- if (error) {
- input_free_device(idev);
- return error;
- }
-
-- bma150->input = idev;
- return 0;
- }
-
-@@ -511,15 +512,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
-
- bma150_init_input_device(bma150, ipoll_dev->input);
-
-+ bma150->input_polled = ipoll_dev;
-+ bma150->input = ipoll_dev->input;
-+
- error = input_register_polled_device(ipoll_dev);
- if (error) {
- input_free_polled_device(ipoll_dev);
- return error;
- }
-
-- bma150->input_polled = ipoll_dev;
-- bma150->input = ipoll_dev->input;
--
- return 0;
- }
-
-diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
-index 30adc5745cba..25ce9047b682 100644
---- a/drivers/input/mouse/elan_i2c_core.c
-+++ b/drivers/input/mouse/elan_i2c_core.c
-@@ -1240,7 +1240,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
- static const struct acpi_device_id elan_acpi_id[] = {
- { "ELAN0000", 0 },
- { "ELAN0100", 0 },
-- { "ELAN0501", 0 },
- { "ELAN0600", 0 },
- { "ELAN0602", 0 },
- { "ELAN0605", 0 },
-@@ -1251,6 +1250,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
- { "ELAN060C", 0 },
- { "ELAN0611", 0 },
- { "ELAN0612", 0 },
-+ { "ELAN0617", 0 },
- { "ELAN0618", 0 },
- { "ELAN061C", 0 },
- { "ELAN061D", 0 },
-diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
-index 84aead19622c..4c1e527f14a5 100644
---- a/drivers/input/mouse/elantech.c
-+++ b/drivers/input/mouse/elantech.c
-@@ -1121,6 +1121,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
- * Asus UX31 0x361f00 20, 15, 0e clickpad
- * Asus UX32VD 0x361f02 00, 15, 0e clickpad
- * Avatar AVIU-145A2 0x361f00 ? clickpad
-+ * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**)
-+ * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**)
- * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
- * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
- * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
-@@ -1173,6 +1175,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
- DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
- },
- },
-+ {
-+ /* Fujitsu H780 also has a middle button */
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"),
-+ },
-+ },
- #endif
- { }
- };
-diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
-index fc6eb752ab35..eb9937225d64 100644
---- a/drivers/iommu/arm-smmu-v3.c
-+++ b/drivers/iommu/arm-smmu-v3.c
-@@ -683,7 +683,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
- u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
-
- q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-- writel(q->cons, q->cons_reg);
-+
-+ /*
-+ * Ensure that all CPU accesses (reads and writes) to the queue
-+ * are complete before we update the cons pointer.
-+ */
-+ mb();
-+ writel_relaxed(q->cons, q->cons_reg);
- }
-
- static int queue_sync_prod(struct arm_smmu_queue *q)
-diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
-index 90449e1e91e5..1b1453d62fed 100644
---- a/drivers/isdn/hisax/hfc_pci.c
-+++ b/drivers/isdn/hisax/hfc_pci.c
-@@ -1169,11 +1169,13 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
- if (cs->debug & L1_DEB_LAPD)
- debugl1(cs, "-> PH_REQUEST_PULL");
- #endif
-+ spin_lock_irqsave(&cs->lock, flags);
- if (!cs->tx_skb) {
- test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
- } else
- test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-+ spin_unlock_irqrestore(&cs->lock, flags);
- break;
- case (HW_RESET | REQUEST):
- spin_lock_irqsave(&cs->lock, flags);
-diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
-index bc4e6825ff62..07eaa9f90712 100644
---- a/drivers/md/dm-thin.c
-+++ b/drivers/md/dm-thin.c
-@@ -256,6 +256,7 @@ struct pool {
-
- spinlock_t lock;
- struct bio_list deferred_flush_bios;
-+ struct bio_list deferred_flush_completions;
- struct list_head prepared_mappings;
- struct list_head prepared_discards;
- struct list_head active_thins;
-@@ -920,6 +921,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
- mempool_free(m, m->tc->pool->mapping_pool);
- }
-
-+static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
-+{
-+ struct pool *pool = tc->pool;
-+ unsigned long flags;
-+
-+ /*
-+ * If the bio has the REQ_FUA flag set we must commit the metadata
-+ * before signaling its completion.
-+ */
-+ if (!bio_triggers_commit(tc, bio)) {
-+ bio_endio(bio);
-+ return;
-+ }
-+
-+ /*
-+ * Complete bio with an error if earlier I/O caused changes to the
-+ * metadata that can't be committed, e.g, due to I/O errors on the
-+ * metadata device.
-+ */
-+ if (dm_thin_aborted_changes(tc->td)) {
-+ bio_io_error(bio);
-+ return;
-+ }
-+
-+ /*
-+ * Batch together any bios that trigger commits and then issue a
-+ * single commit for them in process_deferred_bios().
-+ */
-+ spin_lock_irqsave(&pool->lock, flags);
-+ bio_list_add(&pool->deferred_flush_completions, bio);
-+ spin_unlock_irqrestore(&pool->lock, flags);
-+}
-+
- static void process_prepared_mapping(struct dm_thin_new_mapping *m)
- {
- struct thin_c *tc = m->tc;
-@@ -952,7 +986,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
- */
- if (bio) {
- inc_remap_and_issue_cell(tc, m->cell, m->data_block);
-- bio_endio(bio);
-+ complete_overwrite_bio(tc, bio);
- } else {
- inc_all_io_entry(tc->pool, m->cell->holder);
- remap_and_issue(tc, m->cell->holder, m->data_block);
-@@ -2228,7 +2262,7 @@ static void process_deferred_bios(struct pool *pool)
- {
- unsigned long flags;
- struct bio *bio;
-- struct bio_list bios;
-+ struct bio_list bios, bio_completions;
- struct thin_c *tc;
-
- tc = get_first_thin(pool);
-@@ -2239,26 +2273,36 @@ static void process_deferred_bios(struct pool *pool)
- }
-
- /*
-- * If there are any deferred flush bios, we must commit
-- * the metadata before issuing them.
-+ * If there are any deferred flush bios, we must commit the metadata
-+ * before issuing them or signaling their completion.
- */
- bio_list_init(&bios);
-+ bio_list_init(&bio_completions);
-+
- spin_lock_irqsave(&pool->lock, flags);
- bio_list_merge(&bios, &pool->deferred_flush_bios);
- bio_list_init(&pool->deferred_flush_bios);
-+
-+ bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
-+ bio_list_init(&pool->deferred_flush_completions);
- spin_unlock_irqrestore(&pool->lock, flags);
-
-- if (bio_list_empty(&bios) &&
-+ if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
- !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
- return;
-
- if (commit(pool)) {
-+ bio_list_merge(&bios, &bio_completions);
-+
- while ((bio = bio_list_pop(&bios)))
- bio_io_error(bio);
- return;
- }
- pool->last_commit_jiffies = jiffies;
-
-+ while ((bio = bio_list_pop(&bio_completions)))
-+ bio_endio(bio);
-+
- while ((bio = bio_list_pop(&bios)))
- generic_make_request(bio);
- }
-@@ -2885,6 +2929,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
- INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
- spin_lock_init(&pool->lock);
- bio_list_init(&pool->deferred_flush_bios);
-+ bio_list_init(&pool->deferred_flush_completions);
- INIT_LIST_HEAD(&pool->prepared_mappings);
- INIT_LIST_HEAD(&pool->prepared_discards);
- INIT_LIST_HEAD(&pool->active_thins);
-diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c
-index 9a6c2cc38acb..abce9c4a1a8e 100644
---- a/drivers/media/platform/davinci/vpbe.c
-+++ b/drivers/media/platform/davinci/vpbe.c
-@@ -753,7 +753,7 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
- if (ret) {
- v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
- def_output);
-- return ret;
-+ goto fail_kfree_amp;
- }
-
- printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
-@@ -761,12 +761,15 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
- if (ret) {
- v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
- def_mode);
-- return ret;
-+ goto fail_kfree_amp;
- }
- vpbe_dev->initialized = 1;
- /* TBD handling of bootargs for default output and mode */
- return 0;
-
-+fail_kfree_amp:
-+ mutex_lock(&vpbe_dev->lock);
-+ kfree(vpbe_dev->amp);
- fail_kfree_encoders:
- kfree(vpbe_dev->encoders);
- fail_dev_unregister:
-diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
-index a0547dbf9806..4d673a626db4 100644
---- a/drivers/memstick/core/memstick.c
-+++ b/drivers/memstick/core/memstick.c
-@@ -18,6 +18,7 @@
- #include
- #include
- #include
-+#include
-
- #define DRIVER_NAME "memstick"
-
-@@ -436,6 +437,7 @@ static void memstick_check(struct work_struct *work)
- struct memstick_dev *card;
-
- dev_dbg(&host->dev, "memstick_check started\n");
-+ pm_runtime_get_noresume(host->dev.parent);
- mutex_lock(&host->lock);
- if (!host->card) {
- if (memstick_power_on(host))
-@@ -479,6 +481,7 @@ out_power_off:
- host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
-
- mutex_unlock(&host->lock);
-+ pm_runtime_put(host->dev.parent);
- dev_dbg(&host->dev, "memstick_check finished\n");
- }
-
-diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c
-index c344483fa7d6..9f257c53e6d4 100644
---- a/drivers/misc/vexpress-syscfg.c
-+++ b/drivers/misc/vexpress-syscfg.c
-@@ -61,7 +61,7 @@ static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func,
- int tries;
- long timeout;
-
-- if (WARN_ON(index > func->num_templates))
-+ if (WARN_ON(index >= func->num_templates))
- return -EINVAL;
-
- command = readl(syscfg->base + SYS_CFGCTRL);
-diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
-index 43fa16b5f510..672c02e32a39 100644
---- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
-+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
-@@ -168,9 +168,10 @@ int gpmi_init(struct gpmi_nand_data *this)
-
- /*
- * Reset BCH here, too. We got failures otherwise :(
-- * See later BCH reset for explanation of MX23 handling
-+ * See later BCH reset for explanation of MX23 and MX28 handling
- */
-- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
-+ ret = gpmi_reset_block(r->bch_regs,
-+ GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
- if (ret)
- goto err_out;
-
-@@ -274,13 +275,11 @@ int bch_set_geometry(struct gpmi_nand_data *this)
-
- /*
- * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
-- * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
-- * On the other hand, the MX28 needs the reset, because one case has been
-- * seen where the BCH produced ECC errors constantly after 10000
-- * consecutive reboots. The latter case has not been seen on the MX23
-- * yet, still we don't know if it could happen there as well.
-+ * chip, otherwise it will lock up. So we skip resetting BCH on the MX23
-+ * and MX28.
- */
-- ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
-+ ret = gpmi_reset_block(r->bch_regs,
-+ GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
- if (ret)
- goto err_out;
-
-diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
-index 7a6dd5e5e498..143b9a384af8 100644
---- a/drivers/net/ethernet/broadcom/bcmsysport.c
-+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
-@@ -400,7 +400,6 @@ static void bcm_sysport_get_wol(struct net_device *dev,
- struct ethtool_wolinfo *wol)
- {
- struct bcm_sysport_priv *priv = netdev_priv(dev);
-- u32 reg;
-
- wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
- wol->wolopts = priv->wolopts;
-@@ -408,11 +407,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
- if (!(priv->wolopts & WAKE_MAGICSECURE))
- return;
-
-- /* Return the programmed SecureOn password */
-- reg = umac_readl(priv, UMAC_PSW_MS);
-- put_unaligned_be16(reg, &wol->sopass[0]);
-- reg = umac_readl(priv, UMAC_PSW_LS);
-- put_unaligned_be32(reg, &wol->sopass[2]);
-+ memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
- }
-
- static int bcm_sysport_set_wol(struct net_device *dev,
-@@ -428,13 +423,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
- if (wol->wolopts & ~supported)
- return -EINVAL;
-
-- /* Program the SecureOn password */
-- if (wol->wolopts & WAKE_MAGICSECURE) {
-- umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
-- UMAC_PSW_MS);
-- umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
-- UMAC_PSW_LS);
-- }
-+ if (wol->wolopts & WAKE_MAGICSECURE)
-+ memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
-
- /* Flag the device and relevant IRQ as wakeup capable */
- if (wol->wolopts) {
-@@ -1889,12 +1879,17 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
- unsigned int timeout = 1000;
- u32 reg;
-
-- /* Password has already been programmed */
- reg = umac_readl(priv, UMAC_MPD_CTRL);
- reg |= MPD_EN;
- reg &= ~PSW_EN;
-- if (priv->wolopts & WAKE_MAGICSECURE)
-+ if (priv->wolopts & WAKE_MAGICSECURE) {
-+ /* Program the SecureOn password */
-+ umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
-+ UMAC_PSW_MS);
-+ umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
-+ UMAC_PSW_LS);
- reg |= PSW_EN;
-+ }
- umac_writel(priv, reg, UMAC_MPD_CTRL);
-
- /* Make sure RBUF entered WoL mode as result */
-diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
-index 8ace6ecb5f79..e668b1ce5828 100644
---- a/drivers/net/ethernet/broadcom/bcmsysport.h
-+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
-@@ -11,6 +11,7 @@
- #ifndef __BCM_SYSPORT_H
- #define __BCM_SYSPORT_H
-
-+#include
- #include
-
- /* Receive/transmit descriptor format */
-@@ -682,6 +683,7 @@ struct bcm_sysport_priv {
- unsigned int crc_fwd:1;
- u16 rev;
- u32 wolopts;
-+ u8 sopass[SOPASS_MAX];
- unsigned int wol_irq_disabled:1;
-
- /* MIB related fields */
-diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
-index 0433fdebda25..9ef4caa4b84d 100644
---- a/drivers/net/ethernet/cisco/enic/enic_main.c
-+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
-@@ -1180,7 +1180,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
- * CHECSUM_UNNECESSARY.
- */
- if ((netdev->features & NETIF_F_RXCSUM) && tcp_udp_csum_ok &&
-- ipv4_csum_ok)
-+ (ipv4_csum_ok || ipv6))
- skb->ip_summed = CHECKSUM_UNNECESSARY;
-
- if (vlan_stripped)
-diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
-index 02b23f6277fb..c1796aa2dde5 100644
---- a/drivers/net/ethernet/intel/igb/igb_main.c
-+++ b/drivers/net/ethernet/intel/igb/igb_main.c
-@@ -7339,9 +7339,11 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake,
- rtnl_unlock();
-
- #ifdef CONFIG_PM
-- retval = pci_save_state(pdev);
-- if (retval)
-- return retval;
-+ if (!runtime) {
-+ retval = pci_save_state(pdev);
-+ if (retval)
-+ return retval;
-+ }
- #endif
-
- status = rd32(E1000_STATUS);
-diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
-index 7173836fe361..c9f4b5412844 100644
---- a/drivers/net/ethernet/marvell/skge.c
-+++ b/drivers/net/ethernet/marvell/skge.c
-@@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
- memset(p, 0, regs->len);
- memcpy_fromio(p, io, B3_RAM_ADDR);
-
-- memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-- regs->len - B3_RI_WTO_R1);
-+ if (regs->len > B3_RI_WTO_R1) {
-+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-+ regs->len - B3_RI_WTO_R1);
-+ }
- }
-
- /* Wake on Lan only supported on Yukon chips with rev 1 or above */
-diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
-index ccebf89aa1e4..85f3a2c0d4dd 100644
---- a/drivers/net/ethernet/sun/niu.c
-+++ b/drivers/net/ethernet/sun/niu.c
-@@ -8121,6 +8121,8 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
- start += 3;
-
- prop_len = niu_pci_eeprom_read(np, start + 4);
-+ if (prop_len < 0)
-+ return prop_len;
- err = niu_pci_vpd_get_propname(np, start + 5, namebuf, 64);
- if (err < 0)
- return err;
-@@ -8165,8 +8167,12 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
- netif_printk(np, probe, KERN_DEBUG, np->dev,
- "VPD_SCAN: Reading in property [%s] len[%d]\n",
- namebuf, prop_len);
-- for (i = 0; i < prop_len; i++)
-- *prop_buf++ = niu_pci_eeprom_read(np, off + i);
-+ for (i = 0; i < prop_len; i++) {
-+ err = niu_pci_eeprom_read(np, off + i);
-+ if (err >= 0)
-+ *prop_buf = err;
-+ ++prop_buf;
-+ }
- }
-
- start += len;
-diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
-index dc934347ae28..e6f564d50663 100644
---- a/drivers/net/phy/dp83640.c
-+++ b/drivers/net/phy/dp83640.c
-@@ -890,14 +890,14 @@ static void decode_txts(struct dp83640_private *dp83640,
- struct phy_txts *phy_txts)
- {
- struct skb_shared_hwtstamps shhwtstamps;
-+ struct dp83640_skb_info *skb_info;
- struct sk_buff *skb;
-- u64 ns;
- u8 overflow;
-+ u64 ns;
-
- /* We must already have the skb that triggered this. */
--
-+again:
- skb = skb_dequeue(&dp83640->tx_queue);
--
- if (!skb) {
- pr_debug("have timestamp but tx_queue empty\n");
- return;
-@@ -912,6 +912,11 @@ static void decode_txts(struct dp83640_private *dp83640,
- }
- return;
- }
-+ skb_info = (struct dp83640_skb_info *)skb->cb;
-+ if (time_after(jiffies, skb_info->tmo)) {
-+ kfree_skb(skb);
-+ goto again;
-+ }
-
- ns = phy2txts(phy_txts);
- memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-@@ -1461,6 +1466,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
- static void dp83640_txtstamp(struct phy_device *phydev,
- struct sk_buff *skb, int type)
- {
-+ struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
- struct dp83640_private *dp83640 = phydev->priv;
-
- switch (dp83640->hwts_tx_en) {
-@@ -1473,6 +1479,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
- /* fall through */
- case HWTSTAMP_TX_ON:
- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
-+ skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
- skb_queue_tail(&dp83640->tx_queue, skb);
- break;
-
-diff --git a/drivers/net/usb/ch9200.c b/drivers/net/usb/ch9200.c
-index 5e151e6a3e09..3c7715ea40c1 100644
---- a/drivers/net/usb/ch9200.c
-+++ b/drivers/net/usb/ch9200.c
-@@ -255,14 +255,9 @@ static struct sk_buff *ch9200_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
- tx_overhead = 0x40;
-
- len = skb->len;
-- if (skb_headroom(skb) < tx_overhead) {
-- struct sk_buff *skb2;
--
-- skb2 = skb_copy_expand(skb, tx_overhead, 0, flags);
-+ if (skb_cow_head(skb, tx_overhead)) {
- dev_kfree_skb_any(skb);
-- skb = skb2;
-- if (!skb)
-- return NULL;
-+ return NULL;
- }
-
- __skb_push(skb, tx_overhead);
-diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
-index cd93220c9b45..a628db738b8a 100644
---- a/drivers/net/usb/kaweth.c
-+++ b/drivers/net/usb/kaweth.c
-@@ -812,18 +812,12 @@ static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb,
- }
-
- /* We now decide whether we can put our special header into the sk_buff */
-- if (skb_cloned(skb) || skb_headroom(skb) < 2) {
-- /* no such luck - we make our own */
-- struct sk_buff *copied_skb;
-- copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC);
-- dev_kfree_skb_irq(skb);
-- skb = copied_skb;
-- if (!copied_skb) {
-- kaweth->stats.tx_errors++;
-- netif_start_queue(net);
-- spin_unlock_irq(&kaweth->device_lock);
-- return NETDEV_TX_OK;
-- }
-+ if (skb_cow_head(skb, 2)) {
-+ kaweth->stats.tx_errors++;
-+ netif_start_queue(net);
-+ spin_unlock_irq(&kaweth->device_lock);
-+ dev_kfree_skb_any(skb);
-+ return NETDEV_TX_OK;
- }
-
- private_header = (__le16 *)__skb_push(skb, 2);
-diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
-index 7cee7777d13f..b6b8aec73b28 100644
---- a/drivers/net/usb/smsc95xx.c
-+++ b/drivers/net/usb/smsc95xx.c
-@@ -1838,13 +1838,13 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
- /* We do not advertise SG, so skbs should be already linearized */
- BUG_ON(skb_shinfo(skb)->nr_frags);
-
-- if (skb_headroom(skb) < overhead) {
-- struct sk_buff *skb2 = skb_copy_expand(skb,
-- overhead, 0, flags);
-+ /* Make writable and expand header space by overhead if required */
-+ if (skb_cow_head(skb, overhead)) {
-+ /* Must deallocate here as returning NULL to indicate error
-+ * means the skb won't be deallocated in the caller.
-+ */
- dev_kfree_skb_any(skb);
-- skb = skb2;
-- if (!skb)
-- return NULL;
-+ return NULL;
- }
-
- if (csum) {
-diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c
-index bff81b8d4164..9f1037e7e55c 100644
---- a/drivers/net/wireless/cw1200/scan.c
-+++ b/drivers/net/wireless/cw1200/scan.c
-@@ -78,6 +78,10 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
- if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
- return -EINVAL;
-
-+ /* will be unlocked in cw1200_scan_work() */
-+ down(&priv->scan.lock);
-+ mutex_lock(&priv->conf_mutex);
-+
- frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
- req->ie_len);
- if (!frame.skb)
-@@ -86,19 +90,15 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
- if (req->ie_len)
- memcpy(skb_put(frame.skb, req->ie_len), req->ie, req->ie_len);
-
-- /* will be unlocked in cw1200_scan_work() */
-- down(&priv->scan.lock);
-- mutex_lock(&priv->conf_mutex);
--
- ret = wsm_set_template_frame(priv, &frame);
- if (!ret) {
- /* Host want to be the probe responder. */
- ret = wsm_set_probe_responder(priv, true);
- }
- if (ret) {
-+ dev_kfree_skb(frame.skb);
- mutex_unlock(&priv->conf_mutex);
- up(&priv->scan.lock);
-- dev_kfree_skb(frame.skb);
- return ret;
- }
-
-@@ -120,10 +120,9 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
- ++priv->scan.n_ssids;
- }
-
-- mutex_unlock(&priv->conf_mutex);
--
- if (frame.skb)
- dev_kfree_skb(frame.skb);
-+ mutex_unlock(&priv->conf_mutex);
- queue_work(priv->workqueue, &priv->scan.work);
- return 0;
- }
-diff --git a/drivers/nfc/nxp-nci/firmware.c b/drivers/nfc/nxp-nci/firmware.c
-index 5291797324ba..553011f58339 100644
---- a/drivers/nfc/nxp-nci/firmware.c
-+++ b/drivers/nfc/nxp-nci/firmware.c
-@@ -24,7 +24,7 @@
- #include
- #include
- #include
--#include
-+#include
-
- #include "nxp-nci.h"
-
-diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
-index df4333c7ee0f..0b1122cb5d0c 100644
---- a/drivers/nfc/nxp-nci/i2c.c
-+++ b/drivers/nfc/nxp-nci/i2c.c
-@@ -36,7 +36,7 @@
- #include
- #include
- #include
--#include