Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2017-10-20 13:20:25 +0200
committerJiri Kosina <jkosina@suse.cz>2017-10-20 13:20:25 +0200
commit480195331e2d75bd2482b353c18df1e946b0c723 (patch)
tree62d4b5bf126f1045a03bf430737354fa1bc6f416
parente741c37acc2a24135302f17aa6eb3f090b6c1fc1 (diff)
parentcd2246aefbef1eecc3defd37e31a2f5477e456e8 (diff)
Merge remote-tracking branch 'origin/users/lurodriguez/SLE15/for-next' into SLE15
-rw-r--r--blacklist.conf1
-rw-r--r--config/arm64/default3
-rw-r--r--config/ppc64le/debug6
-rw-r--r--config/ppc64le/default4
-rw-r--r--config/s390x/default4
-rw-r--r--config/s390x/zfcpdump1
-rw-r--r--config/x86_64/debug6
-rw-r--r--config/x86_64/default3
-rw-r--r--patches.drivers/0002-tools-testing-selftests-sysctl-Add-pre-check-to-the-.patch90
-rw-r--r--patches.drivers/0003-test_sysctl-add-dedicated-proc-sysctl-test-driver.patch237
-rw-r--r--patches.drivers/0004-test_firmware-add-test-case-for-SIGCHLD-on-sync-fall.patch72
-rw-r--r--patches.drivers/0004-test_sysctl-add-generic-script-to-expand-on-tests.patch812
-rw-r--r--patches.drivers/0005-test_firmware-add-batched-firmware-tests.patch1082
-rw-r--r--patches.drivers/0005-test_sysctl-test-against-PAGE_SIZE-for-int.patch149
-rw-r--r--patches.drivers/0006-test_sysctl-add-simple-proc_dointvec-case.patch170
-rw-r--r--patches.drivers/0007-test_sysctl-add-simple-proc_douintvec-case.patch173
-rw-r--r--patches.drivers/0008-test_sysctl-test-against-int-proc_dointvec-array-sup.patch204
-rw-r--r--patches.drivers/0009-test_sysctl-fix-sysctl.sh-by-making-it-executable.patch32
-rw-r--r--patches.suse/0001-firmware-send-EINTR-on-signal-abort-on-fallback-mech.patch46
-rw-r--r--patches.suse/0001-sysctl-add-unsigned-int-range-support.patch165
-rw-r--r--patches.suse/0002-firmware-define-pr_fmt.patch34
-rw-r--r--patches.suse/0003-firmware-enable-a-debug-print-for-batched-requests.patch40
-rw-r--r--rpm/package-descriptions21
-rw-r--r--series.conf22
-rw-r--r--supported.conf3
25 files changed, 3370 insertions, 10 deletions
diff --git a/blacklist.conf b/blacklist.conf
index 79609aede4..484c32facb 100644
--- a/blacklist.conf
+++ b/blacklist.conf
@@ -85,3 +85,4 @@ deecd4d71b12626db48544faa66bb897e2cafd07 # we do not set CONFIG_MATOM=y
630cc2b30a42c70628368a412beb4a5e5dd71abe # doc update
74dcb29a38e4419a8e4217caa7e35ccc1b31e5a4 # doc update
075d8a75daedec14f2337c2881186aabd8fa4fda # changes logging in an undesirable way
+768dc4e48420955518974d8486c1b00ec05e7274 # CONFIG_TEST_KMOD=n right now
diff --git a/config/arm64/default b/config/arm64/default
index 8c89a85b94..5a7d683d6b 100644
--- a/config/arm64/default
+++ b/config/arm64/default
@@ -7100,7 +7100,8 @@ CONFIG_LKDTM=m
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_USER_COPY is not set
# CONFIG_TEST_BPF is not set
-# CONFIG_TEST_FIRMWARE is not set
+CONFIG_TEST_FIRMWARE=m
+CONFIG_TEST_SYSCTL=m
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
# CONFIG_TEST_STATIC_KEYS is not set
diff --git a/config/ppc64le/debug b/config/ppc64le/debug
index 77696f64cd..95e71a2648 100644
--- a/config/ppc64le/debug
+++ b/config/ppc64le/debug
@@ -39,6 +39,7 @@ CONFIG_MAC80211_PS_DEBUG=y
CONFIG_MAC80211_STA_DEBUG=y
CONFIG_MAC80211_TDLS_DEBUG=y
CONFIG_MAC80211_VERBOSE_DEBUG=y
+# CONFIG_MODULE_SIG is not set
CONFIG_PCIEASPM_DEBUG=y
# CONFIG_PPC_ICSWX is not set
CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
@@ -52,10 +53,11 @@ CONFIG_REISERFS_PROC_INFO=y
CONFIG_RT2X00_DEBUG=y
CONFIG_RT2X00_LIB_DEBUGFS=y
CONFIG_SCSI_LPFC_DEBUG_FS=y
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_TCM_QLA2XXX_DEBUG=y
CONFIG_TTY_PRINTK=y
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_MODULES=y
-# CONFIG_MODULE_SIG is not set
-# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_SUSE_KERNEL_SUPPORTED=y
+CONFIG_TEST_SYSCTL=m
+CONFIG_TEST_FIRMWARE=m
diff --git a/config/ppc64le/default b/config/ppc64le/default
index 519a0eba21..4bc935bcad 100644
--- a/config/ppc64le/default
+++ b/config/ppc64le/default
@@ -5011,7 +5011,8 @@ CONFIG_LKDTM=m
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_USER_COPY is not set
# CONFIG_TEST_BPF is not set
-# CONFIG_TEST_FIRMWARE is not set
+CONFIG_TEST_FIRMWARE=m
+CONFIG_TEST_SYSCTL=m
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
# CONFIG_TEST_STATIC_KEYS is not set
@@ -5297,7 +5298,6 @@ CONFIG_SYSTEM_TRUSTED_KEYS=""
# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
-# CONFIG_EFI_SIGNATURE_LIST_PARSER is not set
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQFD=y
CONFIG_HAVE_KVM_EVENTFD=y
diff --git a/config/s390x/default b/config/s390x/default
index 1df6d09318..e51dc5c94f 100644
--- a/config/s390x/default
+++ b/config/s390x/default
@@ -2722,7 +2722,8 @@ CONFIG_LKDTM=m
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_USER_COPY is not set
# CONFIG_TEST_BPF is not set
-# CONFIG_TEST_FIRMWARE is not set
+CONFIG_TEST_FIRMWARE=m
+CONFIG_TEST_SYSCTL=m
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
# CONFIG_TEST_STATIC_KEYS is not set
@@ -2983,7 +2984,6 @@ CONFIG_SYSTEM_TRUSTED_KEYS=""
# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
-# CONFIG_EFI_SIGNATURE_LIST_PARSER is not set
CONFIG_BINARY_PRINTF=y
#
diff --git a/config/s390x/zfcpdump b/config/s390x/zfcpdump
index 2a9cfe060f..2411316bfa 100644
--- a/config/s390x/zfcpdump
+++ b/config/s390x/zfcpdump
@@ -1119,6 +1119,7 @@ CONFIG_TRACING_SUPPORT=y
# CONFIG_TEST_HASH is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_SYSCTL is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
# CONFIG_BUG_ON_DATA_CORRUPTION is not set
diff --git a/config/x86_64/debug b/config/x86_64/debug
index 733b4b847d..7fb7df2dbd 100644
--- a/config/x86_64/debug
+++ b/config/x86_64/debug
@@ -50,6 +50,7 @@ CONFIG_MAC80211_TDLS_DEBUG=y
CONFIG_MAC80211_VERBOSE_DEBUG=y
CONFIG_MEMSTICK_DEBUG=y
CONFIG_MMC_DEBUG=y
+# CONFIG_MODULE_SIG is not set
CONFIG_OCFS2_DEBUG_FS=y
# CONFIG_PARAVIRT_SPINLOCKS is not set
CONFIG_PCIEASPM_DEBUG=y
@@ -69,6 +70,7 @@ CONFIG_RT2X00_LIB_DEBUGFS=y
CONFIG_RTC_DRV_TEST=m
CONFIG_SND_DEBUG_VERBOSE=y
CONFIG_SSB_DEBUG=y
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_TCM_QLA2XXX_DEBUG=y
CONFIG_THINKPAD_ACPI_DEBUG=y
CONFIG_THINKPAD_ACPI_DEBUGFACILITIES=y
@@ -78,7 +80,7 @@ CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_USB_STORAGE_DEBUG=y
CONFIG_XFS_DEBUG=y
CONFIG_MODULES=y
-# CONFIG_MODULE_SIG is not set
-# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_SUSE_KERNEL_SUPPORTED=y
CONFIG_EFI_STUB=y
+CONFIG_TEST_SYSCTL=m
+CONFIG_TEST_FIRMWARE=m
diff --git a/config/x86_64/default b/config/x86_64/default
index 4c17431dbc..ea4d1b8db9 100644
--- a/config/x86_64/default
+++ b/config/x86_64/default
@@ -6830,7 +6830,8 @@ CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_USER_COPY is not set
# CONFIG_TEST_BPF is not set
-# CONFIG_TEST_FIRMWARE is not set
+CONFIG_TEST_FIRMWARE=m
+CONFIG_TEST_SYSCTL=m
# CONFIG_TEST_UDELAY is not set
CONFIG_MEMTEST=y
# CONFIG_TEST_STATIC_KEYS is not set
diff --git a/patches.drivers/0002-tools-testing-selftests-sysctl-Add-pre-check-to-the-.patch b/patches.drivers/0002-tools-testing-selftests-sysctl-Add-pre-check-to-the-.patch
new file mode 100644
index 0000000000..9910dc5636
--- /dev/null
+++ b/patches.drivers/0002-tools-testing-selftests-sysctl-Add-pre-check-to-the-.patch
@@ -0,0 +1,90 @@
+From 49ebb4c814fce03acf4eaa028300a88396cd0520 Mon Sep 17 00:00:00 2001
+From: Orson Zhai <orson.zhai@linaro.org>
+Date: Tue, 27 Jun 2017 08:52:09 +0800
+Subject: [PATCH 2/9] tools/testing/selftests/sysctl: Add pre-check to the
+ value of writes_strict
+Git-commit: d644437a1dc6226afb7b8a814657961d8812f763
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Sysctl test will fail in some items if the value of /proc/sys/kernel
+/sysctrl_writes_strict is 0 as the default value in kernel older than v4.5.
+
+Make this test more robus and compatible with older kernel by checking and
+update writes_strict value and restore it when test is done.
+
+Signed-off-by: Orson Zhai <orson.zhai@linaro.org>
+Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org>
+Tested-by: Sumit Semwal <sumit.semwal@linaro.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ tools/testing/selftests/sysctl/common_tests | 22 ++++++++++++++++++++++
+ tools/testing/selftests/sysctl/run_numerictests | 2 +-
+ tools/testing/selftests/sysctl/run_stringtests | 2 +-
+ 3 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/sysctl/common_tests b/tools/testing/selftests/sysctl/common_tests
+index 17d534b1b7b4..b6862322962f 100644
+--- a/tools/testing/selftests/sysctl/common_tests
++++ b/tools/testing/selftests/sysctl/common_tests
+@@ -24,6 +24,14 @@ verify()
+ return 0
+ }
+
++exit_test()
++{
++ if [ ! -z ${old_strict} ]; then
++ echo ${old_strict} > ${WRITES_STRICT}
++ fi
++ exit $rc
++}
++
+ trap 'set_orig; rm -f "${TEST_FILE}"' EXIT
+
+ rc=0
+@@ -63,6 +71,20 @@ else
+ echo "ok"
+ fi
+
++echo -n "Checking write strict setting ... "
++WRITES_STRICT="${SYSCTL}/kernel/sysctl_writes_strict"
++if [ ! -e ${WRITES_STRICT} ]; then
++ echo "FAIL, but skip in case of old kernel" >&2
++else
++ old_strict=$(cat ${WRITES_STRICT})
++ if [ "$old_strict" = "1" ]; then
++ echo "ok"
++ else
++ echo "FAIL, strict value is 0 but force to 1 to continue" >&2
++ echo "1" > ${WRITES_STRICT}
++ fi
++fi
++
+ # Now that we've validated the sanity of "set_test" and "set_orig",
+ # we can use those functions to set starting states before running
+ # specific behavioral tests.
+diff --git a/tools/testing/selftests/sysctl/run_numerictests b/tools/testing/selftests/sysctl/run_numerictests
+index 8510f93f2d14..e6e76c93d948 100755
+--- a/tools/testing/selftests/sysctl/run_numerictests
++++ b/tools/testing/selftests/sysctl/run_numerictests
+@@ -7,4 +7,4 @@ TEST_STR=$(( $ORIG + 1 ))
+
+ . ./common_tests
+
+-exit $rc
++exit_test
+diff --git a/tools/testing/selftests/sysctl/run_stringtests b/tools/testing/selftests/sysctl/run_stringtests
+index 90a9293d520c..857ec667fb02 100755
+--- a/tools/testing/selftests/sysctl/run_stringtests
++++ b/tools/testing/selftests/sysctl/run_stringtests
+@@ -74,4 +74,4 @@ else
+ echo "ok"
+ fi
+
+-exit $rc
++exit_test
+--
+2.14.0
+
diff --git a/patches.drivers/0003-test_sysctl-add-dedicated-proc-sysctl-test-driver.patch b/patches.drivers/0003-test_sysctl-add-dedicated-proc-sysctl-test-driver.patch
new file mode 100644
index 0000000000..b80c15aa56
--- /dev/null
+++ b/patches.drivers/0003-test_sysctl-add-dedicated-proc-sysctl-test-driver.patch
@@ -0,0 +1,237 @@
+From 6ef91edc343d132ddba8c8f4c79376e0038e64c0 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:43 -0700
+Subject: [PATCH 3/9] test_sysctl: add dedicated proc sysctl test driver
+Git-commit: 9308f2f9e7f055cf3934645ec622bb5259dc1c14
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+The existing tools/testing/selftests/sysctl/ tests include two test
+cases, but these use existing production kernel sysctl interfaces. We
+want to expand test coverage but we can't just be looking for random
+safe production values to poke at, that's just insane!
+
+Instead just dedicate a test driver for debugging purposes and port the
+existing scripts to use it. This will make it easier for further tests
+to be added.
+
+Subsequent patches will extend our test coverage for sysctl.
+
+The stress test driver uses a new license (GPL on Linux, copyleft-next
+outside of Linux). Linus was fine with this [0] and later due to Ted's
+and Alans's request ironed out an "or" language clause to use [1] which
+is already present upstream.
+
+[0] https://lkml.kernel.org/r/CA+55aFyhxcvD+q7tp+-yrSFDKfR0mOHgyEAe=f_94aKLsOu0Og@mail.gmail.com
+[1] https://lkml.kernel.org/r/1495234558.7848.122.camel@linux.intel.com
+
+Link: http://lkml.kernel.org/r/20170630224431.17374-2-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Acked-by: Kees Cook <keescook@chromium.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ lib/Kconfig.debug | 11 +++
+ lib/Makefile | 1 +
+ lib/test_sysctl.c | 113 ++++++++++++++++++++++++
+ tools/testing/selftests/sysctl/config | 1 +
+ tools/testing/selftests/sysctl/run_numerictests | 4 +-
+ tools/testing/selftests/sysctl/run_stringtests | 4 +-
+ 6 files changed, 130 insertions(+), 4 deletions(-)
+ create mode 100644 lib/test_sysctl.c
+ create mode 100644 tools/testing/selftests/sysctl/config
+
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index af215305901d..6404061234d5 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -1989,6 +1989,17 @@ config TEST_FIRMWARE
+
+ If unsure, say N.
+
++config TEST_SYSCTL
++ tristate "sysctl test driver"
++ default n
++ depends on PROC_SYSCTL
++ help
++ This builds the "test_sysctl" module. This driver enables to test the
++ proc sysctl interfaces available to drivers safely without affecting
++ production knobs which might alter system functionality.
++
++ If unsure, say N.
++
+ config TEST_UDELAY
+ tristate "udelay test driver"
+ default n
+diff --git a/lib/Makefile b/lib/Makefile
+index 0166fbc0fa81..1b72172d6ab7 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -49,6 +49,7 @@ obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
+ obj-y += kstrtox.o
+ obj-$(CONFIG_TEST_BPF) += test_bpf.o
+ obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
++obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
+ obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
+ obj-$(CONFIG_TEST_KASAN) += test_kasan.o
+ obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
+diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c
+new file mode 100644
+index 000000000000..b2163bfb6eb2
+--- /dev/null
++++ b/lib/test_sysctl.c
+@@ -0,0 +1,113 @@
++/*
++ * proc sysctl test driver
++ *
++ * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or at your option any
++ * later version; or, when distributed separately from the Linux kernel or
++ * when incorporated into other software packages, subject to the following
++ * license:
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of copyleft-next (version 0.3.1 or later) as published
++ * at http://copyleft-next.org/.
++ */
++
++/*
++ * This module provides an interface to the the proc sysctl interfaces. This
++ * driver requires CONFIG_PROC_SYSCTL. It will not normally be loaded by the
++ * system unless explicitly requested by name. You can also build this driver
++ * into your kernel.
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/printk.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++#include <linux/async.h>
++#include <linux/delay.h>
++#include <linux/vmalloc.h>
++
++static int i_zero;
++static int i_one_hundred = 100;
++
++struct test_sysctl_data {
++ int int_0001;
++ char string_0001[65];
++};
++
++static struct test_sysctl_data test_data = {
++ .int_0001 = 60,
++ .string_0001 = "(none)",
++};
++
++/* These are all under /proc/sys/debug/test_sysctl/ */
++static struct ctl_table test_table[] = {
++ {
++ .procname = "int_0001",
++ .data = &test_data.int_0001,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = &i_zero,
++ .extra2 = &i_one_hundred,
++ },
++ {
++ .procname = "string_0001",
++ .data = &test_data.string_0001,
++ .maxlen = sizeof(test_data.string_0001),
++ .mode = 0644,
++ .proc_handler = proc_dostring,
++ },
++ { }
++};
++
++static struct ctl_table test_sysctl_table[] = {
++ {
++ .procname = "test_sysctl",
++ .maxlen = 0,
++ .mode = 0555,
++ .child = test_table,
++ },
++ { }
++};
++
++static struct ctl_table test_sysctl_root_table[] = {
++ {
++ .procname = "debug",
++ .maxlen = 0,
++ .mode = 0555,
++ .child = test_sysctl_table,
++ },
++ { }
++};
++
++static struct ctl_table_header *test_sysctl_header;
++
++static int __init test_sysctl_init(void)
++{
++ test_sysctl_header = register_sysctl_table(test_sysctl_root_table);
++ if (!test_sysctl_header)
++ return -ENOMEM;
++ return 0;
++}
++late_initcall(test_sysctl_init);
++
++static void __exit test_sysctl_exit(void)
++{
++ if (test_sysctl_header)
++ unregister_sysctl_table(test_sysctl_header);
++}
++
++module_exit(test_sysctl_exit);
++
++MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
++MODULE_LICENSE("GPL");
+diff --git a/tools/testing/selftests/sysctl/config b/tools/testing/selftests/sysctl/config
+new file mode 100644
+index 000000000000..6ca14800d755
+--- /dev/null
++++ b/tools/testing/selftests/sysctl/config
+@@ -0,0 +1 @@
++CONFIG_TEST_SYSCTL=y
+diff --git a/tools/testing/selftests/sysctl/run_numerictests b/tools/testing/selftests/sysctl/run_numerictests
+index e6e76c93d948..c375ce0f4c15 100755
+--- a/tools/testing/selftests/sysctl/run_numerictests
++++ b/tools/testing/selftests/sysctl/run_numerictests
+@@ -1,7 +1,7 @@
+ #!/bin/sh
+
+-SYSCTL="/proc/sys"
+-TARGET="${SYSCTL}/vm/swappiness"
++SYSCTL="/proc/sys/debug/test_sysctl/"
++TARGET="${SYSCTL}/int_0001"
+ ORIG=$(cat "${TARGET}")
+ TEST_STR=$(( $ORIG + 1 ))
+
+diff --git a/tools/testing/selftests/sysctl/run_stringtests b/tools/testing/selftests/sysctl/run_stringtests
+index 857ec667fb02..a6f2618afeaa 100755
+--- a/tools/testing/selftests/sysctl/run_stringtests
++++ b/tools/testing/selftests/sysctl/run_stringtests
+@@ -1,7 +1,7 @@
+ #!/bin/sh
+
+-SYSCTL="/proc/sys"
+-TARGET="${SYSCTL}/kernel/domainname"
++SYSCTL="/proc/sys/debug/test_sysctl/"
++TARGET="${SYSCTL}/string_0001"
+ ORIG=$(cat "${TARGET}")
+ TEST_STR="Testing sysctl"
+
+--
+2.14.0
+
diff --git a/patches.drivers/0004-test_firmware-add-test-case-for-SIGCHLD-on-sync-fall.patch b/patches.drivers/0004-test_firmware-add-test-case-for-SIGCHLD-on-sync-fall.patch
new file mode 100644
index 0000000000..c9d5cd05c6
--- /dev/null
+++ b/patches.drivers/0004-test_firmware-add-test-case-for-SIGCHLD-on-sync-fall.patch
@@ -0,0 +1,72 @@
+From c3128afd23e83219d61424ec2d77df3a09a104eb Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Thu, 20 Jul 2017 13:13:38 -0700
+Subject: [PATCH 4/5] test_firmware: add test case for SIGCHLD on sync fallback
+Git-commit: 0d1f417eee8ad0687afb90eab282614eecce1a13
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+It has been reported that SIGCHLD will trigger an immediate abort
+on sync firmware requests which rely on the sysfs interface for a
+trigger. This is unexpected behaviour, this reproduces this issue.
+
+This test case currenty fails.
+
+Reported-by: Martin Fuzzey <mfuzzey@parkeon.com>
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ tools/testing/selftests/firmware/fw_fallback.sh | 31 +++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/tools/testing/selftests/firmware/fw_fallback.sh b/tools/testing/selftests/firmware/fw_fallback.sh
+index 2e4c22d5abf7..8f511035f783 100755
+--- a/tools/testing/selftests/firmware/fw_fallback.sh
++++ b/tools/testing/selftests/firmware/fw_fallback.sh
+@@ -134,6 +134,27 @@ load_fw_custom_cancel()
+ wait
+ }
+
++load_fw_fallback_with_child()
++{
++ local name="$1"
++ local file="$2"
++
++ # This is the value already set but we want to be explicit
++ echo 4 >/sys/class/firmware/timeout
++
++ sleep 1 &
++ SECONDS_BEFORE=$(date +%s)
++ echo -n "$name" >"$DIR"/trigger_request 2>/dev/null
++ SECONDS_AFTER=$(date +%s)
++ SECONDS_DELTA=$(($SECONDS_AFTER - $SECONDS_BEFORE))
++ if [ "$SECONDS_DELTA" -lt 4 ]; then
++ RET=1
++ else
++ RET=0
++ fi
++ wait
++ return $RET
++}
+
+ trap "test_finish" EXIT
+
+@@ -221,4 +242,14 @@ else
+ echo "$0: cancelling custom fallback mechanism works"
+ fi
+
++set +e
++load_fw_fallback_with_child "nope-signal-$NAME" "$FW"
++if [ "$?" -eq 0 ]; then
++ echo "$0: SIGCHLD on sync ignored as expected" >&2
++else
++ echo "$0: error - sync firmware request cancelled due to SIGCHLD" >&2
++ exit 1
++fi
++set -e
++
+ exit 0
+--
+2.14.0
+
diff --git a/patches.drivers/0004-test_sysctl-add-generic-script-to-expand-on-tests.patch b/patches.drivers/0004-test_sysctl-add-generic-script-to-expand-on-tests.patch
new file mode 100644
index 0000000000..7ecbf8eb53
--- /dev/null
+++ b/patches.drivers/0004-test_sysctl-add-generic-script-to-expand-on-tests.patch
@@ -0,0 +1,812 @@
+From d5ed6a97993d28e9c386ebd215099ac538d1c537 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:46 -0700
+Subject: [PATCH 4/9] test_sysctl: add generic script to expand on tests
+Git-commit: 64b671204afd71591e774e7237b7c862ac5bbd97
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+This adds a generic script to let us more easily add more tests cases.
+Since we really have only two types of tests cases just fold them into
+the one file. Each test unit is now identified into its separate
+function:
+
+ # ./sysctl.sh -l
+ Test ID list:
+
+ TEST_ID x NUM_TEST
+ TEST_ID: Test ID
+ NUM_TESTS: Number of recommended times to run the test
+
+ 0001 x 1 - tests proc_dointvec_minmax()
+ 0002 x 1 - tests proc_dostring()
+
+For now we start off with what we had before, and run only each test
+once. We can now watch a test case until it fails:
+
+ ./sysctl.sh -w 0002
+
+We can also run a test case x number of times, say we want to run a test
+case 100 times:
+
+ ./sysctl.sh -c 0001 100
+
+To run a test case only once, for example:
+
+ ./sysctl.sh -s 0002
+
+The default settings are specified at the top of sysctl.sh.
+
+Link: http://lkml.kernel.org/r/20170630224431.17374-3-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ tools/testing/selftests/sysctl/Makefile | 3 +-
+ tools/testing/selftests/sysctl/common_tests | 131 -------
+ tools/testing/selftests/sysctl/run_numerictests | 10 -
+ tools/testing/selftests/sysctl/run_stringtests | 77 ----
+ tools/testing/selftests/sysctl/sysctl.sh | 494 ++++++++++++++++++++++++
+ 5 files changed, 495 insertions(+), 220 deletions(-)
+ delete mode 100644 tools/testing/selftests/sysctl/common_tests
+ delete mode 100755 tools/testing/selftests/sysctl/run_numerictests
+ delete mode 100755 tools/testing/selftests/sysctl/run_stringtests
+ create mode 100644 tools/testing/selftests/sysctl/sysctl.sh
+
+diff --git a/tools/testing/selftests/sysctl/Makefile b/tools/testing/selftests/sysctl/Makefile
+index b3c33e071f10..95c320b354e8 100644
+--- a/tools/testing/selftests/sysctl/Makefile
++++ b/tools/testing/selftests/sysctl/Makefile
+@@ -4,8 +4,7 @@
+ # No binaries, but make sure arg-less "make" doesn't trigger "run_tests".
+ all:
+
+-TEST_PROGS := run_numerictests run_stringtests
+-TEST_FILES := common_tests
++TEST_PROGS := sysctl.sh
+
+ include ../lib.mk
+
+diff --git a/tools/testing/selftests/sysctl/common_tests b/tools/testing/selftests/sysctl/common_tests
+deleted file mode 100644
+index b6862322962f..000000000000
+--- a/tools/testing/selftests/sysctl/common_tests
++++ /dev/null
+@@ -1,131 +0,0 @@
+-#!/bin/sh
+-
+-TEST_FILE=$(mktemp)
+-
+-echo "== Testing sysctl behavior against ${TARGET} =="
+-
+-set_orig()
+-{
+- echo "${ORIG}" > "${TARGET}"
+-}
+-
+-set_test()
+-{
+- echo "${TEST_STR}" > "${TARGET}"
+-}
+-
+-verify()
+-{
+- local seen
+- seen=$(cat "$1")
+- if [ "${seen}" != "${TEST_STR}" ]; then
+- return 1
+- fi
+- return 0
+-}
+-
+-exit_test()
+-{
+- if [ ! -z ${old_strict} ]; then
+- echo ${old_strict} > ${WRITES_STRICT}
+- fi
+- exit $rc
+-}
+-
+-trap 'set_orig; rm -f "${TEST_FILE}"' EXIT
+-
+-rc=0
+-
+-echo -n "Writing test file ... "
+-echo "${TEST_STR}" > "${TEST_FILE}"
+-if ! verify "${TEST_FILE}"; then
+- echo "FAIL" >&2
+- exit 1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Checking sysctl is not set to test value ... "
+-if verify "${TARGET}"; then
+- echo "FAIL" >&2
+- exit 1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Writing sysctl from shell ... "
+-set_test
+-if ! verify "${TARGET}"; then
+- echo "FAIL" >&2
+- exit 1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Resetting sysctl to original value ... "
+-set_orig
+-if verify "${TARGET}"; then
+- echo "FAIL" >&2
+- exit 1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Checking write strict setting ... "
+-WRITES_STRICT="${SYSCTL}/kernel/sysctl_writes_strict"
+-if [ ! -e ${WRITES_STRICT} ]; then
+- echo "FAIL, but skip in case of old kernel" >&2
+-else
+- old_strict=$(cat ${WRITES_STRICT})
+- if [ "$old_strict" = "1" ]; then
+- echo "ok"
+- else
+- echo "FAIL, strict value is 0 but force to 1 to continue" >&2
+- echo "1" > ${WRITES_STRICT}
+- fi
+-fi
+-
+-# Now that we've validated the sanity of "set_test" and "set_orig",
+-# we can use those functions to set starting states before running
+-# specific behavioral tests.
+-
+-echo -n "Writing entire sysctl in single write ... "
+-set_orig
+-dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null
+-if ! verify "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Writing middle of sysctl after synchronized seek ... "
+-set_test
+-dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null
+-if ! verify "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Writing beyond end of sysctl ... "
+-set_orig
+-dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null
+-if verify "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Writing sysctl with multiple long writes ... "
+-set_orig
+-(perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \
+- dd of="${TARGET}" bs=50 2>/dev/null
+-if verify "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+diff --git a/tools/testing/selftests/sysctl/run_numerictests b/tools/testing/selftests/sysctl/run_numerictests
+deleted file mode 100755
+index c375ce0f4c15..000000000000
+--- a/tools/testing/selftests/sysctl/run_numerictests
++++ /dev/null
+@@ -1,10 +0,0 @@
+-#!/bin/sh
+-
+-SYSCTL="/proc/sys/debug/test_sysctl/"
+-TARGET="${SYSCTL}/int_0001"
+-ORIG=$(cat "${TARGET}")
+-TEST_STR=$(( $ORIG + 1 ))
+-
+-. ./common_tests
+-
+-exit_test
+diff --git a/tools/testing/selftests/sysctl/run_stringtests b/tools/testing/selftests/sysctl/run_stringtests
+deleted file mode 100755
+index a6f2618afeaa..000000000000
+--- a/tools/testing/selftests/sysctl/run_stringtests
++++ /dev/null
+@@ -1,77 +0,0 @@
+-#!/bin/sh
+-
+-SYSCTL="/proc/sys/debug/test_sysctl/"
+-TARGET="${SYSCTL}/string_0001"
+-ORIG=$(cat "${TARGET}")
+-TEST_STR="Testing sysctl"
+-
+-. ./common_tests
+-
+-# Only string sysctls support seeking/appending.
+-MAXLEN=65
+-
+-echo -n "Writing entire sysctl in short writes ... "
+-set_orig
+-dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null
+-if ! verify "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Writing middle of sysctl after unsynchronized seek ... "
+-set_test
+-dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null
+-if verify "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Checking sysctl maxlen is at least $MAXLEN ... "
+-set_orig
+-perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \
+- dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
+-if ! grep -q B "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Checking sysctl keeps original string on overflow append ... "
+-set_orig
+-perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
+- dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null
+-if grep -q B "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Checking sysctl stays NULL terminated on write ... "
+-set_orig
+-perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
+- dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
+-if grep -q B "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-echo -n "Checking sysctl stays NULL terminated on overwrite ... "
+-set_orig
+-perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \
+- dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null
+-if grep -q B "${TARGET}"; then
+- echo "FAIL" >&2
+- rc=1
+-else
+- echo "ok"
+-fi
+-
+-exit_test
+diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
+new file mode 100644
+index 000000000000..cbe1345d7c1d
+--- /dev/null
++++ b/tools/testing/selftests/sysctl/sysctl.sh
+@@ -0,0 +1,494 @@
++#!/bin/bash
++# Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
++#
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the Free
++# Software Foundation; either version 2 of the License, or at your option any
++# later version; or, when distributed separately from the Linux kernel or
++# when incorporated into other software packages, subject to the following
++# license:
++#
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of copyleft-next (version 0.3.1 or later) as published
++# at http://copyleft-next.org/.
++
++# This performs a series tests against the proc sysctl interface.
++
++TEST_NAME="sysctl"
++TEST_DRIVER="test_${TEST_NAME}"
++TEST_DIR=$(dirname $0)
++TEST_FILE=$(mktemp)
++
++# This represents
++#
++# TEST_ID:TEST_COUNT:ENABLED
++#
++# TEST_ID: is the test id number
++# TEST_COUNT: number of times we should run the test
++# ENABLED: 1 if enabled, 0 otherwise
++#
++# Once these are enabled please leave them as-is. Write your own test,
++# we have tons of space.
++ALL_TESTS="0001:1:1"
++ALL_TESTS="$ALL_TESTS 0002:1:1"
++
++test_modprobe()
++{
++ if [ ! -d $DIR ]; then
++ echo "$0: $DIR not present" >&2
++ echo "You must have the following enabled in your kernel:" >&2
++ cat $TEST_DIR/config >&2
++ exit 1
++ fi
++}
++
++function allow_user_defaults()
++{
++ if [ -z $DIR ]; then
++ DIR="/sys/module/test_sysctl/"
++ fi
++ if [ -z $DEFAULT_NUM_TESTS ]; then
++ DEFAULT_NUM_TESTS=50
++ fi
++ if [ -z $SYSCTL ]; then
++ SYSCTL="/proc/sys/debug/test_sysctl"
++ fi
++ if [ -z $PROD_SYSCTL ]; then
++ PROD_SYSCTL="/proc/sys"
++ fi
++ if [ -z $WRITES_STRICT ]; then
++ WRITES_STRICT="${PROD_SYSCTL}/kernel/sysctl_writes_strict"
++ fi
++}
++
++function check_production_sysctl_writes_strict()
++{
++ echo -n "Checking production write strict setting ... "
++ if [ ! -e ${WRITES_STRICT} ]; then
++ echo "FAIL, but skip in case of old kernel" >&2
++ else
++ old_strict=$(cat ${WRITES_STRICT})
++ if [ "$old_strict" = "1" ]; then
++ echo "ok"
++ else
++ echo "FAIL, strict value is 0 but force to 1 to continue" >&2
++ echo "1" > ${WRITES_STRICT}
++ fi
++ fi
++}
++
++test_reqs()
++{
++ uid=$(id -u)
++ if [ $uid -ne 0 ]; then
++ echo $msg must be run as root >&2
++ exit 0
++ fi
++
++ if ! which perl 2> /dev/null > /dev/null; then
++ echo "$0: You need perl installed"
++ exit 1
++ fi
++}
++
++function load_req_mod()
++{
++ trap "test_modprobe" EXIT
++
++ if [ ! -d $DIR ]; then
++ modprobe $TEST_DRIVER
++ if [ $? -ne 0 ]; then
++ exit
++ fi
++ fi
++}
++
++set_orig()
++{
++ if [ ! -z $TARGET ]; then
++ echo "${ORIG}" > "${TARGET}"
++ fi
++}
++
++set_test()
++{
++ echo "${TEST_STR}" > "${TARGET}"
++}
++
++verify()
++{
++ local seen
++ seen=$(cat "$1")
++ if [ "${seen}" != "${TEST_STR}" ]; then
++ return 1
++ fi
++ return 0
++}
++
++test_rc()
++{
++ if [[ $rc != 0 ]]; then
++ echo "Failed test, return value: $rc" >&2
++ exit $rc
++ fi
++}
++
++test_finish()
++{
++ set_orig
++ rm -f "${TEST_FILE}"
++
++ if [ ! -z ${old_strict} ]; then
++ echo ${old_strict} > ${WRITES_STRICT}
++ fi
++ exit $rc
++}
++
++run_numerictests()
++{
++ echo "== Testing sysctl behavior against ${TARGET} =="
++
++ rc=0
++
++ echo -n "Writing test file ... "
++ echo "${TEST_STR}" > "${TEST_FILE}"
++ if ! verify "${TEST_FILE}"; then
++ echo "FAIL" >&2
++ exit 1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Checking sysctl is not set to test value ... "
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ exit 1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Writing sysctl from shell ... "
++ set_test
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ exit 1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Resetting sysctl to original value ... "
++ set_orig
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ exit 1
++ else
++ echo "ok"
++ fi
++
++ # Now that we've validated the sanity of "set_test" and "set_orig",
++ # we can use those functions to set starting states before running
++ # specific behavioral tests.
++
++ echo -n "Writing entire sysctl in single write ... "
++ set_orig
++ dd if="${TEST_FILE}" of="${TARGET}" bs=4096 2>/dev/null
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Writing middle of sysctl after synchronized seek ... "
++ set_test
++ dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 skip=1 2>/dev/null
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Writing beyond end of sysctl ... "
++ set_orig
++ dd if="${TEST_FILE}" of="${TARGET}" bs=20 seek=2 2>/dev/null
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Writing sysctl with multiple long writes ... "
++ set_orig
++ (perl -e 'print "A" x 50;'; echo "${TEST_STR}") | \
++ dd of="${TARGET}" bs=50 2>/dev/null
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ test_rc
++}
++
++run_stringtests()
++{
++ echo -n "Writing entire sysctl in short writes ... "
++ set_orig
++ dd if="${TEST_FILE}" of="${TARGET}" bs=1 2>/dev/null
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Writing middle of sysctl after unsynchronized seek ... "
++ set_test
++ dd if="${TEST_FILE}" of="${TARGET}" bs=1 seek=1 2>/dev/null
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Checking sysctl maxlen is at least $MAXLEN ... "
++ set_orig
++ perl -e 'print "A" x ('"${MAXLEN}"'-2), "B";' | \
++ dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
++ if ! grep -q B "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Checking sysctl keeps original string on overflow append ... "
++ set_orig
++ perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
++ dd of="${TARGET}" bs=$(( MAXLEN - 1 )) 2>/dev/null
++ if grep -q B "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Checking sysctl stays NULL terminated on write ... "
++ set_orig
++ perl -e 'print "A" x ('"${MAXLEN}"'-1), "B";' | \
++ dd of="${TARGET}" bs="${MAXLEN}" 2>/dev/null
++ if grep -q B "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ echo -n "Checking sysctl stays NULL terminated on overwrite ... "
++ set_orig
++ perl -e 'print "A" x ('"${MAXLEN}"'-1), "BB";' | \
++ dd of="${TARGET}" bs=$(( $MAXLEN + 1 )) 2>/dev/null
++ if grep -q B "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++
++ test_rc
++}
++
++sysctl_test_0001()
++{
++ TARGET="${SYSCTL}/int_0001"
++ ORIG=$(cat "${TARGET}")
++ TEST_STR=$(( $ORIG + 1 ))
++
++ run_numerictests
++}
++
++sysctl_test_0002()
++{
++ TARGET="${SYSCTL}/string_0001"
++ ORIG=$(cat "${TARGET}")
++ TEST_STR="Testing sysctl"
++ # Only string sysctls support seeking/appending.
++ MAXLEN=65
++
++ run_numerictests
++ run_stringtests
++}
++
++list_tests()
++{
++ echo "Test ID list:"
++ echo
++ echo "TEST_ID x NUM_TEST"
++ echo "TEST_ID: Test ID"
++ echo "NUM_TESTS: Number of recommended times to run the test"
++ echo
++ echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
++ echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
++}
++
++test_reqs
++
++usage()
++{
++ NUM_TESTS=$(grep -o ' ' <<<"$ALL_TESTS" | grep -c .)
++ let NUM_TESTS=$NUM_TESTS+1
++ MAX_TEST=$(printf "%04d\n" $NUM_TESTS)
++ echo "Usage: $0 [ -t <4-number-digit> ] | [ -w <4-number-digit> ] |"
++ echo " [ -s <4-number-digit> ] | [ -c <4-number-digit> <test- count>"
++ echo " [ all ] [ -h | --help ] [ -l ]"
++ echo ""
++ echo "Valid tests: 0001-$MAX_TEST"
++ echo ""
++ echo " all Runs all tests (default)"
++ echo " -t Run test ID the number amount of times is recommended"
++ echo " -w Watch test ID run until it runs into an error"
++ echo " -c Run test ID once"
++ echo " -s Run test ID x test-count number of times"
++ echo " -l List all test ID list"
++ echo " -h|--help Help"
++ echo
++ echo "If an error every occurs execution will immediately terminate."
++ echo "If you are adding a new test try using -w <test-ID> first to"
++ echo "make sure the test passes a series of tests."
++ echo
++ echo Example uses:
++ echo
++ echo "$TEST_NAME.sh -- executes all tests"
++ echo "$TEST_NAME.sh -t 0002 -- Executes test ID 0002 number of times is recomended"
++ echo "$TEST_NAME.sh -w 0002 -- Watch test ID 0002 run until an error occurs"
++ echo "$TEST_NAME.sh -s 0002 -- Run test ID 0002 once"
++ echo "$TEST_NAME.sh -c 0002 3 -- Run test ID 0002 three times"
++ echo
++ list_tests
++ exit 1
++}
++
++function test_num()
++{
++ re='^[0-9]+$'
++ if ! [[ $1 =~ $re ]]; then
++ usage
++ fi
++}
++
++function get_test_count()
++{
++ test_num $1
++ TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
++ LAST_TWO=${TEST_DATA#*:*}
++ echo ${LAST_TWO%:*}
++}
++
++function get_test_enabled()
++{
++ test_num $1
++ TEST_DATA=$(echo $ALL_TESTS | awk '{print $'$1'}')
++ echo ${TEST_DATA#*:*:}
++}
++
++function run_all_tests()
++{
++ for i in $ALL_TESTS ; do
++ TEST_ID=${i%:*:*}
++ ENABLED=$(get_test_enabled $TEST_ID)
++ TEST_COUNT=$(get_test_count $TEST_ID)
++ if [[ $ENABLED -eq "1" ]]; then
++ test_case $TEST_ID $TEST_COUNT
++ fi
++ done
++}
++
++function watch_log()
++{
++ if [ $# -ne 3 ]; then
++ clear
++ fi
++ date
++ echo "Running test: $2 - run #$1"
++}
++
++function watch_case()
++{
++ i=0
++ while [ 1 ]; do
++
++ if [ $# -eq 1 ]; then
++ test_num $1
++ watch_log $i ${TEST_NAME}_test_$1
++ ${TEST_NAME}_test_$1
++ else
++ watch_log $i all
++ run_all_tests
++ fi
++ let i=$i+1
++ done
++}
++
++function test_case()
++{
++ NUM_TESTS=$DEFAULT_NUM_TESTS
++ if [ $# -eq 2 ]; then
++ NUM_TESTS=$2
++ fi
++
++ i=0
++ while [ $i -lt $NUM_TESTS ]; do
++ test_num $1
++ watch_log $i ${TEST_NAME}_test_$1 noclear
++ RUN_TEST=${TEST_NAME}_test_$1
++ $RUN_TEST
++ let i=$i+1
++ done
++}
++
++function parse_args()
++{
++ if [ $# -eq 0 ]; then
++ run_all_tests
++ else
++ if [[ "$1" = "all" ]]; then
++ run_all_tests
++ elif [[ "$1" = "-w" ]]; then
++ shift
++ watch_case $@
++ elif [[ "$1" = "-t" ]]; then
++ shift
++ test_num $1
++ test_case $1 $(get_test_count $1)
++ elif [[ "$1" = "-c" ]]; then
++ shift
++ test_num $1
++ test_num $2
++ test_case $1 $2
++ elif [[ "$1" = "-s" ]]; then
++ shift
++ test_case $1 1
++ elif [[ "$1" = "-l" ]]; then
++ list_tests
++ elif [[ "$1" = "-h" || "$1" = "--help" ]]; then
++ usage
++ else
++ usage
++ fi
++ fi
++}
++
++test_reqs
++allow_user_defaults
++check_production_sysctl_writes_strict
++load_req_mod
++
++trap "test_finish" EXIT
++
++parse_args $@
++
++exit 0
+--
+2.14.0
+
diff --git a/patches.drivers/0005-test_firmware-add-batched-firmware-tests.patch b/patches.drivers/0005-test_firmware-add-batched-firmware-tests.patch
new file mode 100644
index 0000000000..457227e86c
--- /dev/null
+++ b/patches.drivers/0005-test_firmware-add-batched-firmware-tests.patch
@@ -0,0 +1,1082 @@
+From b84daa9c4ff59b14a03099fe36ec014806f82b68 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Thu, 20 Jul 2017 13:13:42 -0700
+Subject: [PATCH 5/5] test_firmware: add batched firmware tests
+Git-commit: c92316bf8e94830a0225f2e904cbdbd173768419
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+The firmware API has a feature to enable batching requests for the same fil
+e under one worker, so only one lookup is done. This only triggers if we so
+happen to schedule two lookups for same file around the same time, or if
+release_firmware() has not been called for a successful firmware call. This
+can happen for instance if you happen to have multiple devices and one
+device driver for certain drivers where the stars line up scheduling
+wise.
+
+This adds a new sync and async test trigger. Instead of adding a new
+trigger for each new test type we make the tests a bit configurable so that
+we could configure the tests in userspace and just kick a test through a
+few basic triggers. With this, for instance the two types of sync requests:
+
+ o request_firmware() and
+ o request_firmware_direct()
+
+can be modified with a knob. Likewise the two type of async requests:
+
+ o request_firmware_nowait(uevent=true) and
+ o request_firmware_nowait(uevent=false)
+
+can be configured with another knob. The call request_firmware_into_buf()
+has no users... yet.
+
+The old tests are left in place as-is given they serve a few other purposes
+which we are currently not interested in also testing yet. This will change
+later as we will be able to just consolidate all tests under a few basic
+triggers with just one general configuration setup.
+
+We perform two types of tests, one for where the file is present and one
+for where the file is not present. All test tests go tested and they now
+pass for the following 3 kernel builds possible for the firmware API:
+
+0. Most distro setup:
+ CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n
+ CONFIG_FW_LOADER_USER_HELPER=y
+1. Android:
+ CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+ CONFIG_FW_LOADER_USER_HELPER=y
+2. Rare build:
+ CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n
+ CONFIG_FW_LOADER_USER_HELPER=n
+
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ lib/test_firmware.c | 710 ++++++++++++++++++++++
+ tools/testing/selftests/firmware/fw_filesystem.sh | 241 +++++++-
+ 2 files changed, 949 insertions(+), 2 deletions(-)
+
+diff --git a/lib/test_firmware.c b/lib/test_firmware.c
+index 09371b0a9baf..64a4c76cba2b 100644
+--- a/lib/test_firmware.c
++++ b/lib/test_firmware.c
+@@ -19,10 +19,85 @@
+ #include <linux/miscdevice.h>
+ #include <linux/slab.h>
+ #include <linux/uaccess.h>
++#include <linux/delay.h>
++#include <linux/kthread.h>
++
++#define TEST_FIRMWARE_NAME "test-firmware.bin"
++#define TEST_FIRMWARE_NUM_REQS 4
+
+ static DEFINE_MUTEX(test_fw_mutex);
+ static const struct firmware *test_firmware;
+
++struct test_batched_req {
++ u8 idx;
++ int rc;
++ bool sent;
++ const struct firmware *fw;
++ const char *name;
++ struct completion completion;
++ struct task_struct *task;
++ struct device *dev;
++};
++
++/**
++ * test_config - represents configuration for the test for different triggers
++ *
++ * @name: the name of the firmware file to look for
++ * @sync_direct: when the sync trigger is used if this is true
++ * request_firmware_direct() will be used instead.
++ * @send_uevent: whether or not to send a uevent for async requests
++ * @num_requests: number of requests to try per test case. This is trigger
++ * specific.
++ * @reqs: stores all requests information
++ * @read_fw_idx: index of thread from which we want to read firmware results
++ * from through the read_fw trigger.
++ * @test_result: a test may use this to collect the result from the call
++ * of the request_firmware*() calls used in their tests. In order of
++ * priority we always keep first any setup error. If no setup errors were
++ * found then we move on to the first error encountered while running the
++ * API. Note that for async calls this typically will be a successful
++ * result (0) unless of course you've used bogus parameters, or the system
++ * is out of memory. In the async case the callback is expected to do a
++ * bit more homework to figure out what happened, unfortunately the only
++ * information passed today on error is the fact that no firmware was
++ * found so we can only assume -ENOENT on async calls if the firmware is
++ * NULL.
++ *
++ * Errors you can expect:
++ *
++ * API specific:
++ *
++ * 0: success for sync, for async it means request was sent
++ * -EINVAL: invalid parameters or request
++ * -ENOENT: files not found
++ *
++ * System environment:
++ *
++ * -ENOMEM: memory pressure on system
++ * -ENODEV: out of number of devices to test
++ * -EINVAL: an unexpected error has occurred
++ * @req_firmware: if @sync_direct is true this is set to
++ * request_firmware_direct(), otherwise request_firmware()
++ */
++struct test_config {
++ char *name;
++ bool sync_direct;
++ bool send_uevent;
++ u8 num_requests;
++ u8 read_fw_idx;
++
++ /*
++ * These below don't belong her but we'll move them once we create
++ * a struct fw_test_device and stuff the misc_dev under there later.
++ */
++ struct test_batched_req *reqs;
++ int test_result;
++ int (*req_firmware)(const struct firmware **fw, const char *name,
++ struct device *device);
++};
++
++struct test_config *test_fw_config;
++
+ static ssize_t test_fw_misc_read(struct file *f, char __user *buf,
+ size_t size, loff_t *offset)
+ {
+@@ -42,6 +117,338 @@ static const struct file_operations test_fw_fops = {
+ .read = test_fw_misc_read,
+ };
+
++static void __test_release_all_firmware(void)
++{
++ struct test_batched_req *req;
++ u8 i;
++
++ if (!test_fw_config->reqs)
++ return;
++
++ for (i = 0; i < test_fw_config->num_requests; i++) {
++ req = &test_fw_config->reqs[i];
++ if (req->fw)
++ release_firmware(req->fw);
++ }
++
++ vfree(test_fw_config->reqs);
++ test_fw_config->reqs = NULL;
++}
++
++static void test_release_all_firmware(void)
++{
++ mutex_lock(&test_fw_mutex);
++ __test_release_all_firmware();
++ mutex_unlock(&test_fw_mutex);
++}
++
++
++static void __test_firmware_config_free(void)
++{
++ __test_release_all_firmware();
++ kfree_const(test_fw_config->name);
++ test_fw_config->name = NULL;
++}
++
++/*
++ * XXX: move to kstrncpy() once merged.
++ *
++ * Users should use kfree_const() when freeing these.
++ */
++static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp)
++{
++ *dst = kstrndup(name, count, gfp);
++ if (!*dst)
++ return -ENOSPC;
++ return count;
++}
++
++static int __test_firmware_config_init(void)
++{
++ int ret;
++
++ ret = __kstrncpy(&test_fw_config->name, TEST_FIRMWARE_NAME,
++ strlen(TEST_FIRMWARE_NAME), GFP_KERNEL);
++ if (ret < 0)
++ goto out;
++
++ test_fw_config->num_requests = TEST_FIRMWARE_NUM_REQS;
++ test_fw_config->send_uevent = true;
++ test_fw_config->sync_direct = false;
++ test_fw_config->req_firmware = request_firmware;
++ test_fw_config->test_result = 0;
++ test_fw_config->reqs = NULL;
++
++ return 0;
++
++out:
++ __test_firmware_config_free();
++ return ret;
++}
++
++static ssize_t reset_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int ret;
++
++ mutex_lock(&test_fw_mutex);
++
++ __test_firmware_config_free();
++
++ ret = __test_firmware_config_init();
++ if (ret < 0) {
++ ret = -ENOMEM;
++ pr_err("could not alloc settings for config trigger: %d\n",
++ ret);
++ goto out;
++ }
++
++ pr_info("reset\n");
++ ret = count;
++
++out:
++ mutex_unlock(&test_fw_mutex);
++
++ return ret;
++}
++static DEVICE_ATTR_WO(reset);
++
++static ssize_t config_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ int len = 0;
++
++ mutex_lock(&test_fw_mutex);
++
++ len += snprintf(buf, PAGE_SIZE,
++ "Custom trigger configuration for: %s\n",
++ dev_name(dev));
++
++ if (test_fw_config->name)
++ len += snprintf(buf+len, PAGE_SIZE,
++ "name:\t%s\n",
++ test_fw_config->name);
++ else
++ len += snprintf(buf+len, PAGE_SIZE,
++ "name:\tEMTPY\n");
++
++ len += snprintf(buf+len, PAGE_SIZE,
++ "num_requests:\t%u\n", test_fw_config->num_requests);
++
++ len += snprintf(buf+len, PAGE_SIZE,
++ "send_uevent:\t\t%s\n",
++ test_fw_config->send_uevent ?
++ "FW_ACTION_HOTPLUG" :
++ "FW_ACTION_NOHOTPLUG");
++ len += snprintf(buf+len, PAGE_SIZE,
++ "sync_direct:\t\t%s\n",
++ test_fw_config->sync_direct ? "true" : "false");
++ len += snprintf(buf+len, PAGE_SIZE,
++ "read_fw_idx:\t%u\n", test_fw_config->read_fw_idx);
++
++ mutex_unlock(&test_fw_mutex);
++
++ return len;
++}
++static DEVICE_ATTR_RO(config);
++
++static ssize_t config_name_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int ret;
++
++ mutex_lock(&test_fw_mutex);
++ kfree_const(test_fw_config->name);
++ ret = __kstrncpy(&test_fw_config->name, buf, count, GFP_KERNEL);
++ mutex_unlock(&test_fw_mutex);
++
++ return ret;
++}
++
++/*
++ * As per sysfs_kf_seq_show() the buf is max PAGE_SIZE.
++ */
++static ssize_t config_test_show_str(char *dst,
++ char *src)
++{
++ int len;
++
++ mutex_lock(&test_fw_mutex);
++ len = snprintf(dst, PAGE_SIZE, "%s\n", src);
++ mutex_unlock(&test_fw_mutex);
++
++ return len;
++}
++
++static int test_dev_config_update_bool(const char *buf, size_t size,
++ bool *cfg)
++{
++ int ret;
++
++ mutex_lock(&test_fw_mutex);
++ if (strtobool(buf, cfg) < 0)
++ ret = -EINVAL;
++ else
++ ret = size;
++ mutex_unlock(&test_fw_mutex);
++
++ return ret;
++}
++
++static ssize_t
++test_dev_config_show_bool(char *buf,
++ bool config)
++{
++ bool val;
++
++ mutex_lock(&test_fw_mutex);
++ val = config;
++ mutex_unlock(&test_fw_mutex);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", val);
++}
++
++static ssize_t test_dev_config_show_int(char *buf, int cfg)
++{
++ int val;
++
++ mutex_lock(&test_fw_mutex);
++ val = cfg;
++ mutex_unlock(&test_fw_mutex);
++
++ return snprintf(buf, PAGE_SIZE, "%d\n", val);
++}
++
++static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
++{
++ int ret;
++ long new;
++
++ ret = kstrtol(buf, 10, &new);
++ if (ret)
++ return ret;
++
++ if (new > U8_MAX)
++ return -EINVAL;
++
++ mutex_lock(&test_fw_mutex);
++ *(u8 *)cfg = new;
++ mutex_unlock(&test_fw_mutex);
++
++ /* Always return full write size even if we didn't consume all */
++ return size;
++}
++
++static ssize_t test_dev_config_show_u8(char *buf, u8 cfg)
++{
++ u8 val;
++
++ mutex_lock(&test_fw_mutex);
++ val = cfg;
++ mutex_unlock(&test_fw_mutex);
++
++ return snprintf(buf, PAGE_SIZE, "%u\n", val);
++}
++
++static ssize_t config_name_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return config_test_show_str(buf, test_fw_config->name);
++}
++static DEVICE_ATTR(config_name, 0644, config_name_show, config_name_store);
++
++static ssize_t config_num_requests_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int rc;
++
++ mutex_lock(&test_fw_mutex);
++ if (test_fw_config->reqs) {
++ pr_err("Must call release_all_firmware prior to changing config\n");
++ rc = -EINVAL;
++ goto out;
++ }
++ mutex_unlock(&test_fw_mutex);
++
++ rc = test_dev_config_update_u8(buf, count,
++ &test_fw_config->num_requests);
++
++out:
++ return rc;
++}
++
++static ssize_t config_num_requests_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return test_dev_config_show_u8(buf, test_fw_config->num_requests);
++}
++static DEVICE_ATTR(config_num_requests, 0644, config_num_requests_show,
++ config_num_requests_store);
++
++static ssize_t config_sync_direct_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int rc = test_dev_config_update_bool(buf, count,
++ &test_fw_config->sync_direct);
++
++ if (rc == count)
++ test_fw_config->req_firmware = test_fw_config->sync_direct ?
++ request_firmware_direct :
++ request_firmware;
++ return rc;
++}
++
++static ssize_t config_sync_direct_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return test_dev_config_show_bool(buf, test_fw_config->sync_direct);
++}
++static DEVICE_ATTR(config_sync_direct, 0644, config_sync_direct_show,
++ config_sync_direct_store);
++
++static ssize_t config_send_uevent_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ return test_dev_config_update_bool(buf, count,
++ &test_fw_config->send_uevent);
++}
++
++static ssize_t config_send_uevent_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return test_dev_config_show_bool(buf, test_fw_config->send_uevent);
++}
++static DEVICE_ATTR(config_send_uevent, 0644, config_send_uevent_show,
++ config_send_uevent_store);
++
++static ssize_t config_read_fw_idx_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ return test_dev_config_update_u8(buf, count,
++ &test_fw_config->read_fw_idx);
++}
++
++static ssize_t config_read_fw_idx_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return test_dev_config_show_u8(buf, test_fw_config->read_fw_idx);
++}
++static DEVICE_ATTR(config_read_fw_idx, 0644, config_read_fw_idx_show,
++ config_read_fw_idx_store);
++
++
+ static ssize_t trigger_request_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -170,12 +577,301 @@ static ssize_t trigger_custom_fallback_store(struct device *dev,
+ }
+ static DEVICE_ATTR_WO(trigger_custom_fallback);
+
++static int test_fw_run_batch_request(void *data)
++{
++ struct test_batched_req *req = data;
++
++ if (!req) {
++ test_fw_config->test_result = -EINVAL;
++ return -EINVAL;
++ }
++
++ req->rc = test_fw_config->req_firmware(&req->fw, req->name, req->dev);
++ if (req->rc) {
++ pr_info("#%u: batched sync load failed: %d\n",
++ req->idx, req->rc);
++ if (!test_fw_config->test_result)
++ test_fw_config->test_result = req->rc;
++ } else if (req->fw) {
++ req->sent = true;
++ pr_info("#%u: batched sync loaded %zu\n",
++ req->idx, req->fw->size);
++ }
++ complete(&req->completion);
++
++ req->task = NULL;
++
++ return 0;
++}
++
++/*
++ * We use a kthread as otherwise the kernel serializes all our sync requests
++ * and we would not be able to mimic batched requests on a sync call. Batched
++ * requests on a sync call can for instance happen on a device driver when
++ * multiple cards are used and firmware loading happens outside of probe.
++ */
++static ssize_t trigger_batched_requests_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct test_batched_req *req;
++ int rc;
++ u8 i;
++
++ mutex_lock(&test_fw_mutex);
++
++ test_fw_config->reqs = vzalloc(sizeof(struct test_batched_req) *
++ test_fw_config->num_requests * 2);
++ if (!test_fw_config->reqs) {
++ rc = -ENOMEM;
++ goto out_unlock;
++ }
++
++ pr_info("batched sync firmware loading '%s' %u times\n",
++ test_fw_config->name, test_fw_config->num_requests);
++
++ for (i = 0; i < test_fw_config->num_requests; i++) {
++ req = &test_fw_config->reqs[i];
++ if (!req) {
++ WARN_ON(1);
++ rc = -ENOMEM;
++ goto out_bail;
++ }
++ req->fw = NULL;
++ req->idx = i;
++ req->name = test_fw_config->name;
++ req->dev = dev;
++ init_completion(&req->completion);
++ req->task = kthread_run(test_fw_run_batch_request, req,
++ "%s-%u", KBUILD_MODNAME, req->idx);
++ if (!req->task || IS_ERR(req->task)) {
++ pr_err("Setting up thread %u failed\n", req->idx);
++ req->task = NULL;
++ rc = -ENOMEM;
++ goto out_bail;
++ }
++ }
++
++ rc = count;
++
++ /*
++ * We require an explicit release to enable more time and delay of
++ * calling release_firmware() to improve our chances of forcing a
++ * batched request. If we instead called release_firmware() right away
++ * then we might miss on an opportunity of having a successful firmware
++ * request pass on the opportunity to be come a batched request.
++ */
++
++out_bail:
++ for (i = 0; i < test_fw_config->num_requests; i++) {
++ req = &test_fw_config->reqs[i];
++ if (req->task || req->sent)
++ wait_for_completion(&req->completion);
++ }
++
++ /* Override any worker error if we had a general setup error */
++ if (rc < 0)
++ test_fw_config->test_result = rc;
++
++out_unlock:
++ mutex_unlock(&test_fw_mutex);
++
++ return rc;
++}
++static DEVICE_ATTR_WO(trigger_batched_requests);
++
++/*
++ * We wait for each callback to return with the lock held, no need to lock here
++ */
++static void trigger_batched_cb(const struct firmware *fw, void *context)
++{
++ struct test_batched_req *req = context;
++
++ if (!req) {
++ test_fw_config->test_result = -EINVAL;
++ return;
++ }
++
++ /* forces *some* batched requests to queue up */
++ if (!req->idx)
++ ssleep(2);
++
++ req->fw = fw;
++
++ /*
++ * Unfortunately the firmware API gives us nothing other than a null FW
++ * if the firmware was not found on async requests. Best we can do is
++ * just assume -ENOENT. A better API would pass the actual return
++ * value to the callback.
++ */
++ if (!fw && !test_fw_config->test_result)
++ test_fw_config->test_result = -ENOENT;
++
++ complete(&req->completion);
++}
++
++static
++ssize_t trigger_batched_requests_async_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct test_batched_req *req;
++ bool send_uevent;
++ int rc;
++ u8 i;
++
++ mutex_lock(&test_fw_mutex);
++
++ test_fw_config->reqs = vzalloc(sizeof(struct test_batched_req) *
++ test_fw_config->num_requests * 2);
++ if (!test_fw_config->reqs) {
++ rc = -ENOMEM;
++ goto out;
++ }
++
++ pr_info("batched loading '%s' custom fallback mechanism %u times\n",
++ test_fw_config->name, test_fw_config->num_requests);
++
++ send_uevent = test_fw_config->send_uevent ? FW_ACTION_HOTPLUG :
++ FW_ACTION_NOHOTPLUG;
++
++ for (i = 0; i < test_fw_config->num_requests; i++) {
++ req = &test_fw_config->reqs[i];
++ if (!req) {
++ WARN_ON(1);
++ goto out_bail;
++ }
++ req->name = test_fw_config->name;
++ req->fw = NULL;
++ req->idx = i;
++ init_completion(&req->completion);
++ rc = request_firmware_nowait(THIS_MODULE, send_uevent,
++ req->name,
++ dev, GFP_KERNEL, req,
++ trigger_batched_cb);
++ if (rc) {
++ pr_info("#%u: batched async load failed setup: %d\n",
++ i, rc);
++ req->rc = rc;
++ goto out_bail;
++ } else
++ req->sent = true;
++ }
++
++ rc = count;
++
++out_bail:
++
++ /*
++ * We require an explicit release to enable more time and delay of
++ * calling release_firmware() to improve our chances of forcing a
++ * batched request. If we instead called release_firmware() right away
++ * then we might miss on an opportunity of having a successful firmware
++ * request pass on the opportunity to be come a batched request.
++ */
++
++ for (i = 0; i < test_fw_config->num_requests; i++) {
++ req = &test_fw_config->reqs[i];
++ if (req->sent)
++ wait_for_completion(&req->completion);
++ }
++
++ /* Override any worker error if we had a general setup error */
++ if (rc < 0)
++ test_fw_config->test_result = rc;
++
++out:
++ mutex_unlock(&test_fw_mutex);
++
++ return rc;
++}
++static DEVICE_ATTR_WO(trigger_batched_requests_async);
++
++static ssize_t test_result_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ return test_dev_config_show_int(buf, test_fw_config->test_result);
++}
++static DEVICE_ATTR_RO(test_result);
++
++static ssize_t release_all_firmware_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ test_release_all_firmware();
++ return count;
++}
++static DEVICE_ATTR_WO(release_all_firmware);
++
++static ssize_t read_firmware_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct test_batched_req *req;
++ u8 idx;
++ ssize_t rc = 0;
++
++ mutex_lock(&test_fw_mutex);
++
++ idx = test_fw_config->read_fw_idx;
++ if (idx >= test_fw_config->num_requests) {
++ rc = -ERANGE;
++ goto out;
++ }
++
++ if (!test_fw_config->reqs) {
++ rc = -EINVAL;
++ goto out;
++ }
++
++ req = &test_fw_config->reqs[idx];
++ if (!req->fw) {
++ pr_err("#%u: failed to async load firmware\n", idx);
++ rc = -ENOENT;
++ goto out;
++ }
++
++ pr_info("#%u: loaded %zu\n", idx, req->fw->size);
++
++ if (req->fw->size > PAGE_SIZE) {
++ pr_err("Testing interface must use PAGE_SIZE firmware for now\n");
++ rc = -EINVAL;
++ }
++ memcpy(buf, req->fw->data, req->fw->size);
++
++ rc = req->fw->size;
++out:
++ mutex_unlock(&test_fw_mutex);
++
++ return rc;
++}
++static DEVICE_ATTR_RO(read_firmware);
++
+ #define TEST_FW_DEV_ATTR(name) &dev_attr_##name.attr
+
+ static struct attribute *test_dev_attrs[] = {
++ TEST_FW_DEV_ATTR(reset),
++
++ TEST_FW_DEV_ATTR(config),
++ TEST_FW_DEV_ATTR(config_name),
++ TEST_FW_DEV_ATTR(config_num_requests),
++ TEST_FW_DEV_ATTR(config_sync_direct),
++ TEST_FW_DEV_ATTR(config_send_uevent),
++ TEST_FW_DEV_ATTR(config_read_fw_idx),
++
++ /* These don't use the config at all - they could be ported! */
+ TEST_FW_DEV_ATTR(trigger_request),
+ TEST_FW_DEV_ATTR(trigger_async_request),
+ TEST_FW_DEV_ATTR(trigger_custom_fallback),
++
++ /* These use the config and can use the test_result */
++ TEST_FW_DEV_ATTR(trigger_batched_requests),
++ TEST_FW_DEV_ATTR(trigger_batched_requests_async),
++
++ TEST_FW_DEV_ATTR(release_all_firmware),
++ TEST_FW_DEV_ATTR(test_result),
++ TEST_FW_DEV_ATTR(read_firmware),
+ NULL,
+ };
+
+@@ -192,8 +888,17 @@ static int __init test_firmware_init(void)
+ {
+ int rc;
+
++ test_fw_config = kzalloc(sizeof(struct test_config), GFP_KERNEL);
++ if (!test_fw_config)
++ return -ENOMEM;
++
++ rc = __test_firmware_config_init();
++ if (rc)
++ return rc;
++
+ rc = misc_register(&test_fw_misc_device);
+ if (rc) {
++ kfree(test_fw_config);
+ pr_err("could not register misc device: %d\n", rc);
+ return rc;
+ }
+@@ -207,8 +912,13 @@ module_init(test_firmware_init);
+
+ static void __exit test_firmware_exit(void)
+ {
++ mutex_lock(&test_fw_mutex);
+ release_firmware(test_firmware);
+ misc_deregister(&test_fw_misc_device);
++ __test_firmware_config_free();
++ kfree(test_fw_config);
++ mutex_unlock(&test_fw_mutex);
++
+ pr_warn("removed interface\n");
+ }
+
+diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
+index e35691239350..7d8fd2e3695a 100755
+--- a/tools/testing/selftests/firmware/fw_filesystem.sh
++++ b/tools/testing/selftests/firmware/fw_filesystem.sh
+@@ -25,8 +25,9 @@ if [ ! -d $DIR ]; then
+ fi
+
+ # CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
+-# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
+-# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
++# These days most distros enable CONFIG_FW_LOADER_USER_HELPER but disable
++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK. We use /sys/class/firmware/ as an
++# indicator for CONFIG_FW_LOADER_USER_HELPER.
+ HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
+
+ if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+@@ -116,4 +117,240 @@ else
+ echo "$0: async filesystem loading works"
+ fi
+
++### Batched requests tests
++test_config_present()
++{
++ if [ ! -f $DIR/reset ]; then
++ echo "Configuration triggers not present, ignoring test"
++ exit 0
++ fi
++}
++
++# Defaults :
++#
++# send_uevent: 1
++# sync_direct: 0
++# name: test-firmware.bin
++# num_requests: 4
++config_reset()
++{
++ echo 1 > $DIR/reset
++}
++
++release_all_firmware()
++{
++ echo 1 > $DIR/release_all_firmware
++}
++
++config_set_name()
++{
++ echo -n $1 > $DIR/config_name
++}
++
++config_set_sync_direct()
++{
++ echo 1 > $DIR/config_sync_direct
++}
++
++config_unset_sync_direct()
++{
++ echo 0 > $DIR/config_sync_direct
++}
++
++config_set_uevent()
++{
++ echo 1 > $DIR/config_send_uevent
++}
++
++config_unset_uevent()
++{
++ echo 0 > $DIR/config_send_uevent
++}
++
++config_trigger_sync()
++{
++ echo -n 1 > $DIR/trigger_batched_requests 2>/dev/null
++}
++
++config_trigger_async()
++{
++ echo -n 1 > $DIR/trigger_batched_requests_async 2> /dev/null
++}
++
++config_set_read_fw_idx()
++{
++ echo -n $1 > $DIR/config_read_fw_idx 2> /dev/null
++}
++
++read_firmwares()
++{
++ for i in $(seq 0 3); do
++ config_set_read_fw_idx $i
++ # Verify the contents are what we expect.
++ # -Z required for now -- check for yourself, md5sum
++ # on $FW and DIR/read_firmware will yield the same. Even
++ # cmp agrees, so something is off.
++ if ! diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
++ echo "request #$i: firmware was not loaded" >&2
++ exit 1
++ fi
++ done
++}
++
++read_firmwares_expect_nofile()
++{
++ for i in $(seq 0 3); do
++ config_set_read_fw_idx $i
++ # Ensures contents differ
++ if diff -q -Z "$FW" $DIR/read_firmware 2>/dev/null ; then
++ echo "request $i: file was not expected to match" >&2
++ exit 1
++ fi
++ done
++}
++
++test_batched_request_firmware_nofile()
++{
++ echo -n "Batched request_firmware() nofile try #$1: "
++ config_reset
++ config_set_name nope-test-firmware.bin
++ config_trigger_sync
++ read_firmwares_expect_nofile
++ release_all_firmware
++ echo "OK"
++}
++
++test_batched_request_firmware_direct_nofile()
++{
++ echo -n "Batched request_firmware_direct() nofile try #$1: "
++ config_reset
++ config_set_name nope-test-firmware.bin
++ config_set_sync_direct
++ config_trigger_sync
++ release_all_firmware
++ echo "OK"
++}
++
++test_request_firmware_nowait_uevent_nofile()
++{
++ echo -n "Batched request_firmware_nowait(uevent=true) nofile try #$1: "
++ config_reset
++ config_set_name nope-test-firmware.bin
++ config_trigger_async
++ release_all_firmware
++ echo "OK"
++}
++
++test_wait_and_cancel_custom_load()
++{
++ if [ "$HAS_FW_LOADER_USER_HELPER" != "yes" ]; then
++ return
++ fi
++ local timeout=10
++ name=$1
++ while [ ! -e "$DIR"/"$name"/loading ]; do
++ sleep 0.1
++ timeout=$(( $timeout - 1 ))
++ if [ "$timeout" -eq 0 ]; then
++ echo "firmware interface never appeared:" >&2
++ echo "$DIR/$name/loading" >&2
++ exit 1
++ fi
++ done
++ echo -1 >"$DIR"/"$name"/loading
++}
++
++test_request_firmware_nowait_custom_nofile()
++{
++ echo -n "Batched request_firmware_nowait(uevent=false) nofile try #$1: "
++ config_unset_uevent
++ config_set_name nope-test-firmware.bin
++ config_trigger_async &
++ test_wait_and_cancel_custom_load nope-test-firmware.bin
++ wait
++ release_all_firmware
++ echo "OK"
++}
++
++test_batched_request_firmware()
++{
++ echo -n "Batched request_firmware() try #$1: "
++ config_reset
++ config_trigger_sync
++ read_firmwares
++ release_all_firmware
++ echo "OK"
++}
++
++test_batched_request_firmware_direct()
++{
++ echo -n "Batched request_firmware_direct() try #$1: "
++ config_reset
++ config_set_sync_direct
++ config_trigger_sync
++ release_all_firmware
++ echo "OK"
++}
++
++test_request_firmware_nowait_uevent()
++{
++ echo -n "Batched request_firmware_nowait(uevent=true) try #$1: "
++ config_reset
++ config_trigger_async
++ release_all_firmware
++ echo "OK"
++}
++
++test_request_firmware_nowait_custom()
++{
++ echo -n "Batched request_firmware_nowait(uevent=false) try #$1: "
++ config_unset_uevent
++ config_trigger_async
++ release_all_firmware
++ echo "OK"
++}
++
++# Only continue if batched request triggers are present on the
++# test-firmware driver
++test_config_present
++
++# test with the file present
++echo
++echo "Testing with the file present..."
++for i in $(seq 1 5); do
++ test_batched_request_firmware $i
++done
++
++for i in $(seq 1 5); do
++ test_batched_request_firmware_direct $i
++done
++
++for i in $(seq 1 5); do
++ test_request_firmware_nowait_uevent $i
++done
++
++for i in $(seq 1 5); do
++ test_request_firmware_nowait_custom $i
++done
++
++# Test for file not found, errors are expected, the failure would be
++# a hung task, which would require a hard reset.
++echo
++echo "Testing with the file missing..."
++for i in $(seq 1 5); do
++ test_batched_request_firmware_nofile $i
++done
++
++for i in $(seq 1 5); do
++ test_batched_request_firmware_direct_nofile $i
++done
++
++for i in $(seq 1 5); do
++ test_request_firmware_nowait_uevent_nofile $i
++done
++
++for i in $(seq 1 5); do
++ test_request_firmware_nowait_custom_nofile $i
++done
++
+ exit 0
+--
+2.14.0
+
diff --git a/patches.drivers/0005-test_sysctl-test-against-PAGE_SIZE-for-int.patch b/patches.drivers/0005-test_sysctl-test-against-PAGE_SIZE-for-int.patch
new file mode 100644
index 0000000000..6ead9c2221
--- /dev/null
+++ b/patches.drivers/0005-test_sysctl-test-against-PAGE_SIZE-for-int.patch
@@ -0,0 +1,149 @@
+From 64a5ca15cfeb580127166c071bd1a771cc52ef84 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:49 -0700
+Subject: [PATCH 5/9] test_sysctl: test against PAGE_SIZE for int
+Git-commit: 1c0357c846452add7c2c863ec372010e3d2ca943
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Add the following tests to ensure we do not regress:
+
+ o Test using a buffer full of space (PAGE_SIZE-1) followed by a
+ single digit works
+
+ o Test using a buffer full of spaces (PAGE_SIZE or over) will fail
+
+As tests increase instead of unloading the module and reloading it we
+can just do a shell reset_vals() with a reset to values we know are set
+at init on the driver.
+
+Link: http://lkml.kernel.org/r/20170630224431.17374-4-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ tools/testing/selftests/sysctl/sysctl.sh | 66 ++++++++++++++++++++++++++++++++
+ 1 file changed, 66 insertions(+)
+
+diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
+index cbe1345d7c1d..6ec807576f7c 100644
+--- a/tools/testing/selftests/sysctl/sysctl.sh
++++ b/tools/testing/selftests/sysctl/sysctl.sh
+@@ -75,6 +75,13 @@ function check_production_sysctl_writes_strict()
+ echo "1" > ${WRITES_STRICT}
+ fi
+ fi
++
++ if [ -z $PAGE_SIZE ]; then
++ PAGE_SIZE=$(getconf PAGESIZE)
++ fi
++ if [ -z $MAX_DIGITS ]; then
++ MAX_DIGITS=$(($PAGE_SIZE/8))
++ fi
+ }
+
+ test_reqs()
+@@ -89,6 +96,10 @@ test_reqs()
+ echo "$0: You need perl installed"
+ exit 1
+ fi
++ if ! which getconf 2> /dev/null > /dev/null; then
++ echo "$0: You need getconf installed"
++ exit 1
++ fi
+ }
+
+ function load_req_mod()
+@@ -103,6 +114,23 @@ function load_req_mod()
+ fi
+ }
+
++reset_vals()
++{
++ VAL=""
++ TRIGGER=$(basename ${TARGET})
++ case "$TRIGGER" in
++ int_0001)
++ VAL="60"
++ ;;
++ string_0001)
++ VAL="(none)"
++ ;;
++ *)
++ ;;
++ esac
++ echo -n $VAL > $TARGET
++}
++
+ set_orig()
+ {
+ if [ ! -z $TARGET ]; then
+@@ -229,7 +257,42 @@ run_numerictests()
+ else
+ echo "ok"
+ fi
++ test_rc
++}
++
++# Your test must accept digits 3 and 4 to use this
++run_limit_digit()
++{
++ echo -n "Checking ignoring spaces up to PAGE_SIZE works on write ..."
++ reset_vals
+
++ LIMIT=$((MAX_DIGITS -1))
++ TEST_STR="3"
++ (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
++ dd of="${TARGET}" 2>/dev/null
++
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Checking passing PAGE_SIZE of spaces fails on write ..."
++ reset_vals
++
++ LIMIT=$((MAX_DIGITS))
++ TEST_STR="4"
++ (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
++ dd of="${TARGET}" 2>/dev/null
++
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
+ test_rc
+ }
+
+@@ -305,15 +368,18 @@ run_stringtests()
+ sysctl_test_0001()
+ {
+ TARGET="${SYSCTL}/int_0001"
++ reset_vals
+ ORIG=$(cat "${TARGET}")
+ TEST_STR=$(( $ORIG + 1 ))
+
+ run_numerictests
++ run_limit_digit
+ }
+
+ sysctl_test_0002()
+ {
+ TARGET="${SYSCTL}/string_0001"
++ reset_vals
+ ORIG=$(cat "${TARGET}")
+ TEST_STR="Testing sysctl"
+ # Only string sysctls support seeking/appending.
+--
+2.14.0
+
diff --git a/patches.drivers/0006-test_sysctl-add-simple-proc_dointvec-case.patch b/patches.drivers/0006-test_sysctl-add-simple-proc_dointvec-case.patch
new file mode 100644
index 0000000000..571e31a86d
--- /dev/null
+++ b/patches.drivers/0006-test_sysctl-add-simple-proc_dointvec-case.patch
@@ -0,0 +1,170 @@
+From 176e9abdd2402621a7d9962e70185c63bd13a29a Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:52 -0700
+Subject: [PATCH 6/9] test_sysctl: add simple proc_dointvec() case
+Git-commit: 2920fad3a5d394b66011c7f35c7b05278354055e
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Test against a simple proc_dointvec() case. While at it, add a test
+against INT_MAX. Make sure INT_MAX works, and INT_MAX+1 will fail.
+Also test negative values work.
+
+Link: http://lkml.kernel.org/r/20170630224431.17374-5-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ lib/test_sysctl.c | 11 ++++++
+ tools/testing/selftests/sysctl/sysctl.sh | 62 ++++++++++++++++++++++++++++++++
+ 2 files changed, 73 insertions(+)
+
+diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c
+index b2163bfb6eb2..1472e1ae4931 100644
+--- a/lib/test_sysctl.c
++++ b/lib/test_sysctl.c
+@@ -41,11 +41,15 @@ static int i_one_hundred = 100;
+
+ struct test_sysctl_data {
+ int int_0001;
++ int int_0002;
++
+ char string_0001[65];
+ };
+
+ static struct test_sysctl_data test_data = {
+ .int_0001 = 60,
++ .int_0002 = 1,
++
+ .string_0001 = "(none)",
+ };
+
+@@ -60,6 +64,13 @@ static struct ctl_table test_table[] = {
+ .extra1 = &i_zero,
+ .extra2 = &i_one_hundred,
+ },
++ {
++ .procname = "int_0002",
++ .data = &test_data.int_0002,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec,
++ },
+ {
+ .procname = "string_0001",
+ .data = &test_data.string_0001,
+diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
+index 6ec807576f7c..7ba3fa2bbd54 100644
+--- a/tools/testing/selftests/sysctl/sysctl.sh
++++ b/tools/testing/selftests/sysctl/sysctl.sh
+@@ -31,6 +31,7 @@ TEST_FILE=$(mktemp)
+ # we have tons of space.
+ ALL_TESTS="0001:1:1"
+ ALL_TESTS="$ALL_TESTS 0002:1:1"
++ALL_TESTS="$ALL_TESTS 0003:1:1"
+
+ test_modprobe()
+ {
+@@ -82,6 +83,9 @@ function check_production_sysctl_writes_strict()
+ if [ -z $MAX_DIGITS ]; then
+ MAX_DIGITS=$(($PAGE_SIZE/8))
+ fi
++ if [ -z $INT_MAX ]; then
++ INT_MAX=$(getconf INT_MAX)
++ fi
+ }
+
+ test_reqs()
+@@ -122,6 +126,9 @@ reset_vals()
+ int_0001)
+ VAL="60"
+ ;;
++ int_0002)
++ VAL="1"
++ ;;
+ string_0001)
+ VAL="(none)"
+ ;;
+@@ -296,6 +303,48 @@ run_limit_digit()
+ test_rc
+ }
+
++# You are using an int
++run_limit_digit_int()
++{
++ echo -n "Testing INT_MAX works ..."
++ reset_vals
++ TEST_STR="$INT_MAX"
++ echo -n $TEST_STR > $TARGET
++
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing INT_MAX + 1 will fail as expected..."
++ reset_vals
++ let TEST_STR=$INT_MAX+1
++ echo -n $TEST_STR > $TARGET 2> /dev/null
++
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing negative values will work as expected..."
++ reset_vals
++ TEST_STR="-3"
++ echo -n $TEST_STR > $TARGET 2> /dev/null
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++}
++
+ run_stringtests()
+ {
+ echo -n "Writing entire sysctl in short writes ... "
+@@ -389,6 +438,18 @@ sysctl_test_0002()
+ run_stringtests
+ }
+
++sysctl_test_0003()
++{
++ TARGET="${SYSCTL}/int_0002"
++ reset_vals
++ ORIG=$(cat "${TARGET}")
++ TEST_STR=$(( $ORIG + 1 ))
++
++ run_numerictests
++ run_limit_digit
++ run_limit_digit_int
++}
++
+ list_tests()
+ {
+ echo "Test ID list:"
+@@ -399,6 +460,7 @@ list_tests()
+ echo
+ echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
+ echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
++ echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
+ }
+
+ test_reqs
+--
+2.14.0
+
diff --git a/patches.drivers/0007-test_sysctl-add-simple-proc_douintvec-case.patch b/patches.drivers/0007-test_sysctl-add-simple-proc_douintvec-case.patch
new file mode 100644
index 0000000000..34930fc9c3
--- /dev/null
+++ b/patches.drivers/0007-test_sysctl-add-simple-proc_douintvec-case.patch
@@ -0,0 +1,173 @@
+From 62d3f48c0048d0c9b261544c9c9b166f4df67cfd Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:55 -0700
+Subject: [PATCH 7/9] test_sysctl: add simple proc_douintvec() case
+Git-commit: 2920fad3a5d394b66011c7f35c7b05278354055e
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Test against a simple proc_douintvec() case. While at it, add a test
+against UINT_MAX. Make sure UINT_MAX works, and UINT_MAX+1 will fail
+and that negative values are not accepted.
+
+Link: http://lkml.kernel.org/r/20170630224431.17374-6-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ lib/test_sysctl.c | 11 ++++++
+ tools/testing/selftests/sysctl/sysctl.sh | 63 ++++++++++++++++++++++++++++++++
+ 2 files changed, 74 insertions(+)
+
+diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c
+index 1472e1ae4931..53db3513ab08 100644
+--- a/lib/test_sysctl.c
++++ b/lib/test_sysctl.c
+@@ -43,6 +43,8 @@ struct test_sysctl_data {
+ int int_0001;
+ int int_0002;
+
++ unsigned int uint_0001;
++
+ char string_0001[65];
+ };
+
+@@ -50,6 +52,8 @@ static struct test_sysctl_data test_data = {
+ .int_0001 = 60,
+ .int_0002 = 1,
+
++ .uint_0001 = 314,
++
+ .string_0001 = "(none)",
+ };
+
+@@ -71,6 +75,13 @@ static struct ctl_table test_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
++ {
++ .procname = "uint_0001",
++ .data = &test_data.uint_0001,
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = proc_douintvec,
++ },
+ {
+ .procname = "string_0001",
+ .data = &test_data.string_0001,
+diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
+index 7ba3fa2bbd54..abeef675a884 100644
+--- a/tools/testing/selftests/sysctl/sysctl.sh
++++ b/tools/testing/selftests/sysctl/sysctl.sh
+@@ -32,6 +32,7 @@ TEST_FILE=$(mktemp)
+ ALL_TESTS="0001:1:1"
+ ALL_TESTS="$ALL_TESTS 0002:1:1"
+ ALL_TESTS="$ALL_TESTS 0003:1:1"
++ALL_TESTS="$ALL_TESTS 0004:1:1"
+
+ test_modprobe()
+ {
+@@ -86,6 +87,9 @@ function check_production_sysctl_writes_strict()
+ if [ -z $INT_MAX ]; then
+ INT_MAX=$(getconf INT_MAX)
+ fi
++ if [ -z $UINT_MAX ]; then
++ UINT_MAX=$(getconf UINT_MAX)
++ fi
+ }
+
+ test_reqs()
+@@ -129,6 +133,9 @@ reset_vals()
+ int_0002)
+ VAL="1"
+ ;;
++ uint_0001)
++ VAL="314"
++ ;;
+ string_0001)
+ VAL="(none)"
+ ;;
+@@ -345,6 +352,49 @@ run_limit_digit_int()
+ test_rc
+ }
+
++# You are using an unsigned int
++run_limit_digit_uint()
++{
++ echo -n "Testing UINT_MAX works ..."
++ reset_vals
++ TEST_STR="$UINT_MAX"
++ echo -n $TEST_STR > $TARGET
++
++ if ! verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing UINT_MAX + 1 will fail as expected..."
++ reset_vals
++ TEST_STR=$(($UINT_MAX+1))
++ echo -n $TEST_STR > $TARGET 2> /dev/null
++
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing negative values will not work as expected ..."
++ reset_vals
++ TEST_STR="-3"
++ echo -n $TEST_STR > $TARGET 2> /dev/null
++
++ if verify "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++}
++
+ run_stringtests()
+ {
+ echo -n "Writing entire sysctl in short writes ... "
+@@ -450,6 +500,18 @@ sysctl_test_0003()
+ run_limit_digit_int
+ }
+
++sysctl_test_0004()
++{
++ TARGET="${SYSCTL}/uint_0001"
++ reset_vals
++ ORIG=$(cat "${TARGET}")
++ TEST_STR=$(( $ORIG + 1 ))
++
++ run_numerictests
++ run_limit_digit
++ run_limit_digit_uint
++}
++
+ list_tests()
+ {
+ echo "Test ID list:"
+@@ -461,6 +523,7 @@ list_tests()
+ echo "0001 x $(get_test_count 0001) - tests proc_dointvec_minmax()"
+ echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
+ echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
++ echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
+ }
+
+ test_reqs
+--
+2.14.0
+
diff --git a/patches.drivers/0008-test_sysctl-test-against-int-proc_dointvec-array-sup.patch b/patches.drivers/0008-test_sysctl-test-against-int-proc_dointvec-array-sup.patch
new file mode 100644
index 0000000000..cb925a5f10
--- /dev/null
+++ b/patches.drivers/0008-test_sysctl-test-against-int-proc_dointvec-array-sup.patch
@@ -0,0 +1,204 @@
+From 1ce7ae4dd489af87a8ee6fefd58c16b19a9ba364 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:58 -0700
+Subject: [PATCH 8/9] test_sysctl: test against int proc_dointvec() array
+ support
+Git-commit: 7c43a657a4beadeb6d2fe1a00732261e313a807f
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Add a few initial respective tests for an array:
+
+ o Echoing values separated by spaces works
+ o Echoing only first elements will set first elements
+ o Confirm PAGE_SIZE limit still applies even if an array is used
+
+Link: http://lkml.kernel.org/r/20170630224431.17374-7-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ lib/test_sysctl.c | 13 +++++
+ tools/testing/selftests/sysctl/sysctl.sh | 89 ++++++++++++++++++++++++++++++++
+ 2 files changed, 102 insertions(+)
+
+diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c
+index 53db3513ab08..3dd801c1c85b 100644
+--- a/lib/test_sysctl.c
++++ b/lib/test_sysctl.c
+@@ -42,6 +42,7 @@ static int i_one_hundred = 100;
+ struct test_sysctl_data {
+ int int_0001;
+ int int_0002;
++ int int_0003[4];
+
+ unsigned int uint_0001;
+
+@@ -52,6 +53,11 @@ static struct test_sysctl_data test_data = {
+ .int_0001 = 60,
+ .int_0002 = 1,
+
++ .int_0003[0] = 0,
++ .int_0003[1] = 1,
++ .int_0003[2] = 2,
++ .int_0003[3] = 3,
++
+ .uint_0001 = 314,
+
+ .string_0001 = "(none)",
+@@ -75,6 +81,13 @@ static struct ctl_table test_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
++ {
++ .procname = "int_0003",
++ .data = &test_data.int_0003,
++ .maxlen = sizeof(test_data.int_0003),
++ .mode = 0644,
++ .proc_handler = proc_dointvec,
++ },
+ {
+ .procname = "uint_0001",
+ .data = &test_data.uint_0001,
+diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
+index abeef675a884..ec232c3cfcaa 100644
+--- a/tools/testing/selftests/sysctl/sysctl.sh
++++ b/tools/testing/selftests/sysctl/sysctl.sh
+@@ -33,6 +33,7 @@ ALL_TESTS="0001:1:1"
+ ALL_TESTS="$ALL_TESTS 0002:1:1"
+ ALL_TESTS="$ALL_TESTS 0003:1:1"
+ ALL_TESTS="$ALL_TESTS 0004:1:1"
++ALL_TESTS="$ALL_TESTS 0005:3:1"
+
+ test_modprobe()
+ {
+@@ -108,6 +109,10 @@ test_reqs()
+ echo "$0: You need getconf installed"
+ exit 1
+ fi
++ if ! which diff 2> /dev/null > /dev/null; then
++ echo "$0: You need diff installed"
++ exit 1
++ fi
+ }
+
+ function load_req_mod()
+@@ -167,6 +172,12 @@ verify()
+ return 0
+ }
+
++verify_diff_w()
++{
++ echo "$TEST_STR" | diff -q -w -u - $1
++ return $?
++}
++
+ test_rc()
+ {
+ if [[ $rc != 0 ]]; then
+@@ -352,6 +363,74 @@ run_limit_digit_int()
+ test_rc
+ }
+
++# You used an int array
++run_limit_digit_int_array()
++{
++ echo -n "Testing array works as expected ... "
++ TEST_STR="4 3 2 1"
++ echo -n $TEST_STR > $TARGET
++
++ if ! verify_diff_w "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing skipping trailing array elements works ... "
++ # Do not reset_vals, carry on the values from the last test.
++ # If we only echo in two digits the last two are left intact
++ TEST_STR="100 101"
++ echo -n $TEST_STR > $TARGET
++ # After we echo in, to help diff we need to set on TEST_STR what
++ # we expect the result to be.
++ TEST_STR="100 101 2 1"
++
++ if ! verify_diff_w "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing PAGE_SIZE limit on array works ... "
++ # Do not reset_vals, carry on the values from the last test.
++ # Even if you use an int array, you are still restricted to
++ # MAX_DIGITS, this is a known limitation. Test limit works.
++ LIMIT=$((MAX_DIGITS -1))
++ TEST_STR="9"
++ (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
++ dd of="${TARGET}" 2>/dev/null
++
++ TEST_STR="9 101 2 1"
++ if ! verify_diff_w "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++
++ echo -n "Testing exceeding PAGE_SIZE limit fails as expected ... "
++ # Do not reset_vals, carry on the values from the last test.
++ # Now go over limit.
++ LIMIT=$((MAX_DIGITS))
++ TEST_STR="7"
++ (perl -e 'print " " x '$LIMIT';'; echo "${TEST_STR}") | \
++ dd of="${TARGET}" 2>/dev/null
++
++ TEST_STR="7 101 2 1"
++ if verify_diff_w "${TARGET}"; then
++ echo "FAIL" >&2
++ rc=1
++ else
++ echo "ok"
++ fi
++ test_rc
++}
++
+ # You are using an unsigned int
+ run_limit_digit_uint()
+ {
+@@ -512,6 +591,15 @@ sysctl_test_0004()
+ run_limit_digit_uint
+ }
+
++sysctl_test_0005()
++{
++ TARGET="${SYSCTL}/int_0003"
++ reset_vals
++ ORIG=$(cat "${TARGET}")
++
++ run_limit_digit_int_array
++}
++
+ list_tests()
+ {
+ echo "Test ID list:"
+@@ -524,6 +612,7 @@ list_tests()
+ echo "0002 x $(get_test_count 0002) - tests proc_dostring()"
+ echo "0003 x $(get_test_count 0003) - tests proc_dointvec()"
+ echo "0004 x $(get_test_count 0004) - tests proc_douintvec()"
++ echo "0005 x $(get_test_count 0005) - tests proc_douintvec() array"
+ }
+
+ test_reqs
+--
+2.14.0
+
diff --git a/patches.drivers/0009-test_sysctl-fix-sysctl.sh-by-making-it-executable.patch b/patches.drivers/0009-test_sysctl-fix-sysctl.sh-by-making-it-executable.patch
new file mode 100644
index 0000000000..e1d8990600
--- /dev/null
+++ b/patches.drivers/0009-test_sysctl-fix-sysctl.sh-by-making-it-executable.patch
@@ -0,0 +1,32 @@
+From ebcd64670877e635561462d76e7f6a8279565add Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Thu, 3 Aug 2017 09:57:13 -0700
+Subject: [PATCH 9/9] test_sysctl: fix sysctl.sh by making it executable
+Git-commit: 8b0949d407431559f7c80a02f5382f5e1c77b8d1
+Patch-mainline: v4.13-rc6
+References: FATE#323821
+
+We had just forogtten to do this. Without this the following test fails:
+
+$ sudo make -C tools/testing/selftests/sysctl/ run_tests
+make: Entering directory '/home/mcgrof/linux-next/tools/testing/selftests/sysctl'
+/bin/sh: ./sysctl.sh: Permission denied
+selftests: sysctl.sh [FAIL]
+/home/mcgrof/linux-next/tools/testing/selftests/sysctl
+make: Leaving directory '/home/mcgrof/linux-next/tools/testing/selftests/sysctl'
+
+Fixes: 64b671204afd71 ("test_sysctl: add generic script to expand on tests")
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ tools/testing/selftests/sysctl/sysctl.sh | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+ mode change 100644 => 100755 tools/testing/selftests/sysctl/sysctl.sh
+
+diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
+old mode 100644
+new mode 100755
+--
+2.14.0
+
diff --git a/patches.suse/0001-firmware-send-EINTR-on-signal-abort-on-fallback-mech.patch b/patches.suse/0001-firmware-send-EINTR-on-signal-abort-on-fallback-mech.patch
new file mode 100644
index 0000000000..c3171281db
--- /dev/null
+++ b/patches.suse/0001-firmware-send-EINTR-on-signal-abort-on-fallback-mech.patch
@@ -0,0 +1,46 @@
+From 4041b495bf4f42ac645e387dfa66d2c3120551f5 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Thu, 20 Jul 2017 13:13:39 -0700
+Subject: [PATCH 1/5] firmware: send -EINTR on signal abort on fallback
+ mechanism
+Git-commit: 76098b36b5db1a509e5af94128b08f950692c7f8
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Right now we send -EAGAIN to a syfs write which got interrupted.
+Userspace can't tell what happened though, send -EINTR if we
+were killed due to a signal so userspace can tell things apart.
+
+This is only applicable to the fallback mechanism.
+
+Reported-by: Martin Fuzzey <mfuzzey@parkeon.com>
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ drivers/base/firmware_class.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
+index 31c0586d9b13..9bc89f332d29 100644
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -1019,9 +1019,12 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
+ mutex_unlock(&fw_lock);
+ }
+
+- if (fw_state_is_aborted(&buf->fw_st))
+- retval = -EAGAIN;
+- else if (buf->is_paged_buf && !buf->data)
++ if (fw_state_is_aborted(&buf->fw_st)) {
++ if (retval == -ERESTARTSYS)
++ retval = -EINTR;
++ else
++ retval = -EAGAIN;
++ } else if (buf->is_paged_buf && !buf->data)
+ retval = -ENOMEM;
+
+ device_del(f_dev);
+--
+2.14.0
+
diff --git a/patches.suse/0001-sysctl-add-unsigned-int-range-support.patch b/patches.suse/0001-sysctl-add-unsigned-int-range-support.patch
new file mode 100644
index 0000000000..426f7acc0a
--- /dev/null
+++ b/patches.suse/0001-sysctl-add-unsigned-int-range-support.patch
@@ -0,0 +1,165 @@
+From 2cd000a58485ae96e216bb14c92243a4d0b7721a Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 12 Jul 2017 14:33:40 -0700
+Subject: [PATCH 1/9] sysctl: add unsigned int range support
+Git-commit: 61d9b56a89208d8cccd0b4cfec7e6959717e16e3
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+To keep parity with regular int interfaces provide the an unsigned int
+proc_douintvec_minmax() which allows you to specify a range of allowed
+valid numbers.
+
+Adding proc_douintvec_minmax_sysadmin() is easy but we can wait for an
+actual user for that.
+
+Link: http://lkml.kernel.org/r/20170519033554.18592-6-mcgrof@kernel.org
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Acked-by: Kees Cook <keescook@chromium.org>
+Cc: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Alexey Dobriyan <adobriyan@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ fs/proc/proc_sysctl.c | 4 ++-
+ include/linux/sysctl.h | 3 +++
+ kernel/sysctl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 72 insertions(+), 1 deletion(-)
+
+diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
+index 4563c12d95ba..8f479229b349 100644
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -1082,7 +1082,8 @@ static int sysctl_check_table_array(const char *path, struct ctl_table *table)
+ {
+ int err = 0;
+
+- if (table->proc_handler == proc_douintvec) {
++ if ((table->proc_handler == proc_douintvec) ||
++ (table->proc_handler == proc_douintvec_minmax)) {
+ if (table->maxlen != sizeof(unsigned int))
+ err |= sysctl_err(path, table, "array now allowed");
+ }
+@@ -1100,6 +1101,7 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
+ if ((table->proc_handler == proc_dostring) ||
+ (table->proc_handler == proc_dointvec) ||
+ (table->proc_handler == proc_douintvec) ||
++ (table->proc_handler == proc_douintvec_minmax) ||
+ (table->proc_handler == proc_dointvec_minmax) ||
+ (table->proc_handler == proc_dointvec_jiffies) ||
+ (table->proc_handler == proc_dointvec_userhz_jiffies) ||
+diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
+index 1c04a26bfd2f..3a89b9ff4cdc 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -47,6 +47,9 @@ extern int proc_douintvec(struct ctl_table *, int,
+ void __user *, size_t *, loff_t *);
+ extern int proc_dointvec_minmax(struct ctl_table *, int,
+ void __user *, size_t *, loff_t *);
++extern int proc_douintvec_minmax(struct ctl_table *table, int write,
++ void __user *buffer, size_t *lenp,
++ loff_t *ppos);
+ extern int proc_dointvec_jiffies(struct ctl_table *, int,
+ void __user *, size_t *, loff_t *);
+ extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int,
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 060395ccb10b..fd5ca3bdd096 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -2583,6 +2583,65 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
+ do_proc_dointvec_minmax_conv, &param);
+ }
+
++struct do_proc_douintvec_minmax_conv_param {
++ unsigned int *min;
++ unsigned int *max;
++};
++
++static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
++ unsigned int *valp,
++ int write, void *data)
++{
++ struct do_proc_douintvec_minmax_conv_param *param = data;
++
++ if (write) {
++ unsigned int val = *lvalp;
++
++ if ((param->min && *param->min > val) ||
++ (param->max && *param->max < val))
++ return -ERANGE;
++
++ if (*lvalp > UINT_MAX)
++ return -EINVAL;
++ *valp = val;
++ } else {
++ unsigned int val = *valp;
++ *lvalp = (unsigned long) val;
++ }
++
++ return 0;
++}
++
++/**
++ * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
++ * @table: the sysctl table
++ * @write: %TRUE if this is a write to the sysctl file
++ * @buffer: the user buffer
++ * @lenp: the size of the user buffer
++ * @ppos: file position
++ *
++ * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
++ * values from/to the user buffer, treated as an ASCII string. Negative
++ * strings are not allowed.
++ *
++ * This routine will ensure the values are within the range specified by
++ * table->extra1 (min) and table->extra2 (max). There is a final sanity
++ * check for UINT_MAX to avoid having to support wrap around uses from
++ * userspace.
++ *
++ * Returns 0 on success.
++ */
++int proc_douintvec_minmax(struct ctl_table *table, int write,
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ struct do_proc_douintvec_minmax_conv_param param = {
++ .min = (unsigned int *) table->extra1,
++ .max = (unsigned int *) table->extra2,
++ };
++ return do_proc_douintvec(table, write, buffer, lenp, ppos,
++ do_proc_douintvec_minmax_conv, &param);
++}
++
+ static void validate_coredump_safety(void)
+ {
+ #ifdef CONFIG_COREDUMP
+@@ -3082,6 +3141,12 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
+ return -ENOSYS;
+ }
+
++int proc_douintvec_minmax(struct ctl_table *table, int write,
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ return -ENOSYS;
++}
++
+ int proc_dointvec_jiffies(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+@@ -3124,6 +3189,7 @@ EXPORT_SYMBOL(proc_dointvec);
+ EXPORT_SYMBOL(proc_douintvec);
+ EXPORT_SYMBOL(proc_dointvec_jiffies);
+ EXPORT_SYMBOL(proc_dointvec_minmax);
++EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
+ EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
+ EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
+ EXPORT_SYMBOL(proc_dostring);
+--
+2.14.0
+
diff --git a/patches.suse/0002-firmware-define-pr_fmt.patch b/patches.suse/0002-firmware-define-pr_fmt.patch
new file mode 100644
index 0000000000..e316f5982f
--- /dev/null
+++ b/patches.suse/0002-firmware-define-pr_fmt.patch
@@ -0,0 +1,34 @@
+From f84e858d81758167a61e28bfa63ddf1ffc8699e9 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Thu, 20 Jul 2017 13:13:40 -0700
+Subject: [PATCH 2/5] firmware: define pr_fmt
+Git-commit: 73da4b4b77661ba3a9a50e5fbb412c9766149911
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+For some reason we have always forgotten this. Without this
+we don't get a nice prefix on our pr_debug() / pr_*() messages.
+
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ drivers/base/firmware_class.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
+index 9bc89f332d29..dc2c1c8f4e4c 100644
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -7,6 +7,8 @@
+ *
+ */
+
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
+ #include <linux/capability.h>
+ #include <linux/device.h>
+ #include <linux/module.h>
+--
+2.14.0
+
diff --git a/patches.suse/0003-firmware-enable-a-debug-print-for-batched-requests.patch b/patches.suse/0003-firmware-enable-a-debug-print-for-batched-requests.patch
new file mode 100644
index 0000000000..d8015d06be
--- /dev/null
+++ b/patches.suse/0003-firmware-enable-a-debug-print-for-batched-requests.patch
@@ -0,0 +1,40 @@
+From 14c98e1bdf3fe78c9465f593ee4b018bbb535aea Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Thu, 20 Jul 2017 13:13:41 -0700
+Subject: [PATCH 3/5] firmware: enable a debug print for batched requests
+Git-commit: 30172bead80e089072c6f2d00e68831c51ebbc19
+Patch-mainline: v4.13-rc1
+References: FATE#323821
+
+Otherwise there is no easy way this actually happened.
+
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+ drivers/base/firmware_class.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
+index dc2c1c8f4e4c..f9ed81c866c3 100644
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -301,6 +301,7 @@ static struct firmware_buf *__fw_lookup_buf(const char *fw_name)
+ return NULL;
+ }
+
++/* Returns 1 for batching firmware requests with the same name */
+ static int fw_lookup_and_allocate_buf(const char *fw_name,
+ struct firmware_cache *fwc,
+ struct firmware_buf **buf, void *dbuf,
+@@ -314,6 +315,7 @@ static int fw_lookup_and_allocate_buf(const char *fw_name,
+ kref_get(&tmp->ref);
+ spin_unlock(&fwc->lock);
+ *buf = tmp;
++ pr_debug("batched request - sharing the same struct firmware_buf and lookup for multiple requests\n");
+ return 1;
+ }
+ tmp = __allocate_fw_buf(fw_name, fwc, dbuf, size);
+--
+2.14.0
+
diff --git a/rpm/package-descriptions b/rpm/package-descriptions
index 482b6e0ab0..4217dbda3e 100644
--- a/rpm/package-descriptions
+++ b/rpm/package-descriptions
@@ -126,3 +126,24 @@ Requires: dlm-kmp
OCFS2 is the Oracle Cluster Filesystem, a filesystem for shared devices
accessible simultaneously from multiple nodes of a cluster.
+
+=== kselftests-kmp ===
+Kernel sefltests
+
+This package contains kernel modules which are part of the upstream kernel
+selftest effort. kselftest is the name of the upstream kernel target to build
+and run all selftests. You can also run each test individually from the
+respective upstream tools/testing/selftests/ directory, this package is
+intended to be used using individial upstream selftest scripts given only
+select supported selftest drivers are enabled.
+
+It should always be possible to always run the latest linux-next version of the
+selftest scripts and tests against any older kernel selftest driver. Certain
+tests facilities may be backported onto older kernels to enable further
+testing.
+
+Selftests also provide for a vehicle or proof of concept issues to be
+reproduced, verified and corrected.
+
+Selftest drivers are intended to be supported only in testing and QA
+environments, they are not intended to be run on production systems.
diff --git a/series.conf b/series.conf
index 05c2239983..9a0bde0684 100644
--- a/series.conf
+++ b/series.conf
@@ -5105,6 +5105,28 @@
patches.fixes/0006-sysctl-simplify-unsigned-int-support.patch
########################################################
+ # Kernel selftest drivers / framework
+ ########################################################
+ # FATE#323821 - sysctl selftest driver requirements
+ patches.suse/0001-sysctl-add-unsigned-int-range-support.patch
+ # FATE#323821 - sysctl selftest driver
+ patches.drivers/0002-tools-testing-selftests-sysctl-Add-pre-check-to-the-.patch
+ patches.drivers/0003-test_sysctl-add-dedicated-proc-sysctl-test-driver.patch
+ patches.drivers/0004-test_sysctl-add-generic-script-to-expand-on-tests.patch
+ patches.drivers/0005-test_sysctl-test-against-PAGE_SIZE-for-int.patch
+ patches.drivers/0006-test_sysctl-add-simple-proc_dointvec-case.patch
+ patches.drivers/0007-test_sysctl-add-simple-proc_douintvec-case.patch
+ patches.drivers/0008-test_sysctl-test-against-int-proc_dointvec-array-sup.patch
+ patches.drivers/0009-test_sysctl-fix-sysctl.sh-by-making-it-executable.patch
+ # FATE#323821 - firmware selftest driver requirements
+ patches.suse/0001-firmware-send-EINTR-on-signal-abort-on-fallback-mech.patch
+ patches.suse/0002-firmware-define-pr_fmt.patch
+ patches.suse/0003-firmware-enable-a-debug-print-for-batched-requests.patch
+ # FATE#323821 - firmware selftest driver
+ patches.drivers/0004-test_firmware-add-test-case-for-SIGCHLD-on-sync-fall.patch
+ patches.drivers/0005-test_firmware-add-batched-firmware-tests.patch
+
+ ########################################################
# Live patching
########################################################
diff --git a/supported.conf b/supported.conf
index 735c18340f..db596c1dcf 100644
--- a/supported.conf
+++ b/supported.conf
@@ -2270,6 +2270,9 @@
lib/zlib_deflate/zlib_deflate
crypto/842
lib/842/842_compress # NX driver for Power
++kselftests-kmp lib/test_sysctl # FATE#323821
++kselftests-kmp lib/test_firmware # FATE#323821
+
mm/hwpoison-inject # Needed for Intel MCE/RAS testing bsc#572552
- mm/z3fold.ko
- net/6lowpan/* # IPv6 over Low power Wireless Personal Area Network