summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Myandin2021-12-20 12:59:49 +0300
committerEvgeny Myandin2021-12-20 12:59:49 +0300
commite96c22890b7fbde56e7885194b90f11047726a65 (patch)
treeb4e62f2a8d7c3b80c3a546ffc08a7a1ca43180d2
downloadaur-e96c22890b7fbde56e7885194b90f11047726a65.tar.gz
Original Kernel 5.15.10-1 Manjaro Linux + ACS patch
-rw-r--r--.SRCINFO104
-rw-r--r--0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-CLONE_NEWUSER.patch122
-rw-r--r--0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_special_driver-list.patch36
-rw-r--r--0101-i2c-nuvoton-nc677x-hwmon-driver.patch745
-rw-r--r--0102-iomap-iomap_bmap-should-accept-unwritten-maps.patch38
-rw-r--r--0103-futex.patch9811
-rw-r--r--0104-revert-xhci-Add-support-for-Renesas-controller-with-memory.patch89
-rw-r--r--0105-quirk-kernel-org-bug-210681-firmware_rome_error.patch12
-rw-r--r--0201-lenovo-wmi2.patch15
-rw-r--r--0301-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch150
-rw-r--r--0302-revert-fbcon-remove-no-op-fbcon_set_origin.patch31
-rw-r--r--0303-revert-fbcon-remove-soft-scrollback-code.patch500
-rw-r--r--0401-bootsplash.patch746
-rw-r--r--0402-bootsplash.patch669
-rw-r--r--0403-bootsplash.patch66
-rw-r--r--0404-bootsplash.patch215
-rw-r--r--0405-bootsplash.patch327
-rw-r--r--0406-bootsplash.patch82
-rw-r--r--0407-bootsplash.patch42
-rw-r--r--0408-bootsplash.patch21
-rw-r--r--0409-bootsplash.patch21
-rw-r--r--0410-bootsplash.patch321
-rw-r--r--0411-bootsplash.patch129
-rw-r--r--0412-bootsplash.patch511
-rw-r--r--0413-bootsplash.gitpatch162
-rw-r--r--0999-acs.patch127
-rw-r--r--1ac8f753e4249e6864c1c42070ba957ceef1f82a.patch21
-rw-r--r--62f1f7606485d450b23f86bc18dab101e7a2443d.patch51
-rw-r--r--675d4b66de78eec370cf5053eecdf00b26780af3.patch36
-rw-r--r--74db74ec6ce112c6137d51610429e7ac9ea5b6c1.patch85
-rw-r--r--PKGBUILD266
-rw-r--r--ae3386d67597db29ad2ba2685815e224a39897bc.patch57
-rw-r--r--config10680
-rw-r--r--modules.list12
34 files changed, 26300 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..69366aaaed3a
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,104 @@
+pkgbase = linux515
+ pkgver = 5.15.10
+ pkgrel = 1
+ url = https://www.kernel.org/
+ arch = x86_64
+ license = GPL2
+ makedepends = bc
+ makedepends = docbook-xsl
+ makedepends = libelf
+ makedepends = pahole
+ makedepends = git
+ makedepends = inetutils
+ makedepends = kmod
+ makedepends = xmlto
+ makedepends = cpio
+ makedepends = perl
+ makedepends = tar
+ makedepends = xz
+ options = !strip
+ source = https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.15.tar.xz
+ source = https://www.kernel.org/pub/linux/kernel/v5.x/patch-5.15.10.xz
+ source = config
+ source = 0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-CLONE_NEWUSER.patch
+ source = 0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_special_driver-list.patch
+ source = 0101-i2c-nuvoton-nc677x-hwmon-driver.patch
+ source = 0103-futex.patch
+ source = 0104-revert-xhci-Add-support-for-Renesas-controller-with-memory.patch
+ source = 0105-quirk-kernel-org-bug-210681-firmware_rome_error.patch
+ source = 0108-drm_i915_Add_workaround_numbers_to_GEN7_COMMON_SLICE_CHICKEN1_whitelisting.patch::https://patchwork.freedesktop.org/patch/463650/raw/
+ source = 1ac8f753e4249e6864c1c42070ba957ceef1f82a.patch
+ source = 74db74ec6ce112c6137d51610429e7ac9ea5b6c1.patch
+ source = 62f1f7606485d450b23f86bc18dab101e7a2443d.patch
+ source = ae3386d67597db29ad2ba2685815e224a39897bc.patch
+ source = 675d4b66de78eec370cf5053eecdf00b26780af3.patch
+ source = 0201-lenovo-wmi2.patch
+ source = 0301-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
+ source = 0302-revert-fbcon-remove-no-op-fbcon_set_origin.patch
+ source = 0303-revert-fbcon-remove-soft-scrollback-code.patch
+ source = 0401-bootsplash.patch
+ source = 0402-bootsplash.patch
+ source = 0403-bootsplash.patch
+ source = 0404-bootsplash.patch
+ source = 0405-bootsplash.patch
+ source = 0406-bootsplash.patch
+ source = 0407-bootsplash.patch
+ source = 0408-bootsplash.patch
+ source = 0409-bootsplash.patch
+ source = 0410-bootsplash.patch
+ source = 0411-bootsplash.patch
+ source = 0412-bootsplash.patch
+ source = 0413-bootsplash.gitpatch
+ source = 0999-acs.patch
+ sha256sums = 57b2cf6991910e3b67a1b3490022e8a0674b6965c74c12da1e99d138d1991ee8
+ sha256sums = bdb35ece2dd0f6d8225947b63539e70c8fc16bd28f03395d590515d8187f03c4
+ sha256sums = ccbfb721030426bbd148602f99c88aaf226b7a6641a9c8c56973dd25a3f1df94
+ sha256sums = 986f8d802f37b72a54256f0ab84da83cb229388d58c0b6750f7c770818a18421
+ sha256sums = df5843818f1571841e1a8bdbe38d7f853d841f38de46d6a6a5765de089495578
+ sha256sums = 7823d7488f42bc4ed7dfae6d1014dbde679d8b862c9a3697a39ba0dae5918978
+ sha256sums = 844e66a95d7df754c55ac2f1ce7e215b1e56e20ca095462d926a993d557b20e0
+ sha256sums = d9330ea593829a6ef3b824db9570253280cbff7da2b4beb47cbc037824d1a29b
+ sha256sums = 5e804e1f241ce542f3f0e83d274ede6aa4b0539e510fb9376f8106e8732ce69b
+ sha256sums = e8e6120035977903a7117ba215809b9b162b64a789848107513f219180baaada
+ sha256sums = e2823eff3355b7c88a3fa327ea2f84f23cbd36569e0a5f0f76599023f63a52ca
+ sha256sums = ce53090a4572cd6162d22225113082f7e4df5028a1230529d170460e26dcf849
+ sha256sums = ab0360eac59329eb84f028c2f402ee4a17e4b3dfacb7957355e6178d35af87b9
+ sha256sums = 6846fbd7d8e05adc0b25179bc5bbd6320929d155fafd4443eff206d6b8b580ac
+ sha256sums = a2a0a0542055a6a921542fbb05cedb6eb6f3d3fb0c038bfb2304bfd3931a0f71
+ sha256sums = 1d58ef2991c625f6f0eb33b4cb8303932f53f1c4694e42bae24c9cd36d2ad013
+ sha256sums = 2b11905b63b05b25807dd64757c779da74dd4c37e36d3f7a46485b1ee5a9d326
+ sha256sums = 94a8538251ad148f1025cc3de446ce64f73dc32b01815426fb159c722e8fa5bc
+ sha256sums = 1f18c5c10a3c63e41ecd05ad34cd9f6653ba96e9f1049ce2b7bb6da2578ae710
+ sha256sums = 59202940d4f12bad23c194a530edc900e066866c9945e39748484a6545af96de
+ sha256sums = e096b127a5208f56d368d2cb938933454d7200d70c86b763aa22c38e0ddb8717
+ sha256sums = 8c1c880f2caa9c7ae43281a35410203887ea8eae750fe8d360d0c8bf80fcc6e0
+ sha256sums = 1144d51e5eb980fceeec16004f3645ed04a60fac9e0c7cf88a15c5c1e7a4b89e
+ sha256sums = dd4b69def2efacf4a6c442202ad5cb93d492c03886d7c61de87696e5a83e2846
+ sha256sums = 028b07f0c954f70ca37237b62e04103e81f7c658bb8bd65d7d3c2ace301297dc
+ sha256sums = a0c548c5703d25ae34b57931f1162de8b18937e676e5791a0f039922090881e7
+ sha256sums = 8dbb5ab3cb99e48d97d4e2f2e3df5d0de66f3721b4f7fd94a708089f53245c77
+ sha256sums = a7aefeacf22c600fafd9e040a985a913643095db7272c296b77a0a651c6a140a
+ sha256sums = e9f22cbb542591087d2d66dc6dc912b1434330ba3cd13d2df741d869a2c31e89
+ sha256sums = 27471eee564ca3149dd271b0817719b5565a9594dc4d884fe3dc51a5f03832bc
+ sha256sums = 60e295601e4fb33d9bf65f198c54c7eb07c0d1e91e2ad1e0dd6cd6e142cb266d
+ sha256sums = 035ea4b2a7621054f4560471f45336b981538a40172d8f17285910d4e0e0b3ef
+ sha256sums = b00dcd459248e57e1f1799e07d4c6aba9f147bb67b86b9f386e16e2268d89214
+
+pkgname = linux515
+ pkgdesc = The Linux515 kernel and modules
+ depends = coreutils
+ depends = linux-firmware
+ depends = kmod
+ depends = mkinitcpio>=27
+ optdepends = crda: to set the correct wireless channels of your country
+ provides = linux=5.15.10
+ provides = VIRTUALBOX-GUEST-MODULES
+ provides = WIREGUARD-MODULE
+
+pkgname = linux515-headers
+ pkgdesc = Header files and scripts for building modules for Linux515 kernel
+ depends = gawk
+ depends = python
+ depends = libelf
+ depends = pahole
+ provides = linux-headers=5.15.10
diff --git a/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-CLONE_NEWUSER.patch b/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-CLONE_NEWUSER.patch
new file mode 100644
index 000000000000..5301464f63c0
--- /dev/null
+++ b/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-CLONE_NEWUSER.patch
@@ -0,0 +1,122 @@
+--- a/include/linux/sysctl.h 2020-06-12 19:27:22.382363840 +0200
++++ b/include/linux/sysctl.h 2020-06-12 19:27:04.715697333 +0200
+@@ -204,6 +204,10 @@ extern int unaligned_enabled;
+ extern int unaligned_dump_stack;
+ extern int no_unaligned_warning;
+
++#ifdef CONFIG_USER_NS
++extern int unprivileged_userns_clone;
++#endif
++
+ extern struct ctl_table sysctl_mount_point[];
+ extern struct ctl_table random_table[];
+ extern struct ctl_table firmware_config_table[];
+
+diff --git a/init/Kconfig b/init/Kconfig
+index bd7d650d4a99..658f9c052151 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1091,6 +1091,22 @@ config USER_NS
+
+ If unsure, say N.
+
++config USER_NS_UNPRIVILEGED
++ bool "Allow unprivileged users to create namespaces"
++ default y
++ depends on USER_NS
++ help
++ When disabled, unprivileged users will not be able to create
++ new namespaces. Allowing users to create their own namespaces
++ has been part of several recent local privilege escalation
++ exploits, so if you need user namespaces but are
++ paranoid^Wsecurity-conscious you want to disable this.
++
++ This setting can be overridden at runtime via the
++ kernel.unprivileged_userns_clone sysctl.
++
++ If unsure, say Y.
++
+ config PID_NS
+ bool "PID Namespaces"
+ default y
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 541fd805fb88..ffd57c812153 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -106,6 +106,11 @@
+
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/task.h>
++#ifdef CONFIG_USER_NS
++extern int unprivileged_userns_clone;
++#else
++#define unprivileged_userns_clone 0
++#endif
+
+ /*
+ * Minimum number of threads to boot the kernel
+@@ -1788,6 +1793,10 @@ static __latent_entropy struct task_struct *copy_process(
+ if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
+ return ERR_PTR(-EINVAL);
+
++ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
++ if (!capable(CAP_SYS_ADMIN))
++ return ERR_PTR(-EPERM);
++
+ /*
+ * Thread groups must share signals as well, and detached threads
+ * can only be started up within the thread group.
+@@ -2819,6 +2828,12 @@ int ksys_unshare(unsigned long unshare_flags)
+ if (unshare_flags & CLONE_NEWNS)
+ unshare_flags |= CLONE_FS;
+
++ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
++ err = -EPERM;
++ if (!capable(CAP_SYS_ADMIN))
++ goto bad_unshare_out;
++ }
++
+ err = check_unshare_flags(unshare_flags);
+ if (err)
+ goto bad_unshare_out;
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 078950d9605b..baead3605bbe 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -545,6 +548,15 @@ static struct ctl_table kern_table[] = {
+ .proc_handler = proc_dointvec,
+ },
+ #endif
++#ifdef CONFIG_USER_NS
++ {
++ .procname = "unprivileged_userns_clone",
++ .data = &unprivileged_userns_clone,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec,
++ },
++#endif
+ #ifdef CONFIG_PROC_SYSCTL
+ {
+ .procname = "tainted",
+diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
+index 8eadadc478f9..c36ecd19562c 100644
+--- a/kernel/user_namespace.c
++++ b/kernel/user_namespace.c
+@@ -21,6 +21,13 @@
+ #include <linux/bsearch.h>
+ #include <linux/sort.h>
+
++/* sysctl */
++#ifdef CONFIG_USER_NS_UNPRIVILEGED
++int unprivileged_userns_clone = 1;
++#else
++int unprivileged_userns_clone;
++#endif
++
+ static struct kmem_cache *user_ns_cachep __read_mostly;
+ static DEFINE_MUTEX(userns_state_mutex);
+
+--
+cgit v1.2.1-1-g437b
+
diff --git a/0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_special_driver-list.patch b/0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_special_driver-list.patch
new file mode 100644
index 000000000000..49bbf222a828
--- /dev/null
+++ b/0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_special_driver-list.patch
@@ -0,0 +1,36 @@
+From 2dad55f373693e9e808fbdc836614162924990a2 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Felix=20H=C3=A4dicke?= <felixhaedicke@web.de>
+Date: Thu, 19 Nov 2020 09:22:32 +0100
+Subject: HID: quirks: Add Apple Magic Trackpad 2 to hid_have_special_driver
+ list
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The Apple Magic Trackpad 2 is handled by the magicmouse driver. And
+there were severe stability issues when both drivers (hid-generic and
+hid-magicmouse) were loaded for this device.
+
+Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=210241
+
+Signed-off-by: Felix Hädicke <felixhaedicke@web.de>
+---
+ drivers/hid/hid-quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
+index bf7ecab5d9e5..142e9dae2837 100644
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -478,6 +478,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
+ #if IS_ENABLED(CONFIG_HID_MAGICMOUSE)
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
++ { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) },
+ #endif
+ #if IS_ENABLED(CONFIG_HID_MAYFLASH)
+ { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) },
+--
+cgit v1.2.3-1-gf6bb5
+
diff --git a/0101-i2c-nuvoton-nc677x-hwmon-driver.patch b/0101-i2c-nuvoton-nc677x-hwmon-driver.patch
new file mode 100644
index 000000000000..85f86d0da22d
--- /dev/null
+++ b/0101-i2c-nuvoton-nc677x-hwmon-driver.patch
@@ -0,0 +1,745 @@
+From 994279ebfc0d19e185792fb11cacb63e6750e22e Mon Sep 17 00:00:00 2001
+From: "Jan Alexander Steffens (heftig)" <heftig@archlinux.org>
+Date: Mon, 3 Aug 2020 21:18:53 +0200
+Subject: [PATCH] ZEN: Add OpenRGB patches
+
+Squashed commit of the following:
+
+commit 942ded8f8652a4b4e6b46d04938bb66f1eac4c78
+Author: Steven Barrett <steven@liquorix.net>
+Date: Sat Jul 4 21:28:54 2020 -0500
+
+ openrgb: Deduplicate piix4 setup for HUDSON2/KERNCZ SMBUS
+
+ In the original OpenRGB patches, the initialization code for CZ
+ secondary SMBus controllers was copied. Later, an upstream commit
+ landed in 5.7 stable that combined the initialization code for both
+ primary/secondary smbus channels.
+
+ Combine the initialization code ahead of time so upstream merges
+ correctly with OpenRGB.
+
+ Fixes: https://github.com/zen-kernel/zen-kernel/issues/176
+
+commit a65e3ecf90b24fd44689cc0713af602965ffaf4e
+Author: Steven Barrett <steven@liquorix.net>
+Date: Wed Jun 17 14:24:20 2020 -0500
+
+ Add OpenRGB patch - 0c45e26c
+
+ Source:
+ https://gitlab.com/CalcProgrammer1/OpenRGB/-/raw/master/OpenRGB.patch
+
+ History:
+ https://gitlab.com/CalcProgrammer1/OpenRGB/-/commits/master/OpenRGB.patch
+---
+ drivers/i2c/busses/Kconfig | 9 +
+ drivers/i2c/busses/Makefile | 1 +
+ drivers/i2c/busses/i2c-nct6775.c | 647 +++++++++++++++++++++++++++++++
+ drivers/i2c/busses/i2c-piix4.c | 4 +-
+ 4 files changed, 659 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/i2c/busses/i2c-nct6775.c
+
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 735bf31a3fdff..3bf00363cd769 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -217,6 +217,15 @@ config I2C_CHT_WC
+ combined with a FUSB302 Type-C port-controller as such it is advised
+ to also select CONFIG_TYPEC_FUSB302=m.
+
++config I2C_NCT6775
++ tristate "Nuvoton NCT6775 and compatible SMBus controller"
++ help
++ If you say yes to this option, support will be included for the
++ Nuvoton NCT6775 and compatible SMBus controllers.
++
++ This driver can also be built as a module. If so, the module
++ will be called i2c-nct6775.
++
+ config I2C_NFORCE2
+ tristate "Nvidia nForce2, nForce3 and nForce4"
+ depends on PCI
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index 306d5dc3f417f..7e75d45c64e5b 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -17,6 +17,7 @@ obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o
+ obj-$(CONFIG_I2C_I801) += i2c-i801.o
+ obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
+ obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
++obj-$(CONFIG_I2C_NCT6775) += i2c-nct6775.o
+ obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
+ obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o
+ obj-$(CONFIG_I2C_NVIDIA_GPU) += i2c-nvidia-gpu.o
+diff --git a/drivers/i2c/busses/i2c-nct6775.c b/drivers/i2c/busses/i2c-nct6775.c
+new file mode 100644
+index 0000000000000..0462f09520431
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-nct6775.c
+@@ -0,0 +1,647 @@
++/*
++ * i2c-nct6775 - Driver for the SMBus master functionality of
++ * Nuvoton NCT677x Super-I/O chips
++ *
++ * Copyright (C) 2019 Adam Honse <calcprogrammer1@gmail.com>
++ *
++ * Derived from nct6775 hwmon driver
++ * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/jiffies.h>
++#include <linux/platform_device.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/hwmon-vid.h>
++#include <linux/err.h>
++#include <linux/mutex.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/i2c.h>
++#include <linux/acpi.h>
++#include <linux/bitops.h>
++#include <linux/dmi.h>
++#include <linux/io.h>
++#include <linux/nospec.h>
++
++#define DRVNAME "i2c-nct6775"
++
++/* Nuvoton SMBus address offsets */
++#define SMBHSTDAT (0 + nuvoton_nct6793d_smba)
++#define SMBBLKSZ (1 + nuvoton_nct6793d_smba)
++#define SMBHSTCMD (2 + nuvoton_nct6793d_smba)
++#define SMBHSTIDX (3 + nuvoton_nct6793d_smba) //Index field is the Command field on other controllers
++#define SMBHSTCTL (4 + nuvoton_nct6793d_smba)
++#define SMBHSTADD (5 + nuvoton_nct6793d_smba)
++#define SMBHSTERR (9 + nuvoton_nct6793d_smba)
++#define SMBHSTSTS (0xE + nuvoton_nct6793d_smba)
++
++/* Command register */
++#define NCT6793D_READ_BYTE 0
++#define NCT6793D_READ_WORD 1
++#define NCT6793D_READ_BLOCK 2
++#define NCT6793D_BLOCK_WRITE_READ_PROC_CALL 3
++#define NCT6793D_PROC_CALL 4
++#define NCT6793D_WRITE_BYTE 8
++#define NCT6793D_WRITE_WORD 9
++#define NCT6793D_WRITE_BLOCK 10
++
++/* Control register */
++#define NCT6793D_MANUAL_START 128
++#define NCT6793D_SOFT_RESET 64
++
++/* Error register */
++#define NCT6793D_NO_ACK 32
++
++/* Status register */
++#define NCT6793D_FIFO_EMPTY 1
++#define NCT6793D_FIFO_FULL 2
++#define NCT6793D_MANUAL_ACTIVE 4
++
++#define NCT6775_LD_SMBUS 0x0B
++
++/* Other settings */
++#define MAX_RETRIES 400
++
++enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793,
++ nct6795, nct6796, nct6798 };
++
++struct nct6775_sio_data {
++ int sioreg;
++ enum kinds kind;
++};
++
++/* used to set data->name = nct6775_device_names[data->sio_kind] */
++static const char * const nct6775_device_names[] = {
++ "nct6106",
++ "nct6775",
++ "nct6776",
++ "nct6779",
++ "nct6791",
++ "nct6792",
++ "nct6793",
++ "nct6795",
++ "nct6796",
++ "nct6798",
++};
++
++static const char * const nct6775_sio_names[] __initconst = {
++ "NCT6106D",
++ "NCT6775F",
++ "NCT6776D/F",
++ "NCT6779D",
++ "NCT6791D",
++ "NCT6792D",
++ "NCT6793D",
++ "NCT6795D",
++ "NCT6796D",
++ "NCT6798D",
++};
++
++#define SIO_REG_LDSEL 0x07 /* Logical device select */
++#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
++#define SIO_REG_SMBA 0x62 /* SMBus base address register */
++
++#define SIO_NCT6106_ID 0xc450
++#define SIO_NCT6775_ID 0xb470
++#define SIO_NCT6776_ID 0xc330
++#define SIO_NCT6779_ID 0xc560
++#define SIO_NCT6791_ID 0xc800
++#define SIO_NCT6792_ID 0xc910
++#define SIO_NCT6793_ID 0xd120
++#define SIO_NCT6795_ID 0xd350
++#define SIO_NCT6796_ID 0xd420
++#define SIO_NCT6798_ID 0xd428
++#define SIO_ID_MASK 0xFFF0
++
++static inline void
++superio_outb(int ioreg, int reg, int val)
++{
++ outb(reg, ioreg);
++ outb(val, ioreg + 1);
++}
++
++static inline int
++superio_inb(int ioreg, int reg)
++{
++ outb(reg, ioreg);
++ return inb(ioreg + 1);
++}
++
++static inline void
++superio_select(int ioreg, int ld)
++{
++ outb(SIO_REG_LDSEL, ioreg);
++ outb(ld, ioreg + 1);
++}
++
++static inline int
++superio_enter(int ioreg)
++{
++ /*
++ * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
++ */
++ if (!request_muxed_region(ioreg, 2, DRVNAME))
++ return -EBUSY;
++
++ outb(0x87, ioreg);
++ outb(0x87, ioreg);
++
++ return 0;
++}
++
++static inline void
++superio_exit(int ioreg)
++{
++ outb(0xaa, ioreg);
++ outb(0x02, ioreg);
++ outb(0x02, ioreg + 1);
++ release_region(ioreg, 2);
++}
++
++/*
++ * ISA constants
++ */
++
++#define IOREGION_ALIGNMENT (~7)
++#define IOREGION_LENGTH 2
++#define ADDR_REG_OFFSET 0
++#define DATA_REG_OFFSET 1
++
++#define NCT6775_REG_BANK 0x4E
++#define NCT6775_REG_CONFIG 0x40
++
++static struct i2c_adapter *nct6775_adapter;
++
++struct i2c_nct6775_adapdata {
++ unsigned short smba;
++};
++
++/* Return negative errno on error. */
++static s32 nct6775_access(struct i2c_adapter * adap, u16 addr,
++ unsigned short flags, char read_write,
++ u8 command, int size, union i2c_smbus_data * data)
++{
++ struct i2c_nct6775_adapdata *adapdata = i2c_get_adapdata(adap);
++ unsigned short nuvoton_nct6793d_smba = adapdata->smba;
++ int i, len, cnt;
++ union i2c_smbus_data tmp_data;
++ int timeout = 0;
++
++ tmp_data.word = 0;
++ cnt = 0;
++ len = 0;
++
++ outb_p(NCT6793D_SOFT_RESET, SMBHSTCTL);
++
++ switch (size) {
++ case I2C_SMBUS_QUICK:
++ outb_p((addr << 1) | read_write,
++ SMBHSTADD);
++ break;
++ case I2C_SMBUS_BYTE_DATA:
++ tmp_data.byte = data->byte;
++ case I2C_SMBUS_BYTE:
++ outb_p((addr << 1) | read_write,
++ SMBHSTADD);
++ outb_p(command, SMBHSTIDX);
++ if (read_write == I2C_SMBUS_WRITE) {
++ outb_p(tmp_data.byte, SMBHSTDAT);
++ outb_p(NCT6793D_WRITE_BYTE, SMBHSTCMD);
++ }
++ else {
++ outb_p(NCT6793D_READ_BYTE, SMBHSTCMD);
++ }
++ break;
++ case I2C_SMBUS_WORD_DATA:
++ outb_p((addr << 1) | read_write,
++ SMBHSTADD);
++ outb_p(command, SMBHSTIDX);
++ if (read_write == I2C_SMBUS_WRITE) {
++ outb_p(data->word & 0xff, SMBHSTDAT);
++ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT);
++ outb_p(NCT6793D_WRITE_WORD, SMBHSTCMD);
++ }
++ else {
++ outb_p(NCT6793D_READ_WORD, SMBHSTCMD);
++ }
++ break;
++ case I2C_SMBUS_BLOCK_DATA:
++ outb_p((addr << 1) | read_write,
++ SMBHSTADD);
++ outb_p(command, SMBHSTIDX);
++ if (read_write == I2C_SMBUS_WRITE) {
++ len = data->block[0];
++ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
++ return -EINVAL;
++ outb_p(len, SMBBLKSZ);
++
++ cnt = 1;
++ if (len >= 4) {
++ for (i = cnt; i <= 4; i++) {
++ outb_p(data->block[i], SMBHSTDAT);
++ }
++
++ len -= 4;
++ cnt += 4;
++ }
++ else {
++ for (i = cnt; i <= len; i++ ) {
++ outb_p(data->block[i], SMBHSTDAT);
++ }
++
++ len = 0;
++ }
++
++ outb_p(NCT6793D_WRITE_BLOCK, SMBHSTCMD);
++ }
++ else {
++ return -ENOTSUPP;
++ }
++ break;
++ default:
++ dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
++ return -EOPNOTSUPP;
++ }
++
++ outb_p(NCT6793D_MANUAL_START, SMBHSTCTL);
++
++ while ((size == I2C_SMBUS_BLOCK_DATA) && (len > 0)) {
++ if (read_write == I2C_SMBUS_WRITE) {
++ timeout = 0;
++ while ((inb_p(SMBHSTSTS) & NCT6793D_FIFO_EMPTY) == 0)
++ {
++ if(timeout > MAX_RETRIES)
++ {
++ return -ETIMEDOUT;
++ }
++ usleep_range(250, 500);
++ timeout++;
++ }
++
++ //Load more bytes into FIFO
++ if (len >= 4) {
++ for (i = cnt; i <= (cnt + 4); i++) {
++ outb_p(data->block[i], SMBHSTDAT);
++ }
++
++ len -= 4;
++ cnt += 4;
++ }
++ else {
++ for (i = cnt; i <= (cnt + len); i++) {
++ outb_p(data->block[i], SMBHSTDAT);
++ }
++
++ len = 0;
++ }
++ }
++ else {
++ return -ENOTSUPP;
++ }
++
++ }
++
++ //wait for manual mode to complete
++ timeout = 0;
++ while ((inb_p(SMBHSTSTS) & NCT6793D_MANUAL_ACTIVE) != 0)
++ {
++ if(timeout > MAX_RETRIES)
++ {
++ return -ETIMEDOUT;
++ }
++ usleep_range(250, 500);
++ timeout++;
++ }
++
++ if ((inb_p(SMBHSTERR) & NCT6793D_NO_ACK) != 0) {
++ return -ENXIO;
++ }
++ else if ((read_write == I2C_SMBUS_WRITE) || (size == I2C_SMBUS_QUICK)) {
++ return 0;
++ }
++
++ switch (size) {
++ case I2C_SMBUS_QUICK:
++ case I2C_SMBUS_BYTE_DATA:
++ data->byte = inb_p(SMBHSTDAT);
++ break;
++ case I2C_SMBUS_WORD_DATA:
++ data->word = inb_p(SMBHSTDAT) + (inb_p(SMBHSTDAT) << 8);
++ break;
++ }
++ return 0;
++}
++
++static u32 nct6775_func(struct i2c_adapter *adapter)
++{
++ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
++ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
++ I2C_FUNC_SMBUS_BLOCK_DATA;
++}
++
++static const struct i2c_algorithm smbus_algorithm = {
++ .smbus_xfer = nct6775_access,
++ .functionality = nct6775_func,
++};
++
++static int nct6775_add_adapter(unsigned short smba, const char *name, struct i2c_adapter **padap)
++{
++ struct i2c_adapter *adap;
++ struct i2c_nct6775_adapdata *adapdata;
++ int retval;
++
++ adap = kzalloc(sizeof(*adap), GFP_KERNEL);
++ if (adap == NULL) {
++ return -ENOMEM;
++ }
++
++ adap->owner = THIS_MODULE;
++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
++ adap->algo = &smbus_algorithm;
++
++ adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL);
++ if (adapdata == NULL) {
++ kfree(adap);
++ return -ENOMEM;
++ }
++
++ adapdata->smba = smba;
++
++ snprintf(adap->name, sizeof(adap->name),
++ "SMBus NCT67xx adapter%s at %04x", name, smba);
++
++ i2c_set_adapdata(adap, adapdata);
++
++ retval = i2c_add_adapter(adap);
++ if (retval) {
++ kfree(adapdata);
++ kfree(adap);
++ return retval;
++ }
++
++ *padap = adap;
++ return 0;
++}
++
++static void nct6775_remove_adapter(struct i2c_adapter *adap)
++{
++ struct i2c_nct6775_adapdata *adapdata = i2c_get_adapdata(adap);
++
++ if (adapdata->smba) {
++ i2c_del_adapter(adap);
++ kfree(adapdata);
++ kfree(adap);
++ }
++}
++
++//static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume);
++
++/*
++ * when Super-I/O functions move to a separate file, the Super-I/O
++ * bus will manage the lifetime of the device and this module will only keep
++ * track of the nct6775 driver. But since we use platform_device_alloc(), we
++ * must keep track of the device
++ */
++static struct platform_device *pdev[2];
++
++static int nct6775_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct nct6775_sio_data *sio_data = dev_get_platdata(dev);
++ struct resource *res;
++
++ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
++ DRVNAME))
++ return -EBUSY;
++
++ switch (sio_data->kind) {
++ case nct6791:
++ case nct6792:
++ case nct6793:
++ case nct6795:
++ case nct6796:
++ case nct6798:
++ nct6775_add_adapter(res->start, "", &nct6775_adapter);
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ return 0;
++}
++/*
++static void nct6791_enable_io_mapping(int sioaddr)
++{
++ int val;
++
++ val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
++ if (val & 0x10) {
++ pr_info("Enabling hardware monitor logical device mappings.\n");
++ superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
++ val & ~0x10);
++ }
++}*/
++
++static struct platform_driver i2c_nct6775_driver = {
++ .driver = {
++ .name = DRVNAME,
++// .pm = &nct6775_dev_pm_ops,
++ },
++ .probe = nct6775_probe,
++};
++
++static void __exit i2c_nct6775_exit(void)
++{
++ int i;
++
++ if(nct6775_adapter)
++ nct6775_remove_adapter(nct6775_adapter);
++
++ for (i = 0; i < ARRAY_SIZE(pdev); i++) {
++ if (pdev[i])
++ platform_device_unregister(pdev[i]);
++ }
++ platform_driver_unregister(&i2c_nct6775_driver);
++}
++
++/* nct6775_find() looks for a '627 in the Super-I/O config space */
++static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
++{
++ u16 val;
++ int err;
++ int addr;
++
++ err = superio_enter(sioaddr);
++ if (err)
++ return err;
++
++ val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) |
++ superio_inb(sioaddr, SIO_REG_DEVID + 1);
++
++ switch (val & SIO_ID_MASK) {
++ case SIO_NCT6106_ID:
++ sio_data->kind = nct6106;
++ break;
++ case SIO_NCT6775_ID:
++ sio_data->kind = nct6775;
++ break;
++ case SIO_NCT6776_ID:
++ sio_data->kind = nct6776;
++ break;
++ case SIO_NCT6779_ID:
++ sio_data->kind = nct6779;
++ break;
++ case SIO_NCT6791_ID:
++ sio_data->kind = nct6791;
++ break;
++ case SIO_NCT6792_ID:
++ sio_data->kind = nct6792;
++ break;
++ case SIO_NCT6793_ID:
++ sio_data->kind = nct6793;
++ break;
++ case SIO_NCT6795_ID:
++ sio_data->kind = nct6795;
++ break;
++ case SIO_NCT6796_ID:
++ sio_data->kind = nct6796;
++ break;
++ case SIO_NCT6798_ID:
++ sio_data->kind = nct6798;
++ break;
++ default:
++ if (val != 0xffff)
++ pr_debug("unsupported chip ID: 0x%04x\n", val);
++ superio_exit(sioaddr);
++ return -ENODEV;
++ }
++
++ /* We have a known chip, find the SMBus I/O address */
++ superio_select(sioaddr, NCT6775_LD_SMBUS);
++ val = (superio_inb(sioaddr, SIO_REG_SMBA) << 8)
++ | superio_inb(sioaddr, SIO_REG_SMBA + 1);
++ addr = val & IOREGION_ALIGNMENT;
++ if (addr == 0) {
++ pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
++ superio_exit(sioaddr);
++ return -ENODEV;
++ }
++
++ //if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
++ // sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
++ // sio_data->kind == nct6796)
++ // nct6791_enable_io_mapping(sioaddr);
++
++ superio_exit(sioaddr);
++ pr_info("Found %s or compatible chip at %#x:%#x\n",
++ nct6775_sio_names[sio_data->kind], sioaddr, addr);
++ sio_data->sioreg = sioaddr;
++
++ return addr;
++}
++
++static int __init i2c_nct6775_init(void)
++{
++ int i, err;
++ bool found = false;
++ int address;
++ struct resource res;
++ struct nct6775_sio_data sio_data;
++ int sioaddr[2] = { 0x2e, 0x4e };
++
++ err = platform_driver_register(&i2c_nct6775_driver);
++ if (err)
++ return err;
++
++ /*
++ * initialize sio_data->kind and sio_data->sioreg.
++ *
++ * when Super-I/O functions move to a separate file, the Super-I/O
++ * driver will probe 0x2e and 0x4e and auto-detect the presence of a
++ * nct6775 hardware monitor, and call probe()
++ */
++ for (i = 0; i < ARRAY_SIZE(pdev); i++) {
++ address = nct6775_find(sioaddr[i], &sio_data);
++ if (address <= 0)
++ continue;
++
++ found = true;
++
++ pdev[i] = platform_device_alloc(DRVNAME, address);
++ if (!pdev[i]) {
++ err = -ENOMEM;
++ goto exit_device_unregister;
++ }
++
++ err = platform_device_add_data(pdev[i], &sio_data,
++ sizeof(struct nct6775_sio_data));
++ if (err)
++ goto exit_device_put;
++
++ memset(&res, 0, sizeof(res));
++ res.name = DRVNAME;
++ res.start = address;
++ res.end = address + IOREGION_LENGTH - 1;
++ res.flags = IORESOURCE_IO;
++
++ err = acpi_check_resource_conflict(&res);
++ if (err) {
++ platform_device_put(pdev[i]);
++ pdev[i] = NULL;
++ continue;
++ }
++
++ err = platform_device_add_resources(pdev[i], &res, 1);
++ if (err)
++ goto exit_device_put;
++
++ /* platform_device_add calls probe() */
++ err = platform_device_add(pdev[i]);
++ if (err)
++ goto exit_device_put;
++ }
++ if (!found) {
++ err = -ENODEV;
++ goto exit_unregister;
++ }
++
++ return 0;
++
++exit_device_put:
++ platform_device_put(pdev[i]);
++exit_device_unregister:
++ while (--i >= 0) {
++ if (pdev[i])
++ platform_device_unregister(pdev[i]);
++ }
++exit_unregister:
++ platform_driver_unregister(&i2c_nct6775_driver);
++ return err;
++}
++
++MODULE_AUTHOR("Adam Honse <calcprogrammer1@gmail.com>");
++MODULE_DESCRIPTION("SMBus driver for NCT6775F and compatible chips");
++MODULE_LICENSE("GPL");
++
++module_init(i2c_nct6775_init);
++module_exit(i2c_nct6775_exit);
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+index 69740a4ff1db2..b70738fbe72a4 100644
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -467,11 +467,11 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter)
+ if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */
+ usleep_range(2000, 2100);
+ else
+- usleep_range(250, 500);
++ usleep_range(25, 50);
+
+ while ((++timeout < MAX_TIMEOUT) &&
+ ((temp = inb_p(SMBHSTSTS)) & 0x01))
+- usleep_range(250, 500);
++ usleep_range(25, 50);
+
+ /* If the SMBus is still busy, we give up */
+ if (timeout == MAX_TIMEOUT) {
diff --git a/0102-iomap-iomap_bmap-should-accept-unwritten-maps.patch b/0102-iomap-iomap_bmap-should-accept-unwritten-maps.patch
new file mode 100644
index 000000000000..9ca50277e88c
--- /dev/null
+++ b/0102-iomap-iomap_bmap-should-accept-unwritten-maps.patch
@@ -0,0 +1,38 @@
+From: Yuxuan Shui <yshuiv7@gmail.com>
+To: viro@zeniv.linux.org.uk
+Cc: linux-fsdevel@vger.kernel.org, Yuxuan Shui <yshuiv7@gmail.com>
+Subject: [PATCH] iomap: iomap_bmap should accept unwritten maps
+Date: Tue, 5 May 2020 19:36:08 +0100
+Message-ID: <20200505183608.10280-1-yshuiv7@gmail.com> (raw)
+
+commit ac58e4fb03f9d111d733a4ad379d06eef3a24705 moved ext4_bmap from
+generic_block_bmap to iomap_bmap, this introduced a regression which
+prevents some user from using previously working swapfiles. The kernel
+will complain about holes while there is none.
+
+What is happening here is that the swapfile has unwritten mappings,
+which is rejected by iomap_bmap, but was accepted by ext4_get_block.
+
+This commit makes sure iomap_bmap would accept unwritten mappings as
+well.
+
+Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
+---
+ fs/iomap/fiemap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/iomap/fiemap.c b/fs/iomap/fiemap.c
+index d55e8f491a5e..fb488dcfa8c7 100644
+--- a/fs/iomap/fiemap.c
++++ b/fs/iomap/fiemap.c
+@@ -115,7 +115,7 @@ iomap_bmap_actor(struct inode *inode, loff_t pos, loff_t length,
+ {
+ sector_t *bno = data, addr;
+
+- if (iomap->type == IOMAP_MAPPED) {
++ if (iomap->type == IOMAP_MAPPED || iomap->type == IOMAP_UNWRITTEN) {
+ addr = (pos - iomap->offset + iomap->addr) >> inode->i_blkbits;
+ *bno = addr;
+ }
+--
+2.26.2
diff --git a/0103-futex.patch b/0103-futex.patch
new file mode 100644
index 000000000000..d33f488ae054
--- /dev/null
+++ b/0103-futex.patch
@@ -0,0 +1,9811 @@
+From 4dc2913212c08c6970f6e8971fd23b6328982f94 Mon Sep 17 00:00:00 2001
+From: Piotr Gorski <lucjan.lucjanov@gmail.com>
+Date: Mon, 1 Nov 2021 12:11:04 +0100
+Subject: [PATCH] futex: resync from gitlab.collabora.com
+
+Signed-off-by: Piotr Gorski <lucjan.lucjanov@gmail.com>
+---
+ Documentation/userspace-api/futex2.rst | 86 +
+ Documentation/userspace-api/index.rst | 1 +
+ MAINTAINERS | 3 +-
+ arch/arm/tools/syscall.tbl | 1 +
+ arch/arm64/include/asm/unistd.h | 2 +-
+ arch/arm64/include/asm/unistd32.h | 2 +
+ arch/x86/entry/syscalls/syscall_32.tbl | 1 +
+ arch/x86/entry/syscalls/syscall_64.tbl | 1 +
+ include/linux/syscalls.h | 7 +-
+ include/uapi/asm-generic/unistd.h | 5 +-
+ include/uapi/linux/futex.h | 25 +
+ kernel/Makefile | 2 +-
+ kernel/futex.c | 4272 -----------------
+ kernel/futex/Makefile | 3 +
+ kernel/futex/core.c | 1176 +++++
+ kernel/futex/futex.h | 295 ++
+ kernel/futex/pi.c | 1233 +++++
+ kernel/futex/requeue.c | 897 ++++
+ kernel/futex/syscalls.c | 396 ++
+ kernel/futex/waitwake.c | 708 +++
+ kernel/sys_ni.c | 3 +-
+ .../selftests/futex/functional/.gitignore | 1 +
+ .../selftests/futex/functional/Makefile | 3 +-
+ .../futex/functional/futex_wait_timeout.c | 21 +-
+ .../futex/functional/futex_wait_wouldblock.c | 41 +-
+ .../selftests/futex/functional/futex_waitv.c | 237 +
+ .../testing/selftests/futex/functional/run.sh | 3 +
+ .../selftests/futex/include/futex2test.h | 22 +
+ 28 files changed, 5163 insertions(+), 4284 deletions(-)
+ create mode 100644 Documentation/userspace-api/futex2.rst
+ delete mode 100644 kernel/futex.c
+ create mode 100644 kernel/futex/Makefile
+ create mode 100644 kernel/futex/core.c
+ create mode 100644 kernel/futex/futex.h
+ create mode 100644 kernel/futex/pi.c
+ create mode 100644 kernel/futex/requeue.c
+ create mode 100644 kernel/futex/syscalls.c
+ create mode 100644 kernel/futex/waitwake.c
+ create mode 100644 tools/testing/selftests/futex/functional/futex_waitv.c
+ create mode 100644 tools/testing/selftests/futex/include/futex2test.h
+
+diff --git a/Documentation/userspace-api/futex2.rst b/Documentation/userspace-api/futex2.rst
+new file mode 100644
+index 000000000..7d37409df
+--- /dev/null
++++ b/Documentation/userspace-api/futex2.rst
+@@ -0,0 +1,86 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++======
++futex2
++======
++
++:Author: André Almeida <andrealmeid@collabora.com>
++
++futex, or fast user mutex, is a set of syscalls to allow userspace to create
++performant synchronization mechanisms, such as mutexes, semaphores and
++conditional variables in userspace. C standard libraries, like glibc, uses it
++as a means to implement more high level interfaces like pthreads.
++
++futex2 is a followup version of the initial futex syscall, designed to overcome
++limitations of the original interface.
++
++User API
++========
++
++``futex_waitv()``
++-----------------
++
++Wait on an array of futexes, wake on any::
++
++ futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes,
++ unsigned int flags, struct timespec *timeout, clockid_t clockid)
++
++ struct futex_waitv {
++ __u64 val;
++ __u64 uaddr;
++ __u32 flags;
++ __u32 __reserved;
++ };
++
++Userspace sets an array of struct futex_waitv (up to a max of 128 entries),
++using ``uaddr`` for the address to wait for, ``val`` for the expected value
++and ``flags`` to specify the type (e.g. private) and size of futex.
++``__reserved`` needs to be 0, but it can be used for future extension. The
++pointer for the first item of the array is passed as ``waiters``. An invalid
++address for ``waiters`` or for any ``uaddr`` returns ``-EFAULT``.
++
++If userspace has 32-bit pointers, it should do a explicit cast to make sure
++the upper bits are zeroed. ``uintptr_t`` does the tricky and it works for
++both 32/64-bit pointers.
++
++``nr_futexes`` specifies the size of the array. Numbers out of [1, 128]
++interval will make the syscall return ``-EINVAL``.
++
++The ``flags`` argument of the syscall needs to be 0, but it can be used for
++future extension.
++
++For each entry in ``waiters`` array, the current value at ``uaddr`` is compared
++to ``val``. If it's different, the syscall undo all the work done so far and
++return ``-EAGAIN``. If all tests and verifications succeeds, syscall waits until
++one of the following happens:
++
++- The timeout expires, returning ``-ETIMEOUT``.
++- A signal was sent to the sleeping task, returning ``-ERESTARTSYS``.
++- Some futex at the list was awaken, returning the index of some waked futex.
++
++An example of how to use the interface can be found at ``tools/testing/selftests/futex/functional/futex_waitv.c``.
++
++Timeout
++-------
++
++``struct timespec *timeout`` argument is an optional argument that points to an
++absolute timeout. You need to specify the type of clock being used at
++``clockid`` argument. ``CLOCK_MONOTONIC`` and ``CLOCK_REALTIME`` are supported.
++This syscall accepts only 64bit timespec structs.
++
++Types of futex
++--------------
++
++A futex can be either private or shared. Private is used for processes that
++shares the same memory space and the virtual address of the futex will be the
++same for all processes. This allows for optimizations in the kernel. To use
++private futexes, it's necessary to specify ``FUTEX_PRIVATE_FLAG`` in the futex
++flag. For processes that doesn't share the same memory space and therefore can
++have different virtual addresses for the same futex (using, for instance, a
++file-backed shared memory) requires different internal mechanisms to be get
++properly enqueued. This is the default behavior, and it works with both private
++and shared futexes.
++
++Futexes can be of different sizes: 8, 16, 32 or 64 bits. Currently, the only
++supported one is 32 bit sized futex, and it need to be specified using
++``FUTEX_32`` flag.
+diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst
+index c432be070..a61eac0c7 100644
+--- a/Documentation/userspace-api/index.rst
++++ b/Documentation/userspace-api/index.rst
+@@ -28,6 +28,7 @@ place where this information is gathered.
+ media/index
+ sysfs-platform_profile
+ vduse
++ futex2
+
+ .. only:: subproject and html
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 3b79fd441..dd165835f 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -7737,6 +7737,7 @@ M: Ingo Molnar <mingo@redhat.com>
+ R: Peter Zijlstra <peterz@infradead.org>
+ R: Darren Hart <dvhart@infradead.org>
+ R: Davidlohr Bueso <dave@stgolabs.net>
++R: André Almeida <andrealmeid@collabora.com>
+ L: linux-kernel@vger.kernel.org
+ S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
+@@ -7744,7 +7745,7 @@ F: Documentation/locking/*futex*
+ F: include/asm-generic/futex.h
+ F: include/linux/futex.h
+ F: include/uapi/linux/futex.h
+-F: kernel/futex.c
++F: kernel/futex/*
+ F: tools/perf/bench/futex*
+ F: tools/testing/selftests/futex/
+
+diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
+index e842209e1..543100151 100644
+--- a/arch/arm/tools/syscall.tbl
++++ b/arch/arm/tools/syscall.tbl
+@@ -462,3 +462,4 @@
+ 446 common landlock_restrict_self sys_landlock_restrict_self
+ # 447 reserved for memfd_secret
+ 448 common process_mrelease sys_process_mrelease
++449 common futex_waitv sys_futex_waitv
+diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
+index 3cb206aea..6bdb5f5db 100644
+--- a/arch/arm64/include/asm/unistd.h
++++ b/arch/arm64/include/asm/unistd.h
+@@ -38,7 +38,7 @@
+ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
+ #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
+
+-#define __NR_compat_syscalls 449
++#define __NR_compat_syscalls 450
+ #endif
+
+ #define __ARCH_WANT_SYS_CLONE
+diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
+index 844f6ae58..41ea1195e 100644
+--- a/arch/arm64/include/asm/unistd32.h
++++ b/arch/arm64/include/asm/unistd32.h
+@@ -903,6 +903,8 @@ __SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule)
+ __SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
+ #define __NR_process_mrelease 448
+ __SYSCALL(__NR_process_mrelease, sys_process_mrelease)
++#define __NR_futex_waitv 449
++__SYSCALL(__NR_futex_waitv, sys_futex_waitv)
+
+ /*
+ * Please add new compat syscalls above this comment and update
+diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
+index 960a021d5..7e2554369 100644
+--- a/arch/x86/entry/syscalls/syscall_32.tbl
++++ b/arch/x86/entry/syscalls/syscall_32.tbl
+@@ -453,3 +453,4 @@
+ 446 i386 landlock_restrict_self sys_landlock_restrict_self
+ 447 i386 memfd_secret sys_memfd_secret
+ 448 i386 process_mrelease sys_process_mrelease
++449 i386 futex_waitv sys_futex_waitv
+diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
+index 18b5500ea..fe8f8dd15 100644
+--- a/arch/x86/entry/syscalls/syscall_64.tbl
++++ b/arch/x86/entry/syscalls/syscall_64.tbl
+@@ -370,6 +370,7 @@
+ 446 common landlock_restrict_self sys_landlock_restrict_self
+ 447 common memfd_secret sys_memfd_secret
+ 448 common process_mrelease sys_process_mrelease
++449 common futex_waitv sys_futex_waitv
+
+ #
+ # Due to a historical design error, certain syscalls are numbered differently
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 252243c77..528a478db 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -58,6 +58,7 @@ struct mq_attr;
+ struct compat_stat;
+ struct old_timeval32;
+ struct robust_list_head;
++struct futex_waitv;
+ struct getcpu_cache;
+ struct old_linux_dirent;
+ struct perf_event_attr;
+@@ -610,7 +611,7 @@ asmlinkage long sys_waitid(int which, pid_t pid,
+ asmlinkage long sys_set_tid_address(int __user *tidptr);
+ asmlinkage long sys_unshare(unsigned long unshare_flags);
+
+-/* kernel/futex.c */
++/* kernel/futex/syscalls.c */
+ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
+ const struct __kernel_timespec __user *utime,
+ u32 __user *uaddr2, u32 val3);
+@@ -623,6 +624,10 @@ asmlinkage long sys_get_robust_list(int pid,
+ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
+ size_t len);
+
++asmlinkage long sys_futex_waitv(struct futex_waitv *waiters,
++ unsigned int nr_futexes, unsigned int flags,
++ struct __kernel_timespec __user *timeout, clockid_t clockid);
++
+ /* kernel/hrtimer.c */
+ asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp,
+ struct __kernel_timespec __user *rmtp);
+diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
+index 1c5fb86d4..4557a8b60 100644
+--- a/include/uapi/asm-generic/unistd.h
++++ b/include/uapi/asm-generic/unistd.h
+@@ -880,8 +880,11 @@ __SYSCALL(__NR_memfd_secret, sys_memfd_secret)
+ #define __NR_process_mrelease 448
+ __SYSCALL(__NR_process_mrelease, sys_process_mrelease)
+
++#define __NR_futex_waitv 449
++__SYSCALL(__NR_futex_waitv, sys_futex_waitv)
++
+ #undef __NR_syscalls
+-#define __NR_syscalls 449
++#define __NR_syscalls 450
+
+ /*
+ * 32 bit systems traditionally used different
+diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h
+index 235e5b2fa..71a5df8d2 100644
+--- a/include/uapi/linux/futex.h
++++ b/include/uapi/linux/futex.h
+@@ -43,6 +43,31 @@
+ #define FUTEX_CMP_REQUEUE_PI_PRIVATE (FUTEX_CMP_REQUEUE_PI | \
+ FUTEX_PRIVATE_FLAG)
+
++/*
++ * Flags to specify the bit length of the futex word for futex2 syscalls.
++ * Currently, only 32 is supported.
++ */
++#define FUTEX_32 2
++
++/*
++ * Max numbers of elements in a futex_waitv array
++ */
++#define FUTEX_WAITV_MAX 128
++
++/**
++ * struct futex_waitv - A waiter for vectorized wait
++ * @val: Expected value at uaddr
++ * @uaddr: User address to wait on
++ * @flags: Flags for this waiter
++ * @__reserved: Reserved member to preserve data alignment. Should be 0.
++ */
++struct futex_waitv {
++ __u64 val;
++ __u64 uaddr;
++ __u32 flags;
++ __u32 __reserved;
++};
++
+ /*
+ * Support for robust futexes: the kernel cleans up held futexes at
+ * thread exit time.
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 4df609be4..3f6ab5d50 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -59,7 +59,7 @@ obj-$(CONFIG_FREEZER) += freezer.o
+ obj-$(CONFIG_PROFILING) += profile.o
+ obj-$(CONFIG_STACKTRACE) += stacktrace.o
+ obj-y += time/
+-obj-$(CONFIG_FUTEX) += futex.o
++obj-$(CONFIG_FUTEX) += futex/
+ obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
+ obj-$(CONFIG_SMP) += smp.o
+ ifneq ($(CONFIG_SMP),y)
+diff --git a/kernel/futex.c b/kernel/futex.c
+deleted file mode 100644
+index c15ad276f..000000000
+--- a/kernel/futex.c
++++ /dev/null
+@@ -1,4272 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-/*
+- * Fast Userspace Mutexes (which I call "Futexes!").
+- * (C) Rusty Russell, IBM 2002
+- *
+- * Generalized futexes, futex requeueing, misc fixes by Ingo Molnar
+- * (C) Copyright 2003 Red Hat Inc, All Rights Reserved
+- *
+- * Removed page pinning, fix privately mapped COW pages and other cleanups
+- * (C) Copyright 2003, 2004 Jamie Lokier
+- *
+- * Robust futex support started by Ingo Molnar
+- * (C) Copyright 2006 Red Hat Inc, All Rights Reserved
+- * Thanks to Thomas Gleixner for suggestions, analysis and fixes.
+- *
+- * PI-futex support started by Ingo Molnar and Thomas Gleixner
+- * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+- * Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+- *
+- * PRIVATE futexes by Eric Dumazet
+- * Copyright (C) 2007 Eric Dumazet <dada1@cosmosbay.com>
+- *
+- * Requeue-PI support by Darren Hart <dvhltc@us.ibm.com>
+- * Copyright (C) IBM Corporation, 2009
+- * Thanks to Thomas Gleixner for conceptual design and careful reviews.
+- *
+- * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
+- * enough at me, Linus for the original (flawed) idea, Matthew
+- * Kirkwood for proof-of-concept implementation.
+- *
+- * "The futexes are also cursed."
+- * "But they come in a choice of three flavours!"
+- */
+-#include <linux/compat.h>
+-#include <linux/jhash.h>
+-#include <linux/pagemap.h>
+-#include <linux/syscalls.h>
+-#include <linux/freezer.h>
+-#include <linux/memblock.h>
+-#include <linux/fault-inject.h>
+-#include <linux/time_namespace.h>
+-
+-#include <asm/futex.h>
+-
+-#include "locking/rtmutex_common.h"
+-
+-/*
+- * READ this before attempting to hack on futexes!
+- *
+- * Basic futex operation and ordering guarantees
+- * =============================================
+- *
+- * The waiter reads the futex value in user space and calls
+- * futex_wait(). This function computes the hash bucket and acquires
+- * the hash bucket lock. After that it reads the futex user space value
+- * again and verifies that the data has not changed. If it has not changed
+- * it enqueues itself into the hash bucket, releases the hash bucket lock
+- * and schedules.
+- *
+- * The waker side modifies the user space value of the futex and calls
+- * futex_wake(). This function computes the hash bucket and acquires the
+- * hash bucket lock. Then it looks for waiters on that futex in the hash
+- * bucket and wakes them.
+- *
+- * In futex wake up scenarios where no tasks are blocked on a futex, taking
+- * the hb spinlock can be avoided and simply return. In order for this
+- * optimization to work, ordering guarantees must exist so that the waiter
+- * being added to the list is acknowledged when the list is concurrently being
+- * checked by the waker, avoiding scenarios like the following:
+- *
+- * CPU 0 CPU 1
+- * val = *futex;
+- * sys_futex(WAIT, futex, val);
+- * futex_wait(futex, val);
+- * uval = *futex;
+- * *futex = newval;
+- * sys_futex(WAKE, futex);
+- * futex_wake(futex);
+- * if (queue_empty())
+- * return;
+- * if (uval == val)
+- * lock(hash_bucket(futex));
+- * queue();
+- * unlock(hash_bucket(futex));
+- * schedule();
+- *
+- * This would cause the waiter on CPU 0 to wait forever because it
+- * missed the transition of the user space value from val to newval
+- * and the waker did not find the waiter in the hash bucket queue.
+- *
+- * The correct serialization ensures that a waiter either observes
+- * the changed user space value before blocking or is woken by a
+- * concurrent waker:
+- *
+- * CPU 0 CPU 1
+- * val = *futex;
+- * sys_futex(WAIT, futex, val);
+- * futex_wait(futex, val);
+- *
+- * waiters++; (a)
+- * smp_mb(); (A) <-- paired with -.
+- * |
+- * lock(hash_bucket(futex)); |
+- * |
+- * uval = *futex; |
+- * | *futex = newval;
+- * | sys_futex(WAKE, futex);
+- * | futex_wake(futex);
+- * |
+- * `--------> smp_mb(); (B)
+- * if (uval == val)
+- * queue();
+- * unlock(hash_bucket(futex));
+- * schedule(); if (waiters)
+- * lock(hash_bucket(futex));
+- * else wake_waiters(futex);
+- * waiters--; (b) unlock(hash_bucket(futex));
+- *
+- * Where (A) orders the waiters increment and the futex value read through
+- * atomic operations (see hb_waiters_inc) and where (B) orders the write
+- * to futex and the waiters read (see hb_waiters_pending()).
+- *
+- * This yields the following case (where X:=waiters, Y:=futex):
+- *
+- * X = Y = 0
+- *
+- * w[X]=1 w[Y]=1
+- * MB MB
+- * r[Y]=y r[X]=x
+- *
+- * Which guarantees that x==0 && y==0 is impossible; which translates back into
+- * the guarantee that we cannot both miss the futex variable change and the
+- * enqueue.
+- *
+- * Note that a new waiter is accounted for in (a) even when it is possible that
+- * the wait call can return error, in which case we backtrack from it in (b).
+- * Refer to the comment in queue_lock().
+- *
+- * Similarly, in order to account for waiters being requeued on another
+- * address we always increment the waiters for the destination bucket before
+- * acquiring the lock. It then decrements them again after releasing it -
+- * the code that actually moves the futex(es) between hash buckets (requeue_futex)
+- * will do the additional required waiter count housekeeping. This is done for
+- * double_lock_hb() and double_unlock_hb(), respectively.
+- */
+-
+-#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
+-#define futex_cmpxchg_enabled 1
+-#else
+-static int __read_mostly futex_cmpxchg_enabled;
+-#endif
+-
+-/*
+- * Futex flags used to encode options to functions and preserve them across
+- * restarts.
+- */
+-#ifdef CONFIG_MMU
+-# define FLAGS_SHARED 0x01
+-#else
+-/*
+- * NOMMU does not have per process address space. Let the compiler optimize
+- * code away.
+- */
+-# define FLAGS_SHARED 0x00
+-#endif
+-#define FLAGS_CLOCKRT 0x02
+-#define FLAGS_HAS_TIMEOUT 0x04
+-
+-/*
+- * Priority Inheritance state:
+- */
+-struct futex_pi_state {
+- /*
+- * list of 'owned' pi_state instances - these have to be
+- * cleaned up in do_exit() if the task exits prematurely:
+- */
+- struct list_head list;
+-
+- /*
+- * The PI object:
+- */
+- struct rt_mutex_base pi_mutex;
+-
+- struct task_struct *owner;
+- refcount_t refcount;
+-
+- union futex_key key;
+-} __randomize_layout;
+-
+-/**
+- * struct futex_q - The hashed futex queue entry, one per waiting task
+- * @list: priority-sorted list of tasks waiting on this futex
+- * @task: the task waiting on the futex
+- * @lock_ptr: the hash bucket lock
+- * @key: the key the futex is hashed on
+- * @pi_state: optional priority inheritance state
+- * @rt_waiter: rt_waiter storage for use with requeue_pi
+- * @requeue_pi_key: the requeue_pi target futex key
+- * @bitset: bitset for the optional bitmasked wakeup
+- * @requeue_state: State field for futex_requeue_pi()
+- * @requeue_wait: RCU wait for futex_requeue_pi() (RT only)
+- *
+- * We use this hashed waitqueue, instead of a normal wait_queue_entry_t, so
+- * we can wake only the relevant ones (hashed queues may be shared).
+- *
+- * A futex_q has a woken state, just like tasks have TASK_RUNNING.
+- * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
+- * The order of wakeup is always to make the first condition true, then
+- * the second.
+- *
+- * PI futexes are typically woken before they are removed from the hash list via
+- * the rt_mutex code. See unqueue_me_pi().
+- */
+-struct futex_q {
+- struct plist_node list;
+-
+- struct task_struct *task;
+- spinlock_t *lock_ptr;
+- union futex_key key;
+- struct futex_pi_state *pi_state;
+- struct rt_mutex_waiter *rt_waiter;
+- union futex_key *requeue_pi_key;
+- u32 bitset;
+- atomic_t requeue_state;
+-#ifdef CONFIG_PREEMPT_RT
+- struct rcuwait requeue_wait;
+-#endif
+-} __randomize_layout;
+-
+-/*
+- * On PREEMPT_RT, the hash bucket lock is a 'sleeping' spinlock with an
+- * underlying rtmutex. The task which is about to be requeued could have
+- * just woken up (timeout, signal). After the wake up the task has to
+- * acquire hash bucket lock, which is held by the requeue code. As a task
+- * can only be blocked on _ONE_ rtmutex at a time, the proxy lock blocking
+- * and the hash bucket lock blocking would collide and corrupt state.
+- *
+- * On !PREEMPT_RT this is not a problem and everything could be serialized
+- * on hash bucket lock, but aside of having the benefit of common code,
+- * this allows to avoid doing the requeue when the task is already on the
+- * way out and taking the hash bucket lock of the original uaddr1 when the
+- * requeue has been completed.
+- *
+- * The following state transitions are valid:
+- *
+- * On the waiter side:
+- * Q_REQUEUE_PI_NONE -> Q_REQUEUE_PI_IGNORE
+- * Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_WAIT
+- *
+- * On the requeue side:
+- * Q_REQUEUE_PI_NONE -> Q_REQUEUE_PI_INPROGRESS
+- * Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_DONE/LOCKED
+- * Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_NONE (requeue failed)
+- * Q_REQUEUE_PI_WAIT -> Q_REQUEUE_PI_DONE/LOCKED
+- * Q_REQUEUE_PI_WAIT -> Q_REQUEUE_PI_IGNORE (requeue failed)
+- *
+- * The requeue side ignores a waiter with state Q_REQUEUE_PI_IGNORE as this
+- * signals that the waiter is already on the way out. It also means that
+- * the waiter is still on the 'wait' futex, i.e. uaddr1.
+- *
+- * The waiter side signals early wakeup to the requeue side either through
+- * setting state to Q_REQUEUE_PI_IGNORE or to Q_REQUEUE_PI_WAIT depending
+- * on the current state. In case of Q_REQUEUE_PI_IGNORE it can immediately
+- * proceed to take the hash bucket lock of uaddr1. If it set state to WAIT,
+- * which means the wakeup is interleaving with a requeue in progress it has
+- * to wait for the requeue side to change the state. Either to DONE/LOCKED
+- * or to IGNORE. DONE/LOCKED means the waiter q is now on the uaddr2 futex
+- * and either blocked (DONE) or has acquired it (LOCKED). IGNORE is set by
+- * the requeue side when the requeue attempt failed via deadlock detection
+- * and therefore the waiter q is still on the uaddr1 futex.
+- */
+-enum {
+- Q_REQUEUE_PI_NONE = 0,
+- Q_REQUEUE_PI_IGNORE,
+- Q_REQUEUE_PI_IN_PROGRESS,
+- Q_REQUEUE_PI_WAIT,
+- Q_REQUEUE_PI_DONE,
+- Q_REQUEUE_PI_LOCKED,
+-};
+-
+-static const struct futex_q futex_q_init = {
+- /* list gets initialized in queue_me()*/
+- .key = FUTEX_KEY_INIT,
+- .bitset = FUTEX_BITSET_MATCH_ANY,
+- .requeue_state = ATOMIC_INIT(Q_REQUEUE_PI_NONE),
+-};
+-
+-/*
+- * Hash buckets are shared by all the futex_keys that hash to the same
+- * location. Each key may have multiple futex_q structures, one for each task
+- * waiting on a futex.
+- */
+-struct futex_hash_bucket {
+- atomic_t waiters;
+- spinlock_t lock;
+- struct plist_head chain;
+-} ____cacheline_aligned_in_smp;
+-
+-/*
+- * The base of the bucket array and its size are always used together
+- * (after initialization only in hash_futex()), so ensure that they
+- * reside in the same cacheline.
+- */
+-static struct {
+- struct futex_hash_bucket *queues;
+- unsigned long hashsize;
+-} __futex_data __read_mostly __aligned(2*sizeof(long));
+-#define futex_queues (__futex_data.queues)
+-#define futex_hashsize (__futex_data.hashsize)
+-
+-
+-/*
+- * Fault injections for futexes.
+- */
+-#ifdef CONFIG_FAIL_FUTEX
+-
+-static struct {
+- struct fault_attr attr;
+-
+- bool ignore_private;
+-} fail_futex = {
+- .attr = FAULT_ATTR_INITIALIZER,
+- .ignore_private = false,
+-};
+-
+-static int __init setup_fail_futex(char *str)
+-{
+- return setup_fault_attr(&fail_futex.attr, str);
+-}
+-__setup("fail_futex=", setup_fail_futex);
+-
+-static bool should_fail_futex(bool fshared)
+-{
+- if (fail_futex.ignore_private && !fshared)
+- return false;
+-
+- return should_fail(&fail_futex.attr, 1);
+-}
+-
+-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
+-
+-static int __init fail_futex_debugfs(void)
+-{
+- umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+- struct dentry *dir;
+-
+- dir = fault_create_debugfs_attr("fail_futex", NULL,
+- &fail_futex.attr);
+- if (IS_ERR(dir))
+- return PTR_ERR(dir);
+-
+- debugfs_create_bool("ignore-private", mode, dir,
+- &fail_futex.ignore_private);
+- return 0;
+-}
+-
+-late_initcall(fail_futex_debugfs);
+-
+-#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+-
+-#else
+-static inline bool should_fail_futex(bool fshared)
+-{
+- return false;
+-}
+-#endif /* CONFIG_FAIL_FUTEX */
+-
+-#ifdef CONFIG_COMPAT
+-static void compat_exit_robust_list(struct task_struct *curr);
+-#endif
+-
+-/*
+- * Reflects a new waiter being added to the waitqueue.
+- */
+-static inline void hb_waiters_inc(struct futex_hash_bucket *hb)
+-{
+-#ifdef CONFIG_SMP
+- atomic_inc(&hb->waiters);
+- /*
+- * Full barrier (A), see the ordering comment above.
+- */
+- smp_mb__after_atomic();
+-#endif
+-}
+-
+-/*
+- * Reflects a waiter being removed from the waitqueue by wakeup
+- * paths.
+- */
+-static inline void hb_waiters_dec(struct futex_hash_bucket *hb)
+-{
+-#ifdef CONFIG_SMP
+- atomic_dec(&hb->waiters);
+-#endif
+-}
+-
+-static inline int hb_waiters_pending(struct futex_hash_bucket *hb)
+-{
+-#ifdef CONFIG_SMP
+- /*
+- * Full barrier (B), see the ordering comment above.
+- */
+- smp_mb();
+- return atomic_read(&hb->waiters);
+-#else
+- return 1;
+-#endif
+-}
+-
+-/**
+- * hash_futex - Return the hash bucket in the global hash
+- * @key: Pointer to the futex key for which the hash is calculated
+- *
+- * We hash on the keys returned from get_futex_key (see below) and return the
+- * corresponding hash bucket in the global hash.
+- */
+-static struct futex_hash_bucket *hash_futex(union futex_key *key)
+-{
+- u32 hash = jhash2((u32 *)key, offsetof(typeof(*key), both.offset) / 4,
+- key->both.offset);
+-
+- return &futex_queues[hash & (futex_hashsize - 1)];
+-}
+-
+-
+-/**
+- * match_futex - Check whether two futex keys are equal
+- * @key1: Pointer to key1
+- * @key2: Pointer to key2
+- *
+- * Return 1 if two futex_keys are equal, 0 otherwise.
+- */
+-static inline int match_futex(union futex_key *key1, union futex_key *key2)
+-{
+- return (key1 && key2
+- && key1->both.word == key2->both.word
+- && key1->both.ptr == key2->both.ptr
+- && key1->both.offset == key2->both.offset);
+-}
+-
+-enum futex_access {
+- FUTEX_READ,
+- FUTEX_WRITE
+-};
+-
+-/**
+- * futex_setup_timer - set up the sleeping hrtimer.
+- * @time: ptr to the given timeout value
+- * @timeout: the hrtimer_sleeper structure to be set up
+- * @flags: futex flags
+- * @range_ns: optional range in ns
+- *
+- * Return: Initialized hrtimer_sleeper structure or NULL if no timeout
+- * value given
+- */
+-static inline struct hrtimer_sleeper *
+-futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
+- int flags, u64 range_ns)
+-{
+- if (!time)
+- return NULL;
+-
+- hrtimer_init_sleeper_on_stack(timeout, (flags & FLAGS_CLOCKRT) ?
+- CLOCK_REALTIME : CLOCK_MONOTONIC,
+- HRTIMER_MODE_ABS);
+- /*
+- * If range_ns is 0, calling hrtimer_set_expires_range_ns() is
+- * effectively the same as calling hrtimer_set_expires().
+- */
+- hrtimer_set_expires_range_ns(&timeout->timer, *time, range_ns);
+-
+- return timeout;
+-}
+-
+-/*
+- * Generate a machine wide unique identifier for this inode.
+- *
+- * This relies on u64 not wrapping in the life-time of the machine; which with
+- * 1ns resolution means almost 585 years.
+- *
+- * This further relies on the fact that a well formed program will not unmap
+- * the file while it has a (shared) futex waiting on it. This mapping will have
+- * a file reference which pins the mount and inode.
+- *
+- * If for some reason an inode gets evicted and read back in again, it will get
+- * a new sequence number and will _NOT_ match, even though it is the exact same
+- * file.
+- *
+- * It is important that match_futex() will never have a false-positive, esp.
+- * for PI futexes that can mess up the state. The above argues that false-negatives
+- * are only possible for malformed programs.
+- */
+-static u64 get_inode_sequence_number(struct inode *inode)
+-{
+- static atomic64_t i_seq;
+- u64 old;
+-
+- /* Does the inode already have a sequence number? */
+- old = atomic64_read(&inode->i_sequence);
+- if (likely(old))
+- return old;
+-
+- for (;;) {
+- u64 new = atomic64_add_return(1, &i_seq);
+- if (WARN_ON_ONCE(!new))
+- continue;
+-
+- old = atomic64_cmpxchg_relaxed(&inode->i_sequence, 0, new);
+- if (old)
+- return old;
+- return new;
+- }
+-}
+-
+-/**
+- * get_futex_key() - Get parameters which are the keys for a futex
+- * @uaddr: virtual address of the futex
+- * @fshared: false for a PROCESS_PRIVATE futex, true for PROCESS_SHARED
+- * @key: address where result is stored.
+- * @rw: mapping needs to be read/write (values: FUTEX_READ,
+- * FUTEX_WRITE)
+- *
+- * Return: a negative error code or 0
+- *
+- * The key words are stored in @key on success.
+- *
+- * For shared mappings (when @fshared), the key is:
+- *
+- * ( inode->i_sequence, page->index, offset_within_page )
+- *
+- * [ also see get_inode_sequence_number() ]
+- *
+- * For private mappings (or when !@fshared), the key is:
+- *
+- * ( current->mm, address, 0 )
+- *
+- * This allows (cross process, where applicable) identification of the futex
+- * without keeping the page pinned for the duration of the FUTEX_WAIT.
+- *
+- * lock_page() might sleep, the caller should not hold a spinlock.
+- */
+-static int get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key,
+- enum futex_access rw)
+-{
+- unsigned long address = (unsigned long)uaddr;
+- struct mm_struct *mm = current->mm;
+- struct page *page, *tail;
+- struct address_space *mapping;
+- int err, ro = 0;
+-
+- /*
+- * The futex address must be "naturally" aligned.
+- */
+- key->both.offset = address % PAGE_SIZE;
+- if (unlikely((address % sizeof(u32)) != 0))
+- return -EINVAL;
+- address -= key->both.offset;
+-
+- if (unlikely(!access_ok(uaddr, sizeof(u32))))
+- return -EFAULT;
+-
+- if (unlikely(should_fail_futex(fshared)))
+- return -EFAULT;
+-
+- /*
+- * PROCESS_PRIVATE futexes are fast.
+- * As the mm cannot disappear under us and the 'key' only needs
+- * virtual address, we dont even have to find the underlying vma.
+- * Note : We do have to check 'uaddr' is a valid user address,
+- * but access_ok() should be faster than find_vma()
+- */
+- if (!fshared) {
+- key->private.mm = mm;
+- key->private.address = address;
+- return 0;
+- }
+-
+-again:
+- /* Ignore any VERIFY_READ mapping (futex common case) */
+- if (unlikely(should_fail_futex(true)))
+- return -EFAULT;
+-
+- err = get_user_pages_fast(address, 1, FOLL_WRITE, &page);
+- /*
+- * If write access is not required (eg. FUTEX_WAIT), try
+- * and get read-only access.
+- */
+- if (err == -EFAULT && rw == FUTEX_READ) {
+- err = get_user_pages_fast(address, 1, 0, &page);
+- ro = 1;
+- }
+- if (err < 0)
+- return err;
+- else
+- err = 0;
+-
+- /*
+- * The treatment of mapping from this point on is critical. The page
+- * lock protects many things but in this context the page lock
+- * stabilizes mapping, prevents inode freeing in the shared
+- * file-backed region case and guards against movement to swap cache.
+- *
+- * Strictly speaking the page lock is not needed in all cases being
+- * considered here and page lock forces unnecessarily serialization
+- * From this point on, mapping will be re-verified if necessary and
+- * page lock will be acquired only if it is unavoidable
+- *
+- * Mapping checks require the head page for any compound page so the
+- * head page and mapping is looked up now. For anonymous pages, it
+- * does not matter if the page splits in the future as the key is
+- * based on the address. For filesystem-backed pages, the tail is
+- * required as the index of the page determines the key. For
+- * base pages, there is no tail page and tail == page.
+- */
+- tail = page;
+- page = compound_head(page);
+- mapping = READ_ONCE(page->mapping);
+-
+- /*
+- * If page->mapping is NULL, then it cannot be a PageAnon
+- * page; but it might be the ZERO_PAGE or in the gate area or
+- * in a special mapping (all cases which we are happy to fail);
+- * or it may have been a good file page when get_user_pages_fast
+- * found it, but truncated or holepunched or subjected to
+- * invalidate_complete_page2 before we got the page lock (also
+- * cases which we are happy to fail). And we hold a reference,
+- * so refcount care in invalidate_complete_page's remove_mapping
+- * prevents drop_caches from setting mapping to NULL beneath us.
+- *
+- * The case we do have to guard against is when memory pressure made
+- * shmem_writepage move it from filecache to swapcache beneath us:
+- * an unlikely race, but we do need to retry for page->mapping.
+- */
+- if (unlikely(!mapping)) {
+- int shmem_swizzled;
+-
+- /*
+- * Page lock is required to identify which special case above
+- * applies. If this is really a shmem page then the page lock
+- * will prevent unexpected transitions.
+- */
+- lock_page(page);
+- shmem_swizzled = PageSwapCache(page) || page->mapping;
+- unlock_page(page);
+- put_page(page);
+-
+- if (shmem_swizzled)
+- goto again;
+-
+- return -EFAULT;
+- }
+-
+- /*
+- * Private mappings are handled in a simple way.
+- *
+- * If the futex key is stored on an anonymous page, then the associated
+- * object is the mm which is implicitly pinned by the calling process.
+- *
+- * NOTE: When userspace waits on a MAP_SHARED mapping, even if
+- * it's a read-only handle, it's expected that futexes attach to
+- * the object not the particular process.
+- */
+- if (PageAnon(page)) {
+- /*
+- * A RO anonymous page will never change and thus doesn't make
+- * sense for futex operations.
+- */
+- if (unlikely(should_fail_futex(true)) || ro) {
+- err = -EFAULT;
+- goto out;
+- }
+-
+- key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
+- key->private.mm = mm;
+- key->private.address = address;
+-
+- } else {
+- struct inode *inode;
+-
+- /*
+- * The associated futex object in this case is the inode and
+- * the page->mapping must be traversed. Ordinarily this should
+- * be stabilised under page lock but it's not strictly
+- * necessary in this case as we just want to pin the inode, not
+- * update the radix tree or anything like that.
+- *
+- * The RCU read lock is taken as the inode is finally freed
+- * under RCU. If the mapping still matches expectations then the
+- * mapping->host can be safely accessed as being a valid inode.
+- */
+- rcu_read_lock();
+-
+- if (READ_ONCE(page->mapping) != mapping) {
+- rcu_read_unlock();
+- put_page(page);
+-
+- goto again;
+- }
+-
+- inode = READ_ONCE(mapping->host);
+- if (!inode) {
+- rcu_read_unlock();
+- put_page(page);
+-
+- goto again;
+- }
+-
+- key->both.offset |= FUT_OFF_INODE; /* inode-based key */
+- key->shared.i_seq = get_inode_sequence_number(inode);
+- key->shared.pgoff = page_to_pgoff(tail);
+- rcu_read_unlock();
+- }
+-
+-out:
+- put_page(page);
+- return err;
+-}
+-
+-/**
+- * fault_in_user_writeable() - Fault in user address and verify RW access
+- * @uaddr: pointer to faulting user space address
+- *
+- * Slow path to fixup the fault we just took in the atomic write
+- * access to @uaddr.
+- *
+- * We have no generic implementation of a non-destructive write to the
+- * user address. We know that we faulted in the atomic pagefault
+- * disabled section so we can as well avoid the #PF overhead by
+- * calling get_user_pages() right away.
+- */
+-static int fault_in_user_writeable(u32 __user *uaddr)
+-{
+- struct mm_struct *mm = current->mm;
+- int ret;
+-
+- mmap_read_lock(mm);
+- ret = fixup_user_fault(mm, (unsigned long)uaddr,
+- FAULT_FLAG_WRITE, NULL);
+- mmap_read_unlock(mm);
+-
+- return ret < 0 ? ret : 0;
+-}
+-
+-/**
+- * futex_top_waiter() - Return the highest priority waiter on a futex
+- * @hb: the hash bucket the futex_q's reside in
+- * @key: the futex key (to distinguish it from other futex futex_q's)
+- *
+- * Must be called with the hb lock held.
+- */
+-static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
+- union futex_key *key)
+-{
+- struct futex_q *this;
+-
+- plist_for_each_entry(this, &hb->chain, list) {
+- if (match_futex(&this->key, key))
+- return this;
+- }
+- return NULL;
+-}
+-
+-static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
+- u32 uval, u32 newval)
+-{
+- int ret;
+-
+- pagefault_disable();
+- ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
+- pagefault_enable();
+-
+- return ret;
+-}
+-
+-static int get_futex_value_locked(u32 *dest, u32 __user *from)
+-{
+- int ret;
+-
+- pagefault_disable();
+- ret = __get_user(*dest, from);
+- pagefault_enable();
+-
+- return ret ? -EFAULT : 0;
+-}
+-
+-
+-/*
+- * PI code:
+- */
+-static int refill_pi_state_cache(void)
+-{
+- struct futex_pi_state *pi_state;
+-
+- if (likely(current->pi_state_cache))
+- return 0;
+-
+- pi_state = kzalloc(sizeof(*pi_state), GFP_KERNEL);
+-
+- if (!pi_state)
+- return -ENOMEM;
+-
+- INIT_LIST_HEAD(&pi_state->list);
+- /* pi_mutex gets initialized later */
+- pi_state->owner = NULL;
+- refcount_set(&pi_state->refcount, 1);
+- pi_state->key = FUTEX_KEY_INIT;
+-
+- current->pi_state_cache = pi_state;
+-
+- return 0;
+-}
+-
+-static struct futex_pi_state *alloc_pi_state(void)
+-{
+- struct futex_pi_state *pi_state = current->pi_state_cache;
+-
+- WARN_ON(!pi_state);
+- current->pi_state_cache = NULL;
+-
+- return pi_state;
+-}
+-
+-static void pi_state_update_owner(struct futex_pi_state *pi_state,
+- struct task_struct *new_owner)
+-{
+- struct task_struct *old_owner = pi_state->owner;
+-
+- lockdep_assert_held(&pi_state->pi_mutex.wait_lock);
+-
+- if (old_owner) {
+- raw_spin_lock(&old_owner->pi_lock);
+- WARN_ON(list_empty(&pi_state->list));
+- list_del_init(&pi_state->list);
+- raw_spin_unlock(&old_owner->pi_lock);
+- }
+-
+- if (new_owner) {
+- raw_spin_lock(&new_owner->pi_lock);
+- WARN_ON(!list_empty(&pi_state->list));
+- list_add(&pi_state->list, &new_owner->pi_state_list);
+- pi_state->owner = new_owner;
+- raw_spin_unlock(&new_owner->pi_lock);
+- }
+-}
+-
+-static void get_pi_state(struct futex_pi_state *pi_state)
+-{
+- WARN_ON_ONCE(!refcount_inc_not_zero(&pi_state->refcount));
+-}
+-
+-/*
+- * Drops a reference to the pi_state object and frees or caches it
+- * when the last reference is gone.
+- */
+-static void put_pi_state(struct futex_pi_state *pi_state)
+-{
+- if (!pi_state)
+- return;
+-
+- if (!refcount_dec_and_test(&pi_state->refcount))
+- return;
+-
+- /*
+- * If pi_state->owner is NULL, the owner is most probably dying
+- * and has cleaned up the pi_state already
+- */
+- if (pi_state->owner) {
+- unsigned long flags;
+-
+- raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags);
+- pi_state_update_owner(pi_state, NULL);
+- rt_mutex_proxy_unlock(&pi_state->pi_mutex);
+- raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags);
+- }
+-
+- if (current->pi_state_cache) {
+- kfree(pi_state);
+- } else {
+- /*
+- * pi_state->list is already empty.
+- * clear pi_state->owner.
+- * refcount is at 0 - put it back to 1.
+- */
+- pi_state->owner = NULL;
+- refcount_set(&pi_state->refcount, 1);
+- current->pi_state_cache = pi_state;
+- }
+-}
+-
+-#ifdef CONFIG_FUTEX_PI
+-
+-/*
+- * This task is holding PI mutexes at exit time => bad.
+- * Kernel cleans up PI-state, but userspace is likely hosed.
+- * (Robust-futex cleanup is separate and might save the day for userspace.)
+- */
+-static void exit_pi_state_list(struct task_struct *curr)
+-{
+- struct list_head *next, *head = &curr->pi_state_list;
+- struct futex_pi_state *pi_state;
+- struct futex_hash_bucket *hb;
+- union futex_key key = FUTEX_KEY_INIT;
+-
+- if (!futex_cmpxchg_enabled)
+- return;
+- /*
+- * We are a ZOMBIE and nobody can enqueue itself on
+- * pi_state_list anymore, but we have to be careful
+- * versus waiters unqueueing themselves:
+- */
+- raw_spin_lock_irq(&curr->pi_lock);
+- while (!list_empty(head)) {
+- next = head->next;
+- pi_state = list_entry(next, struct futex_pi_state, list);
+- key = pi_state->key;
+- hb = hash_futex(&key);
+-
+- /*
+- * We can race against put_pi_state() removing itself from the
+- * list (a waiter going away). put_pi_state() will first
+- * decrement the reference count and then modify the list, so
+- * its possible to see the list entry but fail this reference
+- * acquire.
+- *
+- * In that case; drop the locks to let put_pi_state() make
+- * progress and retry the loop.
+- */
+- if (!refcount_inc_not_zero(&pi_state->refcount)) {
+- raw_spin_unlock_irq(&curr->pi_lock);
+- cpu_relax();
+- raw_spin_lock_irq(&curr->pi_lock);
+- continue;
+- }
+- raw_spin_unlock_irq(&curr->pi_lock);
+-
+- spin_lock(&hb->lock);
+- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+- raw_spin_lock(&curr->pi_lock);
+- /*
+- * We dropped the pi-lock, so re-check whether this
+- * task still owns the PI-state:
+- */
+- if (head->next != next) {
+- /* retain curr->pi_lock for the loop invariant */
+- raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
+- spin_unlock(&hb->lock);
+- put_pi_state(pi_state);
+- continue;
+- }
+-
+- WARN_ON(pi_state->owner != curr);
+- WARN_ON(list_empty(&pi_state->list));
+- list_del_init(&pi_state->list);
+- pi_state->owner = NULL;
+-
+- raw_spin_unlock(&curr->pi_lock);
+- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+- spin_unlock(&hb->lock);
+-
+- rt_mutex_futex_unlock(&pi_state->pi_mutex);
+- put_pi_state(pi_state);
+-
+- raw_spin_lock_irq(&curr->pi_lock);
+- }
+- raw_spin_unlock_irq(&curr->pi_lock);
+-}
+-#else
+-static inline void exit_pi_state_list(struct task_struct *curr) { }
+-#endif
+-
+-/*
+- * We need to check the following states:
+- *
+- * Waiter | pi_state | pi->owner | uTID | uODIED | ?
+- *
+- * [1] NULL | --- | --- | 0 | 0/1 | Valid
+- * [2] NULL | --- | --- | >0 | 0/1 | Valid
+- *
+- * [3] Found | NULL | -- | Any | 0/1 | Invalid
+- *
+- * [4] Found | Found | NULL | 0 | 1 | Valid
+- * [5] Found | Found | NULL | >0 | 1 | Invalid
+- *
+- * [6] Found | Found | task | 0 | 1 | Valid
+- *
+- * [7] Found | Found | NULL | Any | 0 | Invalid
+- *
+- * [8] Found | Found | task | ==taskTID | 0/1 | Valid
+- * [9] Found | Found | task | 0 | 0 | Invalid
+- * [10] Found | Found | task | !=taskTID | 0/1 | Invalid
+- *
+- * [1] Indicates that the kernel can acquire the futex atomically. We
+- * came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
+- *
+- * [2] Valid, if TID does not belong to a kernel thread. If no matching
+- * thread is found then it indicates that the owner TID has died.
+- *
+- * [3] Invalid. The waiter is queued on a non PI futex
+- *
+- * [4] Valid state after exit_robust_list(), which sets the user space
+- * value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
+- *
+- * [5] The user space value got manipulated between exit_robust_list()
+- * and exit_pi_state_list()
+- *
+- * [6] Valid state after exit_pi_state_list() which sets the new owner in
+- * the pi_state but cannot access the user space value.
+- *
+- * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
+- *
+- * [8] Owner and user space value match
+- *
+- * [9] There is no transient state which sets the user space TID to 0
+- * except exit_robust_list(), but this is indicated by the
+- * FUTEX_OWNER_DIED bit. See [4]
+- *
+- * [10] There is no transient state which leaves owner and user space
+- * TID out of sync. Except one error case where the kernel is denied
+- * write access to the user address, see fixup_pi_state_owner().
+- *
+- *
+- * Serialization and lifetime rules:
+- *
+- * hb->lock:
+- *
+- * hb -> futex_q, relation
+- * futex_q -> pi_state, relation
+- *
+- * (cannot be raw because hb can contain arbitrary amount
+- * of futex_q's)
+- *
+- * pi_mutex->wait_lock:
+- *
+- * {uval, pi_state}
+- *
+- * (and pi_mutex 'obviously')
+- *
+- * p->pi_lock:
+- *
+- * p->pi_state_list -> pi_state->list, relation
+- * pi_mutex->owner -> pi_state->owner, relation
+- *
+- * pi_state->refcount:
+- *
+- * pi_state lifetime
+- *
+- *
+- * Lock order:
+- *
+- * hb->lock
+- * pi_mutex->wait_lock
+- * p->pi_lock
+- *
+- */
+-
+-/*
+- * Validate that the existing waiter has a pi_state and sanity check
+- * the pi_state against the user space value. If correct, attach to
+- * it.
+- */
+-static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
+- struct futex_pi_state *pi_state,
+- struct futex_pi_state **ps)
+-{
+- pid_t pid = uval & FUTEX_TID_MASK;
+- u32 uval2;
+- int ret;
+-
+- /*
+- * Userspace might have messed up non-PI and PI futexes [3]
+- */
+- if (unlikely(!pi_state))
+- return -EINVAL;
+-
+- /*
+- * We get here with hb->lock held, and having found a
+- * futex_top_waiter(). This means that futex_lock_pi() of said futex_q
+- * has dropped the hb->lock in between queue_me() and unqueue_me_pi(),
+- * which in turn means that futex_lock_pi() still has a reference on
+- * our pi_state.
+- *
+- * The waiter holding a reference on @pi_state also protects against
+- * the unlocked put_pi_state() in futex_unlock_pi(), futex_lock_pi()
+- * and futex_wait_requeue_pi() as it cannot go to 0 and consequently
+- * free pi_state before we can take a reference ourselves.
+- */
+- WARN_ON(!refcount_read(&pi_state->refcount));
+-
+- /*
+- * Now that we have a pi_state, we can acquire wait_lock
+- * and do the state validation.
+- */
+- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+-
+- /*
+- * Since {uval, pi_state} is serialized by wait_lock, and our current
+- * uval was read without holding it, it can have changed. Verify it
+- * still is what we expect it to be, otherwise retry the entire
+- * operation.
+- */
+- if (get_futex_value_locked(&uval2, uaddr))
+- goto out_efault;
+-
+- if (uval != uval2)
+- goto out_eagain;
+-
+- /*
+- * Handle the owner died case:
+- */
+- if (uval & FUTEX_OWNER_DIED) {
+- /*
+- * exit_pi_state_list sets owner to NULL and wakes the
+- * topmost waiter. The task which acquires the
+- * pi_state->rt_mutex will fixup owner.
+- */
+- if (!pi_state->owner) {
+- /*
+- * No pi state owner, but the user space TID
+- * is not 0. Inconsistent state. [5]
+- */
+- if (pid)
+- goto out_einval;
+- /*
+- * Take a ref on the state and return success. [4]
+- */
+- goto out_attach;
+- }
+-
+- /*
+- * If TID is 0, then either the dying owner has not
+- * yet executed exit_pi_state_list() or some waiter
+- * acquired the rtmutex in the pi state, but did not
+- * yet fixup the TID in user space.
+- *
+- * Take a ref on the state and return success. [6]
+- */
+- if (!pid)
+- goto out_attach;
+- } else {
+- /*
+- * If the owner died bit is not set, then the pi_state
+- * must have an owner. [7]
+- */
+- if (!pi_state->owner)
+- goto out_einval;
+- }
+-
+- /*
+- * Bail out if user space manipulated the futex value. If pi
+- * state exists then the owner TID must be the same as the
+- * user space TID. [9/10]
+- */
+- if (pid != task_pid_vnr(pi_state->owner))
+- goto out_einval;
+-
+-out_attach:
+- get_pi_state(pi_state);
+- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+- *ps = pi_state;
+- return 0;
+-
+-out_einval:
+- ret = -EINVAL;
+- goto out_error;
+-
+-out_eagain:
+- ret = -EAGAIN;
+- goto out_error;
+-
+-out_efault:
+- ret = -EFAULT;
+- goto out_error;
+-
+-out_error:
+- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+- return ret;
+-}
+-
+-/**
+- * wait_for_owner_exiting - Block until the owner has exited
+- * @ret: owner's current futex lock status
+- * @exiting: Pointer to the exiting task
+- *
+- * Caller must hold a refcount on @exiting.
+- */
+-static void wait_for_owner_exiting(int ret, struct task_struct *exiting)
+-{
+- if (ret != -EBUSY) {
+- WARN_ON_ONCE(exiting);
+- return;
+- }
+-
+- if (WARN_ON_ONCE(ret == -EBUSY && !exiting))
+- return;
+-
+- mutex_lock(&exiting->futex_exit_mutex);
+- /*
+- * No point in doing state checking here. If the waiter got here
+- * while the task was in exec()->exec_futex_release() then it can
+- * have any FUTEX_STATE_* value when the waiter has acquired the
+- * mutex. OK, if running, EXITING or DEAD if it reached exit()
+- * already. Highly unlikely and not a problem. Just one more round
+- * through the futex maze.
+- */
+- mutex_unlock(&exiting->futex_exit_mutex);
+-
+- put_task_struct(exiting);
+-}
+-
+-static int handle_exit_race(u32 __user *uaddr, u32 uval,
+- struct task_struct *tsk)
+-{
+- u32 uval2;
+-
+- /*
+- * If the futex exit state is not yet FUTEX_STATE_DEAD, tell the
+- * caller that the alleged owner is busy.
+- */
+- if (tsk && tsk->futex_state != FUTEX_STATE_DEAD)
+- return -EBUSY;
+-
+- /*
+- * Reread the user space value to handle the following situation:
+- *
+- * CPU0 CPU1
+- *
+- * sys_exit() sys_futex()
+- * do_exit() futex_lock_pi()
+- * futex_lock_pi_atomic()
+- * exit_signals(tsk) No waiters:
+- * tsk->flags |= PF_EXITING; *uaddr == 0x00000PID
+- * mm_release(tsk) Set waiter bit
+- * exit_robust_list(tsk) { *uaddr = 0x80000PID;
+- * Set owner died attach_to_pi_owner() {
+- * *uaddr = 0xC0000000; tsk = get_task(PID);
+- * } if (!tsk->flags & PF_EXITING) {
+- * ... attach();
+- * tsk->futex_state = } else {
+- * FUTEX_STATE_DEAD; if (tsk->futex_state !=
+- * FUTEX_STATE_DEAD)
+- * return -EAGAIN;
+- * return -ESRCH; <--- FAIL
+- * }
+- *
+- * Returning ESRCH unconditionally is wrong here because the
+- * user space value has been changed by the exiting task.
+- *
+- * The same logic applies to the case where the exiting task is
+- * already gone.
+- */
+- if (get_futex_value_locked(&uval2, uaddr))
+- return -EFAULT;
+-
+- /* If the user space value has changed, try again. */
+- if (uval2 != uval)
+- return -EAGAIN;
+-
+- /*
+- * The exiting task did not have a robust list, the robust list was
+- * corrupted or the user space value in *uaddr is simply bogus.
+- * Give up and tell user space.
+- */
+- return -ESRCH;
+-}
+-
+-static void __attach_to_pi_owner(struct task_struct *p, union futex_key *key,
+- struct futex_pi_state **ps)
+-{
+- /*
+- * No existing pi state. First waiter. [2]
+- *
+- * This creates pi_state, we have hb->lock held, this means nothing can
+- * observe this state, wait_lock is irrelevant.
+- */
+- struct futex_pi_state *pi_state = alloc_pi_state();
+-
+- /*
+- * Initialize the pi_mutex in locked state and make @p
+- * the owner of it:
+- */
+- rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p);
+-
+- /* Store the key for possible exit cleanups: */
+- pi_state->key = *key;
+-
+- WARN_ON(!list_empty(&pi_state->list));
+- list_add(&pi_state->list, &p->pi_state_list);
+- /*
+- * Assignment without holding pi_state->pi_mutex.wait_lock is safe
+- * because there is no concurrency as the object is not published yet.
+- */
+- pi_state->owner = p;
+-
+- *ps = pi_state;
+-}
+-/*
+- * Lookup the task for the TID provided from user space and attach to
+- * it after doing proper sanity checks.
+- */
+-static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key,
+- struct futex_pi_state **ps,
+- struct task_struct **exiting)
+-{
+- pid_t pid = uval & FUTEX_TID_MASK;
+- struct task_struct *p;
+-
+- /*
+- * We are the first waiter - try to look up the real owner and attach
+- * the new pi_state to it, but bail out when TID = 0 [1]
+- *
+- * The !pid check is paranoid. None of the call sites should end up
+- * with pid == 0, but better safe than sorry. Let the caller retry
+- */
+- if (!pid)
+- return -EAGAIN;
+- p = find_get_task_by_vpid(pid);
+- if (!p)
+- return handle_exit_race(uaddr, uval, NULL);
+-
+- if (unlikely(p->flags & PF_KTHREAD)) {
+- put_task_struct(p);
+- return -EPERM;
+- }
+-
+- /*
+- * We need to look at the task state to figure out, whether the
+- * task is exiting. To protect against the change of the task state
+- * in futex_exit_release(), we do this protected by p->pi_lock:
+- */
+- raw_spin_lock_irq(&p->pi_lock);
+- if (unlikely(p->futex_state != FUTEX_STATE_OK)) {
+- /*
+- * The task is on the way out. When the futex state is
+- * FUTEX_STATE_DEAD, we know that the task has finished
+- * the cleanup:
+- */
+- int ret = handle_exit_race(uaddr, uval, p);
+-
+- raw_spin_unlock_irq(&p->pi_lock);
+- /*
+- * If the owner task is between FUTEX_STATE_EXITING and
+- * FUTEX_STATE_DEAD then store the task pointer and keep
+- * the reference on the task struct. The calling code will
+- * drop all locks, wait for the task to reach
+- * FUTEX_STATE_DEAD and then drop the refcount. This is
+- * required to prevent a live lock when the current task
+- * preempted the exiting task between the two states.
+- */
+- if (ret == -EBUSY)
+- *exiting = p;
+- else
+- put_task_struct(p);
+- return ret;
+- }
+-
+- __attach_to_pi_owner(p, key, ps);
+- raw_spin_unlock_irq(&p->pi_lock);
+-
+- put_task_struct(p);
+-
+- return 0;
+-}
+-
+-static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval)
+-{
+- int err;
+- u32 curval;
+-
+- if (unlikely(should_fail_futex(true)))
+- return -EFAULT;
+-
+- err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
+- if (unlikely(err))
+- return err;
+-
+- /* If user space value changed, let the caller retry */
+- return curval != uval ? -EAGAIN : 0;
+-}
+-
+-/**
+- * futex_lock_pi_atomic() - Atomic work required to acquire a pi aware futex
+- * @uaddr: the pi futex user address
+- * @hb: the pi futex hash bucket
+- * @key: the futex key associated with uaddr and hb
+- * @ps: the pi_state pointer where we store the result of the
+- * lookup
+- * @task: the task to perform the atomic lock work for. This will
+- * be "current" except in the case of requeue pi.
+- * @exiting: Pointer to store the task pointer of the owner task
+- * which is in the middle of exiting
+- * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0)
+- *
+- * Return:
+- * - 0 - ready to wait;
+- * - 1 - acquired the lock;
+- * - <0 - error
+- *
+- * The hb->lock must be held by the caller.
+- *
+- * @exiting is only set when the return value is -EBUSY. If so, this holds
+- * a refcount on the exiting task on return and the caller needs to drop it
+- * after waiting for the exit to complete.
+- */
+-static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
+- union futex_key *key,
+- struct futex_pi_state **ps,
+- struct task_struct *task,
+- struct task_struct **exiting,
+- int set_waiters)
+-{
+- u32 uval, newval, vpid = task_pid_vnr(task);
+- struct futex_q *top_waiter;
+- int ret;
+-
+- /*
+- * Read the user space value first so we can validate a few
+- * things before proceeding further.
+- */
+- if (get_futex_value_locked(&uval, uaddr))
+- return -EFAULT;
+-
+- if (unlikely(should_fail_futex(true)))
+- return -EFAULT;
+-
+- /*
+- * Detect deadlocks.
+- */
+- if ((unlikely((uval & FUTEX_TID_MASK) == vpid)))
+- return -EDEADLK;
+-
+- if ((unlikely(should_fail_futex(true))))
+- return -EDEADLK;
+-
+- /*
+- * Lookup existing state first. If it exists, try to attach to
+- * its pi_state.
+- */
+- top_waiter = futex_top_waiter(hb, key);
+- if (top_waiter)
+- return attach_to_pi_state(uaddr, uval, top_waiter->pi_state, ps);
+-
+- /*
+- * No waiter and user TID is 0. We are here because the
+- * waiters or the owner died bit is set or called from
+- * requeue_cmp_pi or for whatever reason something took the
+- * syscall.
+- */
+- if (!(uval & FUTEX_TID_MASK)) {
+- /*
+- * We take over the futex. No other waiters and the user space
+- * TID is 0. We preserve the owner died bit.
+- */
+- newval = uval & FUTEX_OWNER_DIED;
+- newval |= vpid;
+-
+- /* The futex requeue_pi code can enforce the waiters bit */
+- if (set_waiters)
+- newval |= FUTEX_WAITERS;
+-
+- ret = lock_pi_update_atomic(uaddr, uval, newval);
+- if (ret)
+- return ret;
+-
+- /*
+- * If the waiter bit was requested the caller also needs PI
+- * state attached to the new owner of the user space futex.
+- *
+- * @task is guaranteed to be alive and it cannot be exiting
+- * because it is either sleeping or waiting in
+- * futex_requeue_pi_wakeup_sync().
+- *
+- * No need to do the full attach_to_pi_owner() exercise
+- * because @task is known and valid.
+- */
+- if (set_waiters) {
+- raw_spin_lock_irq(&task->pi_lock);
+- __attach_to_pi_owner(task, key, ps);
+- raw_spin_unlock_irq(&task->pi_lock);
+- }
+- return 1;
+- }
+-
+- /*
+- * First waiter. Set the waiters bit before attaching ourself to
+- * the owner. If owner tries to unlock, it will be forced into
+- * the kernel and blocked on hb->lock.
+- */
+- newval = uval | FUTEX_WAITERS;
+- ret = lock_pi_update_atomic(uaddr, uval, newval);
+- if (ret)
+- return ret;
+- /*
+- * If the update of the user space value succeeded, we try to
+- * attach to the owner. If that fails, no harm done, we only
+- * set the FUTEX_WAITERS bit in the user space variable.
+- */
+- return attach_to_pi_owner(uaddr, newval, key, ps, exiting);
+-}
+-
+-/**
+- * __unqueue_futex() - Remove the futex_q from its futex_hash_bucket
+- * @q: The futex_q to unqueue
+- *
+- * The q->lock_ptr must not be NULL and must be held by the caller.
+- */
+-static void __unqueue_futex(struct futex_q *q)
+-{
+- struct futex_hash_bucket *hb;
+-
+- if (WARN_ON_SMP(!q->lock_ptr) || WARN_ON(plist_node_empty(&q->list)))
+- return;
+- lockdep_assert_held(q->lock_ptr);
+-
+- hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock);
+- plist_del(&q->list, &hb->chain);
+- hb_waiters_dec(hb);
+-}
+-
+-/*
+- * The hash bucket lock must be held when this is called.
+- * Afterwards, the futex_q must not be accessed. Callers
+- * must ensure to later call wake_up_q() for the actual
+- * wakeups to occur.
+- */
+-static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
+-{
+- struct task_struct *p = q->task;
+-
+- if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
+- return;
+-
+- get_task_struct(p);
+- __unqueue_futex(q);
+- /*
+- * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
+- * is written, without taking any locks. This is possible in the event
+- * of a spurious wakeup, for example. A memory barrier is required here
+- * to prevent the following store to lock_ptr from getting ahead of the
+- * plist_del in __unqueue_futex().
+- */
+- smp_store_release(&q->lock_ptr, NULL);
+-
+- /*
+- * Queue the task for later wakeup for after we've released
+- * the hb->lock.
+- */
+- wake_q_add_safe(wake_q, p);
+-}
+-
+-/*
+- * Caller must hold a reference on @pi_state.
+- */
+-static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state)
+-{
+- struct rt_mutex_waiter *top_waiter;
+- struct task_struct *new_owner;
+- bool postunlock = false;
+- DEFINE_RT_WAKE_Q(wqh);
+- u32 curval, newval;
+- int ret = 0;
+-
+- top_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex);
+- if (WARN_ON_ONCE(!top_waiter)) {
+- /*
+- * As per the comment in futex_unlock_pi() this should not happen.
+- *
+- * When this happens, give up our locks and try again, giving
+- * the futex_lock_pi() instance time to complete, either by
+- * waiting on the rtmutex or removing itself from the futex
+- * queue.
+- */
+- ret = -EAGAIN;
+- goto out_unlock;
+- }
+-
+- new_owner = top_waiter->task;
+-
+- /*
+- * We pass it to the next owner. The WAITERS bit is always kept
+- * enabled while there is PI state around. We cleanup the owner
+- * died bit, because we are the owner.
+- */
+- newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
+-
+- if (unlikely(should_fail_futex(true))) {
+- ret = -EFAULT;
+- goto out_unlock;
+- }
+-
+- ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
+- if (!ret && (curval != uval)) {
+- /*
+- * If a unconditional UNLOCK_PI operation (user space did not
+- * try the TID->0 transition) raced with a waiter setting the
+- * FUTEX_WAITERS flag between get_user() and locking the hash
+- * bucket lock, retry the operation.
+- */
+- if ((FUTEX_TID_MASK & curval) == uval)
+- ret = -EAGAIN;
+- else
+- ret = -EINVAL;
+- }
+-
+- if (!ret) {
+- /*
+- * This is a point of no return; once we modified the uval
+- * there is no going back and subsequent operations must
+- * not fail.
+- */
+- pi_state_update_owner(pi_state, new_owner);
+- postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wqh);
+- }
+-
+-out_unlock:
+- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+-
+- if (postunlock)
+- rt_mutex_postunlock(&wqh);
+-
+- return ret;
+-}
+-
+-/*
+- * Express the locking dependencies for lockdep:
+- */
+-static inline void
+-double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
+-{
+- if (hb1 <= hb2) {
+- spin_lock(&hb1->lock);
+- if (hb1 < hb2)
+- spin_lock_nested(&hb2->lock, SINGLE_DEPTH_NESTING);
+- } else { /* hb1 > hb2 */
+- spin_lock(&hb2->lock);
+- spin_lock_nested(&hb1->lock, SINGLE_DEPTH_NESTING);
+- }
+-}
+-
+-static inline void
+-double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
+-{
+- spin_unlock(&hb1->lock);
+- if (hb1 != hb2)
+- spin_unlock(&hb2->lock);
+-}
+-
+-/*
+- * Wake up waiters matching bitset queued on this futex (uaddr).
+- */
+-static int
+-futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
+-{
+- struct futex_hash_bucket *hb;
+- struct futex_q *this, *next;
+- union futex_key key = FUTEX_KEY_INIT;
+- int ret;
+- DEFINE_WAKE_Q(wake_q);
+-
+- if (!bitset)
+- return -EINVAL;
+-
+- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, FUTEX_READ);
+- if (unlikely(ret != 0))
+- return ret;
+-
+- hb = hash_futex(&key);
+-
+- /* Make sure we really have tasks to wakeup */
+- if (!hb_waiters_pending(hb))
+- return ret;
+-
+- spin_lock(&hb->lock);
+-
+- plist_for_each_entry_safe(this, next, &hb->chain, list) {
+- if (match_futex (&this->key, &key)) {
+- if (this->pi_state || this->rt_waiter) {
+- ret = -EINVAL;
+- break;
+- }
+-
+- /* Check if one of the bits is set in both bitsets */
+- if (!(this->bitset & bitset))
+- continue;
+-
+- mark_wake_futex(&wake_q, this);
+- if (++ret >= nr_wake)
+- break;
+- }
+- }
+-
+- spin_unlock(&hb->lock);
+- wake_up_q(&wake_q);
+- return ret;
+-}
+-
+-static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
+-{
+- unsigned int op = (encoded_op & 0x70000000) >> 28;
+- unsigned int cmp = (encoded_op & 0x0f000000) >> 24;
+- int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 11);
+- int cmparg = sign_extend32(encoded_op & 0x00000fff, 11);
+- int oldval, ret;
+-
+- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
+- if (oparg < 0 || oparg > 31) {
+- char comm[sizeof(current->comm)];
+- /*
+- * kill this print and return -EINVAL when userspace
+- * is sane again
+- */
+- pr_info_ratelimited("futex_wake_op: %s tries to shift op by %d; fix this program\n",
+- get_task_comm(comm, current), oparg);
+- oparg &= 31;
+- }
+- oparg = 1 << oparg;
+- }
+-
+- pagefault_disable();
+- ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
+- pagefault_enable();
+- if (ret)
+- return ret;
+-
+- switch (cmp) {
+- case FUTEX_OP_CMP_EQ:
+- return oldval == cmparg;
+- case FUTEX_OP_CMP_NE:
+- return oldval != cmparg;
+- case FUTEX_OP_CMP_LT:
+- return oldval < cmparg;
+- case FUTEX_OP_CMP_GE:
+- return oldval >= cmparg;
+- case FUTEX_OP_CMP_LE:
+- return oldval <= cmparg;
+- case FUTEX_OP_CMP_GT:
+- return oldval > cmparg;
+- default:
+- return -ENOSYS;
+- }
+-}
+-
+-/*
+- * Wake up all waiters hashed on the physical page that is mapped
+- * to this virtual address:
+- */
+-static int
+-futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
+- int nr_wake, int nr_wake2, int op)
+-{
+- union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
+- struct futex_hash_bucket *hb1, *hb2;
+- struct futex_q *this, *next;
+- int ret, op_ret;
+- DEFINE_WAKE_Q(wake_q);
+-
+-retry:
+- ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
+- if (unlikely(ret != 0))
+- return ret;
+- ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
+- if (unlikely(ret != 0))
+- return ret;
+-
+- hb1 = hash_futex(&key1);
+- hb2 = hash_futex(&key2);
+-
+-retry_private:
+- double_lock_hb(hb1, hb2);
+- op_ret = futex_atomic_op_inuser(op, uaddr2);
+- if (unlikely(op_ret < 0)) {
+- double_unlock_hb(hb1, hb2);
+-
+- if (!IS_ENABLED(CONFIG_MMU) ||
+- unlikely(op_ret != -EFAULT && op_ret != -EAGAIN)) {
+- /*
+- * we don't get EFAULT from MMU faults if we don't have
+- * an MMU, but we might get them from range checking
+- */
+- ret = op_ret;
+- return ret;
+- }
+-
+- if (op_ret == -EFAULT) {
+- ret = fault_in_user_writeable(uaddr2);
+- if (ret)
+- return ret;
+- }
+-
+- cond_resched();
+- if (!(flags & FLAGS_SHARED))
+- goto retry_private;
+- goto retry;
+- }
+-
+- plist_for_each_entry_safe(this, next, &hb1->chain, list) {
+- if (match_futex (&this->key, &key1)) {
+- if (this->pi_state || this->rt_waiter) {
+- ret = -EINVAL;
+- goto out_unlock;
+- }
+- mark_wake_futex(&wake_q, this);
+- if (++ret >= nr_wake)
+- break;
+- }
+- }
+-
+- if (op_ret > 0) {
+- op_ret = 0;
+- plist_for_each_entry_safe(this, next, &hb2->chain, list) {
+- if (match_futex (&this->key, &key2)) {
+- if (this->pi_state || this->rt_waiter) {
+- ret = -EINVAL;
+- goto out_unlock;
+- }
+- mark_wake_futex(&wake_q, this);
+- if (++op_ret >= nr_wake2)
+- break;
+- }
+- }
+- ret += op_ret;
+- }
+-
+-out_unlock:
+- double_unlock_hb(hb1, hb2);
+- wake_up_q(&wake_q);
+- return ret;
+-}
+-
+-/**
+- * requeue_futex() - Requeue a futex_q from one hb to another
+- * @q: the futex_q to requeue
+- * @hb1: the source hash_bucket
+- * @hb2: the target hash_bucket
+- * @key2: the new key for the requeued futex_q
+- */
+-static inline
+-void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
+- struct futex_hash_bucket *hb2, union futex_key *key2)
+-{
+-
+- /*
+- * If key1 and key2 hash to the same bucket, no need to
+- * requeue.
+- */
+- if (likely(&hb1->chain != &hb2->chain)) {
+- plist_del(&q->list, &hb1->chain);
+- hb_waiters_dec(hb1);
+- hb_waiters_inc(hb2);
+- plist_add(&q->list, &hb2->chain);
+- q->lock_ptr = &hb2->lock;
+- }
+- q->key = *key2;
+-}
+-
+-static inline bool futex_requeue_pi_prepare(struct futex_q *q,
+- struct futex_pi_state *pi_state)
+-{
+- int old, new;
+-
+- /*
+- * Set state to Q_REQUEUE_PI_IN_PROGRESS unless an early wakeup has
+- * already set Q_REQUEUE_PI_IGNORE to signal that requeue should
+- * ignore the waiter.
+- */
+- old = atomic_read_acquire(&q->requeue_state);
+- do {
+- if (old == Q_REQUEUE_PI_IGNORE)
+- return false;
+-
+- /*
+- * futex_proxy_trylock_atomic() might have set it to
+- * IN_PROGRESS and a interleaved early wake to WAIT.
+- *
+- * It was considered to have an extra state for that
+- * trylock, but that would just add more conditionals
+- * all over the place for a dubious value.
+- */
+- if (old != Q_REQUEUE_PI_NONE)
+- break;
+-
+- new = Q_REQUEUE_PI_IN_PROGRESS;
+- } while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
+-
+- q->pi_state = pi_state;
+- return true;
+-}
+-
+-static inline void futex_requeue_pi_complete(struct futex_q *q, int locked)
+-{
+- int old, new;
+-
+- old = atomic_read_acquire(&q->requeue_state);
+- do {
+- if (old == Q_REQUEUE_PI_IGNORE)
+- return;
+-
+- if (locked >= 0) {
+- /* Requeue succeeded. Set DONE or LOCKED */
+- WARN_ON_ONCE(old != Q_REQUEUE_PI_IN_PROGRESS &&
+- old != Q_REQUEUE_PI_WAIT);
+- new = Q_REQUEUE_PI_DONE + locked;
+- } else if (old == Q_REQUEUE_PI_IN_PROGRESS) {
+- /* Deadlock, no early wakeup interleave */
+- new = Q_REQUEUE_PI_NONE;
+- } else {
+- /* Deadlock, early wakeup interleave. */
+- WARN_ON_ONCE(old != Q_REQUEUE_PI_WAIT);
+- new = Q_REQUEUE_PI_IGNORE;
+- }
+- } while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
+-
+-#ifdef CONFIG_PREEMPT_RT
+- /* If the waiter interleaved with the requeue let it know */
+- if (unlikely(old == Q_REQUEUE_PI_WAIT))
+- rcuwait_wake_up(&q->requeue_wait);
+-#endif
+-}
+-
+-static inline int futex_requeue_pi_wakeup_sync(struct futex_q *q)
+-{
+- int old, new;
+-
+- old = atomic_read_acquire(&q->requeue_state);
+- do {
+- /* Is requeue done already? */
+- if (old >= Q_REQUEUE_PI_DONE)
+- return old;
+-
+- /*
+- * If not done, then tell the requeue code to either ignore
+- * the waiter or to wake it up once the requeue is done.
+- */
+- new = Q_REQUEUE_PI_WAIT;
+- if (old == Q_REQUEUE_PI_NONE)
+- new = Q_REQUEUE_PI_IGNORE;
+- } while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
+-
+- /* If the requeue was in progress, wait for it to complete */
+- if (old == Q_REQUEUE_PI_IN_PROGRESS) {
+-#ifdef CONFIG_PREEMPT_RT
+- rcuwait_wait_event(&q->requeue_wait,
+- atomic_read(&q->requeue_state) != Q_REQUEUE_PI_WAIT,
+- TASK_UNINTERRUPTIBLE);
+-#else
+- (void)atomic_cond_read_relaxed(&q->requeue_state, VAL != Q_REQUEUE_PI_WAIT);
+-#endif
+- }
+-
+- /*
+- * Requeue is now either prohibited or complete. Reread state
+- * because during the wait above it might have changed. Nothing
+- * will modify q->requeue_state after this point.
+- */
+- return atomic_read(&q->requeue_state);
+-}
+-
+-/**
+- * requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
+- * @q: the futex_q
+- * @key: the key of the requeue target futex
+- * @hb: the hash_bucket of the requeue target futex
+- *
+- * During futex_requeue, with requeue_pi=1, it is possible to acquire the
+- * target futex if it is uncontended or via a lock steal.
+- *
+- * 1) Set @q::key to the requeue target futex key so the waiter can detect
+- * the wakeup on the right futex.
+- *
+- * 2) Dequeue @q from the hash bucket.
+- *
+- * 3) Set @q::rt_waiter to NULL so the woken up task can detect atomic lock
+- * acquisition.
+- *
+- * 4) Set the q->lock_ptr to the requeue target hb->lock for the case that
+- * the waiter has to fixup the pi state.
+- *
+- * 5) Complete the requeue state so the waiter can make progress. After
+- * this point the waiter task can return from the syscall immediately in
+- * case that the pi state does not have to be fixed up.
+- *
+- * 6) Wake the waiter task.
+- *
+- * Must be called with both q->lock_ptr and hb->lock held.
+- */
+-static inline
+-void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
+- struct futex_hash_bucket *hb)
+-{
+- q->key = *key;
+-
+- __unqueue_futex(q);
+-
+- WARN_ON(!q->rt_waiter);
+- q->rt_waiter = NULL;
+-
+- q->lock_ptr = &hb->lock;
+-
+- /* Signal locked state to the waiter */
+- futex_requeue_pi_complete(q, 1);
+- wake_up_state(q->task, TASK_NORMAL);
+-}
+-
+-/**
+- * futex_proxy_trylock_atomic() - Attempt an atomic lock for the top waiter
+- * @pifutex: the user address of the to futex
+- * @hb1: the from futex hash bucket, must be locked by the caller
+- * @hb2: the to futex hash bucket, must be locked by the caller
+- * @key1: the from futex key
+- * @key2: the to futex key
+- * @ps: address to store the pi_state pointer
+- * @exiting: Pointer to store the task pointer of the owner task
+- * which is in the middle of exiting
+- * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0)
+- *
+- * Try and get the lock on behalf of the top waiter if we can do it atomically.
+- * Wake the top waiter if we succeed. If the caller specified set_waiters,
+- * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit.
+- * hb1 and hb2 must be held by the caller.
+- *
+- * @exiting is only set when the return value is -EBUSY. If so, this holds
+- * a refcount on the exiting task on return and the caller needs to drop it
+- * after waiting for the exit to complete.
+- *
+- * Return:
+- * - 0 - failed to acquire the lock atomically;
+- * - >0 - acquired the lock, return value is vpid of the top_waiter
+- * - <0 - error
+- */
+-static int
+-futex_proxy_trylock_atomic(u32 __user *pifutex, struct futex_hash_bucket *hb1,
+- struct futex_hash_bucket *hb2, union futex_key *key1,
+- union futex_key *key2, struct futex_pi_state **ps,
+- struct task_struct **exiting, int set_waiters)
+-{
+- struct futex_q *top_waiter = NULL;
+- u32 curval;
+- int ret;
+-
+- if (get_futex_value_locked(&curval, pifutex))
+- return -EFAULT;
+-
+- if (unlikely(should_fail_futex(true)))
+- return -EFAULT;
+-
+- /*
+- * Find the top_waiter and determine if there are additional waiters.
+- * If the caller intends to requeue more than 1 waiter to pifutex,
+- * force futex_lock_pi_atomic() to set the FUTEX_WAITERS bit now,
+- * as we have means to handle the possible fault. If not, don't set
+- * the bit unnecessarily as it will force the subsequent unlock to enter
+- * the kernel.
+- */
+- top_waiter = futex_top_waiter(hb1, key1);
+-
+- /* There are no waiters, nothing for us to do. */
+- if (!top_waiter)
+- return 0;
+-
+- /*
+- * Ensure that this is a waiter sitting in futex_wait_requeue_pi()
+- * and waiting on the 'waitqueue' futex which is always !PI.
+- */
+- if (!top_waiter->rt_waiter || top_waiter->pi_state)
+- return -EINVAL;
+-
+- /* Ensure we requeue to the expected futex. */
+- if (!match_futex(top_waiter->requeue_pi_key, key2))
+- return -EINVAL;
+-
+- /* Ensure that this does not race against an early wakeup */
+- if (!futex_requeue_pi_prepare(top_waiter, NULL))
+- return -EAGAIN;
+-
+- /*
+- * Try to take the lock for top_waiter and set the FUTEX_WAITERS bit
+- * in the contended case or if @set_waiters is true.
+- *
+- * In the contended case PI state is attached to the lock owner. If
+- * the user space lock can be acquired then PI state is attached to
+- * the new owner (@top_waiter->task) when @set_waiters is true.
+- */
+- ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
+- exiting, set_waiters);
+- if (ret == 1) {
+- /*
+- * Lock was acquired in user space and PI state was
+- * attached to @top_waiter->task. That means state is fully
+- * consistent and the waiter can return to user space
+- * immediately after the wakeup.
+- */
+- requeue_pi_wake_futex(top_waiter, key2, hb2);
+- } else if (ret < 0) {
+- /* Rewind top_waiter::requeue_state */
+- futex_requeue_pi_complete(top_waiter, ret);
+- } else {
+- /*
+- * futex_lock_pi_atomic() did not acquire the user space
+- * futex, but managed to establish the proxy lock and pi
+- * state. top_waiter::requeue_state cannot be fixed up here
+- * because the waiter is not enqueued on the rtmutex
+- * yet. This is handled at the callsite depending on the
+- * result of rt_mutex_start_proxy_lock() which is
+- * guaranteed to be reached with this function returning 0.
+- */
+- }
+- return ret;
+-}
+-
+-/**
+- * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
+- * @uaddr1: source futex user address
+- * @flags: futex flags (FLAGS_SHARED, etc.)
+- * @uaddr2: target futex user address
+- * @nr_wake: number of waiters to wake (must be 1 for requeue_pi)
+- * @nr_requeue: number of waiters to requeue (0-INT_MAX)
+- * @cmpval: @uaddr1 expected value (or %NULL)
+- * @requeue_pi: if we are attempting to requeue from a non-pi futex to a
+- * pi futex (pi to pi requeue is not supported)
+- *
+- * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
+- * uaddr2 atomically on behalf of the top waiter.
+- *
+- * Return:
+- * - >=0 - on success, the number of tasks requeued or woken;
+- * - <0 - on error
+- */
+-static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
+- u32 __user *uaddr2, int nr_wake, int nr_requeue,
+- u32 *cmpval, int requeue_pi)
+-{
+- union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
+- int task_count = 0, ret;
+- struct futex_pi_state *pi_state = NULL;
+- struct futex_hash_bucket *hb1, *hb2;
+- struct futex_q *this, *next;
+- DEFINE_WAKE_Q(wake_q);
+-
+- if (nr_wake < 0 || nr_requeue < 0)
+- return -EINVAL;
+-
+- /*
+- * When PI not supported: return -ENOSYS if requeue_pi is true,
+- * consequently the compiler knows requeue_pi is always false past
+- * this point which will optimize away all the conditional code
+- * further down.
+- */
+- if (!IS_ENABLED(CONFIG_FUTEX_PI) && requeue_pi)
+- return -ENOSYS;
+-
+- if (requeue_pi) {
+- /*
+- * Requeue PI only works on two distinct uaddrs. This
+- * check is only valid for private futexes. See below.
+- */
+- if (uaddr1 == uaddr2)
+- return -EINVAL;
+-
+- /*
+- * futex_requeue() allows the caller to define the number
+- * of waiters to wake up via the @nr_wake argument. With
+- * REQUEUE_PI, waking up more than one waiter is creating
+- * more problems than it solves. Waking up a waiter makes
+- * only sense if the PI futex @uaddr2 is uncontended as
+- * this allows the requeue code to acquire the futex
+- * @uaddr2 before waking the waiter. The waiter can then
+- * return to user space without further action. A secondary
+- * wakeup would just make the futex_wait_requeue_pi()
+- * handling more complex, because that code would have to
+- * look up pi_state and do more or less all the handling
+- * which the requeue code has to do for the to be requeued
+- * waiters. So restrict the number of waiters to wake to
+- * one, and only wake it up when the PI futex is
+- * uncontended. Otherwise requeue it and let the unlock of
+- * the PI futex handle the wakeup.
+- *
+- * All REQUEUE_PI users, e.g. pthread_cond_signal() and
+- * pthread_cond_broadcast() must use nr_wake=1.
+- */
+- if (nr_wake != 1)
+- return -EINVAL;
+-
+- /*
+- * requeue_pi requires a pi_state, try to allocate it now
+- * without any locks in case it fails.
+- */
+- if (refill_pi_state_cache())
+- return -ENOMEM;
+- }
+-
+-retry:
+- ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
+- if (unlikely(ret != 0))
+- return ret;
+- ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
+- requeue_pi ? FUTEX_WRITE : FUTEX_READ);
+- if (unlikely(ret != 0))
+- return ret;
+-
+- /*
+- * The check above which compares uaddrs is not sufficient for
+- * shared futexes. We need to compare the keys:
+- */
+- if (requeue_pi && match_futex(&key1, &key2))
+- return -EINVAL;
+-
+- hb1 = hash_futex(&key1);
+- hb2 = hash_futex(&key2);
+-
+-retry_private:
+- hb_waiters_inc(hb2);
+- double_lock_hb(hb1, hb2);
+-
+- if (likely(cmpval != NULL)) {
+- u32 curval;
+-
+- ret = get_futex_value_locked(&curval, uaddr1);
+-
+- if (unlikely(ret)) {
+- double_unlock_hb(hb1, hb2);
+- hb_waiters_dec(hb2);
+-
+- ret = get_user(curval, uaddr1);
+- if (ret)
+- return ret;
+-
+- if (!(flags & FLAGS_SHARED))
+- goto retry_private;
+-
+- goto retry;
+- }
+- if (curval != *cmpval) {
+- ret = -EAGAIN;
+- goto out_unlock;
+- }
+- }
+-
+- if (requeue_pi) {
+- struct task_struct *exiting = NULL;
+-
+- /*
+- * Attempt to acquire uaddr2 and wake the top waiter. If we
+- * intend to requeue waiters, force setting the FUTEX_WAITERS
+- * bit. We force this here where we are able to easily handle
+- * faults rather in the requeue loop below.
+- *
+- * Updates topwaiter::requeue_state if a top waiter exists.
+- */
+- ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1,
+- &key2, &pi_state,
+- &exiting, nr_requeue);
+-
+- /*
+- * At this point the top_waiter has either taken uaddr2 or
+- * is waiting on it. In both cases pi_state has been
+- * established and an initial refcount on it. In case of an
+- * error there's nothing.
+- *
+- * The top waiter's requeue_state is up to date:
+- *
+- * - If the lock was acquired atomically (ret == 1), then
+- * the state is Q_REQUEUE_PI_LOCKED.
+- *
+- * The top waiter has been dequeued and woken up and can
+- * return to user space immediately. The kernel/user
+- * space state is consistent. In case that there must be
+- * more waiters requeued the WAITERS bit in the user
+- * space futex is set so the top waiter task has to go
+- * into the syscall slowpath to unlock the futex. This
+- * will block until this requeue operation has been
+- * completed and the hash bucket locks have been
+- * dropped.
+- *
+- * - If the trylock failed with an error (ret < 0) then
+- * the state is either Q_REQUEUE_PI_NONE, i.e. "nothing
+- * happened", or Q_REQUEUE_PI_IGNORE when there was an
+- * interleaved early wakeup.
+- *
+- * - If the trylock did not succeed (ret == 0) then the
+- * state is either Q_REQUEUE_PI_IN_PROGRESS or
+- * Q_REQUEUE_PI_WAIT if an early wakeup interleaved.
+- * This will be cleaned up in the loop below, which
+- * cannot fail because futex_proxy_trylock_atomic() did
+- * the same sanity checks for requeue_pi as the loop
+- * below does.
+- */
+- switch (ret) {
+- case 0:
+- /* We hold a reference on the pi state. */
+- break;
+-
+- case 1:
+- /*
+- * futex_proxy_trylock_atomic() acquired the user space
+- * futex. Adjust task_count.
+- */
+- task_count++;
+- ret = 0;
+- break;
+-
+- /*
+- * If the above failed, then pi_state is NULL and
+- * waiter::requeue_state is correct.
+- */
+- case -EFAULT:
+- double_unlock_hb(hb1, hb2);
+- hb_waiters_dec(hb2);
+- ret = fault_in_user_writeable(uaddr2);
+- if (!ret)
+- goto retry;
+- return ret;
+- case -EBUSY:
+- case -EAGAIN:
+- /*
+- * Two reasons for this:
+- * - EBUSY: Owner is exiting and we just wait for the
+- * exit to complete.
+- * - EAGAIN: The user space value changed.
+- */
+- double_unlock_hb(hb1, hb2);
+- hb_waiters_dec(hb2);
+- /*
+- * Handle the case where the owner is in the middle of
+- * exiting. Wait for the exit to complete otherwise
+- * this task might loop forever, aka. live lock.
+- */
+- wait_for_owner_exiting(ret, exiting);
+- cond_resched();
+- goto retry;
+- default:
+- goto out_unlock;
+- }
+- }
+-
+- plist_for_each_entry_safe(this, next, &hb1->chain, list) {
+- if (task_count - nr_wake >= nr_requeue)
+- break;
+-
+- if (!match_futex(&this->key, &key1))
+- continue;
+-
+- /*
+- * FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI should always
+- * be paired with each other and no other futex ops.
+- *
+- * We should never be requeueing a futex_q with a pi_state,
+- * which is awaiting a futex_unlock_pi().
+- */
+- if ((requeue_pi && !this->rt_waiter) ||
+- (!requeue_pi && this->rt_waiter) ||
+- this->pi_state) {
+- ret = -EINVAL;
+- break;
+- }
+-
+- /* Plain futexes just wake or requeue and are done */
+- if (!requeue_pi) {
+- if (++task_count <= nr_wake)
+- mark_wake_futex(&wake_q, this);
+- else
+- requeue_futex(this, hb1, hb2, &key2);
+- continue;
+- }
+-
+- /* Ensure we requeue to the expected futex for requeue_pi. */
+- if (!match_futex(this->requeue_pi_key, &key2)) {
+- ret = -EINVAL;
+- break;
+- }
+-
+- /*
+- * Requeue nr_requeue waiters and possibly one more in the case
+- * of requeue_pi if we couldn't acquire the lock atomically.
+- *
+- * Prepare the waiter to take the rt_mutex. Take a refcount
+- * on the pi_state and store the pointer in the futex_q
+- * object of the waiter.
+- */
+- get_pi_state(pi_state);
+-
+- /* Don't requeue when the waiter is already on the way out. */
+- if (!futex_requeue_pi_prepare(this, pi_state)) {
+- /*
+- * Early woken waiter signaled that it is on the
+- * way out. Drop the pi_state reference and try the
+- * next waiter. @this->pi_state is still NULL.
+- */
+- put_pi_state(pi_state);
+- continue;
+- }
+-
+- ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
+- this->rt_waiter,
+- this->task);
+-
+- if (ret == 1) {
+- /*
+- * We got the lock. We do neither drop the refcount
+- * on pi_state nor clear this->pi_state because the
+- * waiter needs the pi_state for cleaning up the
+- * user space value. It will drop the refcount
+- * after doing so. this::requeue_state is updated
+- * in the wakeup as well.
+- */
+- requeue_pi_wake_futex(this, &key2, hb2);
+- task_count++;
+- } else if (!ret) {
+- /* Waiter is queued, move it to hb2 */
+- requeue_futex(this, hb1, hb2, &key2);
+- futex_requeue_pi_complete(this, 0);
+- task_count++;
+- } else {
+- /*
+- * rt_mutex_start_proxy_lock() detected a potential
+- * deadlock when we tried to queue that waiter.
+- * Drop the pi_state reference which we took above
+- * and remove the pointer to the state from the
+- * waiters futex_q object.
+- */
+- this->pi_state = NULL;
+- put_pi_state(pi_state);
+- futex_requeue_pi_complete(this, ret);
+- /*
+- * We stop queueing more waiters and let user space
+- * deal with the mess.
+- */
+- break;
+- }
+- }
+-
+- /*
+- * We took an extra initial reference to the pi_state in
+- * futex_proxy_trylock_atomic(). We need to drop it here again.
+- */
+- put_pi_state(pi_state);
+-
+-out_unlock:
+- double_unlock_hb(hb1, hb2);
+- wake_up_q(&wake_q);
+- hb_waiters_dec(hb2);
+- return ret ? ret : task_count;
+-}
+-
+-/* The key must be already stored in q->key. */
+-static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
+- __acquires(&hb->lock)
+-{
+- struct futex_hash_bucket *hb;
+-
+- hb = hash_futex(&q->key);
+-
+- /*
+- * Increment the counter before taking the lock so that
+- * a potential waker won't miss a to-be-slept task that is
+- * waiting for the spinlock. This is safe as all queue_lock()
+- * users end up calling queue_me(). Similarly, for housekeeping,
+- * decrement the counter at queue_unlock() when some error has
+- * occurred and we don't end up adding the task to the list.
+- */
+- hb_waiters_inc(hb); /* implies smp_mb(); (A) */
+-
+- q->lock_ptr = &hb->lock;
+-
+- spin_lock(&hb->lock);
+- return hb;
+-}
+-
+-static inline void
+-queue_unlock(struct futex_hash_bucket *hb)
+- __releases(&hb->lock)
+-{
+- spin_unlock(&hb->lock);
+- hb_waiters_dec(hb);
+-}
+-
+-static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
+-{
+- int prio;
+-
+- /*
+- * The priority used to register this element is
+- * - either the real thread-priority for the real-time threads
+- * (i.e. threads with a priority lower than MAX_RT_PRIO)
+- * - or MAX_RT_PRIO for non-RT threads.
+- * Thus, all RT-threads are woken first in priority order, and
+- * the others are woken last, in FIFO order.
+- */
+- prio = min(current->normal_prio, MAX_RT_PRIO);
+-
+- plist_node_init(&q->list, prio);
+- plist_add(&q->list, &hb->chain);
+- q->task = current;
+-}
+-
+-/**
+- * queue_me() - Enqueue the futex_q on the futex_hash_bucket
+- * @q: The futex_q to enqueue
+- * @hb: The destination hash bucket
+- *
+- * The hb->lock must be held by the caller, and is released here. A call to
+- * queue_me() is typically paired with exactly one call to unqueue_me(). The
+- * exceptions involve the PI related operations, which may use unqueue_me_pi()
+- * or nothing if the unqueue is done as part of the wake process and the unqueue
+- * state is implicit in the state of woken task (see futex_wait_requeue_pi() for
+- * an example).
+- */
+-static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
+- __releases(&hb->lock)
+-{
+- __queue_me(q, hb);
+- spin_unlock(&hb->lock);
+-}
+-
+-/**
+- * unqueue_me() - Remove the futex_q from its futex_hash_bucket
+- * @q: The futex_q to unqueue
+- *
+- * The q->lock_ptr must not be held by the caller. A call to unqueue_me() must
+- * be paired with exactly one earlier call to queue_me().
+- *
+- * Return:
+- * - 1 - if the futex_q was still queued (and we removed unqueued it);
+- * - 0 - if the futex_q was already removed by the waking thread
+- */
+-static int unqueue_me(struct futex_q *q)
+-{
+- spinlock_t *lock_ptr;
+- int ret = 0;
+-
+- /* In the common case we don't take the spinlock, which is nice. */
+-retry:
+- /*
+- * q->lock_ptr can change between this read and the following spin_lock.
+- * Use READ_ONCE to forbid the compiler from reloading q->lock_ptr and
+- * optimizing lock_ptr out of the logic below.
+- */
+- lock_ptr = READ_ONCE(q->lock_ptr);
+- if (lock_ptr != NULL) {
+- spin_lock(lock_ptr);
+- /*
+- * q->lock_ptr can change between reading it and
+- * spin_lock(), causing us to take the wrong lock. This
+- * corrects the race condition.
+- *
+- * Reasoning goes like this: if we have the wrong lock,
+- * q->lock_ptr must have changed (maybe several times)
+- * between reading it and the spin_lock(). It can
+- * change again after the spin_lock() but only if it was
+- * already changed before the spin_lock(). It cannot,
+- * however, change back to the original value. Therefore
+- * we can detect whether we acquired the correct lock.
+- */
+- if (unlikely(lock_ptr != q->lock_ptr)) {
+- spin_unlock(lock_ptr);
+- goto retry;
+- }
+- __unqueue_futex(q);
+-
+- BUG_ON(q->pi_state);
+-
+- spin_unlock(lock_ptr);
+- ret = 1;
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * PI futexes can not be requeued and must remove themselves from the
+- * hash bucket. The hash bucket lock (i.e. lock_ptr) is held.
+- */
+-static void unqueue_me_pi(struct futex_q *q)
+-{
+- __unqueue_futex(q);
+-
+- BUG_ON(!q->pi_state);
+- put_pi_state(q->pi_state);
+- q->pi_state = NULL;
+-}
+-
+-static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
+- struct task_struct *argowner)
+-{
+- struct futex_pi_state *pi_state = q->pi_state;
+- struct task_struct *oldowner, *newowner;
+- u32 uval, curval, newval, newtid;
+- int err = 0;
+-
+- oldowner = pi_state->owner;
+-
+- /*
+- * We are here because either:
+- *
+- * - we stole the lock and pi_state->owner needs updating to reflect
+- * that (@argowner == current),
+- *
+- * or:
+- *
+- * - someone stole our lock and we need to fix things to point to the
+- * new owner (@argowner == NULL).
+- *
+- * Either way, we have to replace the TID in the user space variable.
+- * This must be atomic as we have to preserve the owner died bit here.
+- *
+- * Note: We write the user space value _before_ changing the pi_state
+- * because we can fault here. Imagine swapped out pages or a fork
+- * that marked all the anonymous memory readonly for cow.
+- *
+- * Modifying pi_state _before_ the user space value would leave the
+- * pi_state in an inconsistent state when we fault here, because we
+- * need to drop the locks to handle the fault. This might be observed
+- * in the PID checks when attaching to PI state .
+- */
+-retry:
+- if (!argowner) {
+- if (oldowner != current) {
+- /*
+- * We raced against a concurrent self; things are
+- * already fixed up. Nothing to do.
+- */
+- return 0;
+- }
+-
+- if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
+- /* We got the lock. pi_state is correct. Tell caller. */
+- return 1;
+- }
+-
+- /*
+- * The trylock just failed, so either there is an owner or
+- * there is a higher priority waiter than this one.
+- */
+- newowner = rt_mutex_owner(&pi_state->pi_mutex);
+- /*
+- * If the higher priority waiter has not yet taken over the
+- * rtmutex then newowner is NULL. We can't return here with
+- * that state because it's inconsistent vs. the user space
+- * state. So drop the locks and try again. It's a valid
+- * situation and not any different from the other retry
+- * conditions.
+- */
+- if (unlikely(!newowner)) {
+- err = -EAGAIN;
+- goto handle_err;
+- }
+- } else {
+- WARN_ON_ONCE(argowner != current);
+- if (oldowner == current) {
+- /*
+- * We raced against a concurrent self; things are
+- * already fixed up. Nothing to do.
+- */
+- return 1;
+- }
+- newowner = argowner;
+- }
+-
+- newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
+- /* Owner died? */
+- if (!pi_state->owner)
+- newtid |= FUTEX_OWNER_DIED;
+-
+- err = get_futex_value_locked(&uval, uaddr);
+- if (err)
+- goto handle_err;
+-
+- for (;;) {
+- newval = (uval & FUTEX_OWNER_DIED) | newtid;
+-
+- err = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval);
+- if (err)
+- goto handle_err;
+-
+- if (curval == uval)
+- break;
+- uval = curval;
+- }
+-
+- /*
+- * We fixed up user space. Now we need to fix the pi_state
+- * itself.
+- */
+- pi_state_update_owner(pi_state, newowner);
+-
+- return argowner == current;
+-
+- /*
+- * In order to reschedule or handle a page fault, we need to drop the
+- * locks here. In the case of a fault, this gives the other task
+- * (either the highest priority waiter itself or the task which stole
+- * the rtmutex) the chance to try the fixup of the pi_state. So once we
+- * are back from handling the fault we need to check the pi_state after
+- * reacquiring the locks and before trying to do another fixup. When
+- * the fixup has been done already we simply return.
+- *
+- * Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely
+- * drop hb->lock since the caller owns the hb -> futex_q relation.
+- * Dropping the pi_mutex->wait_lock requires the state revalidate.
+- */
+-handle_err:
+- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+- spin_unlock(q->lock_ptr);
+-
+- switch (err) {
+- case -EFAULT:
+- err = fault_in_user_writeable(uaddr);
+- break;
+-
+- case -EAGAIN:
+- cond_resched();
+- err = 0;
+- break;
+-
+- default:
+- WARN_ON_ONCE(1);
+- break;
+- }
+-
+- spin_lock(q->lock_ptr);
+- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+-
+- /*
+- * Check if someone else fixed it for us:
+- */
+- if (pi_state->owner != oldowner)
+- return argowner == current;
+-
+- /* Retry if err was -EAGAIN or the fault in succeeded */
+- if (!err)
+- goto retry;
+-
+- /*
+- * fault_in_user_writeable() failed so user state is immutable. At
+- * best we can make the kernel state consistent but user state will
+- * be most likely hosed and any subsequent unlock operation will be
+- * rejected due to PI futex rule [10].
+- *
+- * Ensure that the rtmutex owner is also the pi_state owner despite
+- * the user space value claiming something different. There is no
+- * point in unlocking the rtmutex if current is the owner as it
+- * would need to wait until the next waiter has taken the rtmutex
+- * to guarantee consistent state. Keep it simple. Userspace asked
+- * for this wreckaged state.
+- *
+- * The rtmutex has an owner - either current or some other
+- * task. See the EAGAIN loop above.
+- */
+- pi_state_update_owner(pi_state, rt_mutex_owner(&pi_state->pi_mutex));
+-
+- return err;
+-}
+-
+-static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
+- struct task_struct *argowner)
+-{
+- struct futex_pi_state *pi_state = q->pi_state;
+- int ret;
+-
+- lockdep_assert_held(q->lock_ptr);
+-
+- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+- ret = __fixup_pi_state_owner(uaddr, q, argowner);
+- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
+- return ret;
+-}
+-
+-static long futex_wait_restart(struct restart_block *restart);
+-
+-/**
+- * fixup_owner() - Post lock pi_state and corner case management
+- * @uaddr: user address of the futex
+- * @q: futex_q (contains pi_state and access to the rt_mutex)
+- * @locked: if the attempt to take the rt_mutex succeeded (1) or not (0)
+- *
+- * After attempting to lock an rt_mutex, this function is called to cleanup
+- * the pi_state owner as well as handle race conditions that may allow us to
+- * acquire the lock. Must be called with the hb lock held.
+- *
+- * Return:
+- * - 1 - success, lock taken;
+- * - 0 - success, lock not taken;
+- * - <0 - on error (-EFAULT)
+- */
+-static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
+-{
+- if (locked) {
+- /*
+- * Got the lock. We might not be the anticipated owner if we
+- * did a lock-steal - fix up the PI-state in that case:
+- *
+- * Speculative pi_state->owner read (we don't hold wait_lock);
+- * since we own the lock pi_state->owner == current is the
+- * stable state, anything else needs more attention.
+- */
+- if (q->pi_state->owner != current)
+- return fixup_pi_state_owner(uaddr, q, current);
+- return 1;
+- }
+-
+- /*
+- * If we didn't get the lock; check if anybody stole it from us. In
+- * that case, we need to fix up the uval to point to them instead of
+- * us, otherwise bad things happen. [10]
+- *
+- * Another speculative read; pi_state->owner == current is unstable
+- * but needs our attention.
+- */
+- if (q->pi_state->owner == current)
+- return fixup_pi_state_owner(uaddr, q, NULL);
+-
+- /*
+- * Paranoia check. If we did not take the lock, then we should not be
+- * the owner of the rt_mutex. Warn and establish consistent state.
+- */
+- if (WARN_ON_ONCE(rt_mutex_owner(&q->pi_state->pi_mutex) == current))
+- return fixup_pi_state_owner(uaddr, q, current);
+-
+- return 0;
+-}
+-
+-/**
+- * futex_wait_queue_me() - queue_me() and wait for wakeup, timeout, or signal
+- * @hb: the futex hash bucket, must be locked by the caller
+- * @q: the futex_q to queue up on
+- * @timeout: the prepared hrtimer_sleeper, or null for no timeout
+- */
+-static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
+- struct hrtimer_sleeper *timeout)
+-{
+- /*
+- * The task state is guaranteed to be set before another task can
+- * wake it. set_current_state() is implemented using smp_store_mb() and
+- * queue_me() calls spin_unlock() upon completion, both serializing
+- * access to the hash list and forcing another memory barrier.
+- */
+- set_current_state(TASK_INTERRUPTIBLE);
+- queue_me(q, hb);
+-
+- /* Arm the timer */
+- if (timeout)
+- hrtimer_sleeper_start_expires(timeout, HRTIMER_MODE_ABS);
+-
+- /*
+- * If we have been removed from the hash list, then another task
+- * has tried to wake us, and we can skip the call to schedule().
+- */
+- if (likely(!plist_node_empty(&q->list))) {
+- /*
+- * If the timer has already expired, current will already be
+- * flagged for rescheduling. Only call schedule if there
+- * is no timeout, or if it has yet to expire.
+- */
+- if (!timeout || timeout->task)
+- freezable_schedule();
+- }
+- __set_current_state(TASK_RUNNING);
+-}
+-
+-/**
+- * futex_wait_setup() - Prepare to wait on a futex
+- * @uaddr: the futex userspace address
+- * @val: the expected value
+- * @flags: futex flags (FLAGS_SHARED, etc.)
+- * @q: the associated futex_q
+- * @hb: storage for hash_bucket pointer to be returned to caller
+- *
+- * Setup the futex_q and locate the hash_bucket. Get the futex value and
+- * compare it with the expected value. Handle atomic faults internally.
+- * Return with the hb lock held on success, and unlocked on failure.
+- *
+- * Return:
+- * - 0 - uaddr contains val and hb has been locked;
+- * - <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
+- */
+-static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
+- struct futex_q *q, struct futex_hash_bucket **hb)
+-{
+- u32 uval;
+- int ret;
+-
+- /*
+- * Access the page AFTER the hash-bucket is locked.
+- * Order is important:
+- *
+- * Userspace waiter: val = var; if (cond(val)) futex_wait(&var, val);
+- * Userspace waker: if (cond(var)) { var = new; futex_wake(&var); }
+- *
+- * The basic logical guarantee of a futex is that it blocks ONLY
+- * if cond(var) is known to be true at the time of blocking, for
+- * any cond. If we locked the hash-bucket after testing *uaddr, that
+- * would open a race condition where we could block indefinitely with
+- * cond(var) false, which would violate the guarantee.
+- *
+- * On the other hand, we insert q and release the hash-bucket only
+- * after testing *uaddr. This guarantees that futex_wait() will NOT
+- * absorb a wakeup if *uaddr does not match the desired values
+- * while the syscall executes.
+- */
+-retry:
+- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key, FUTEX_READ);
+- if (unlikely(ret != 0))
+- return ret;
+-
+-retry_private:
+- *hb = queue_lock(q);
+-
+- ret = get_futex_value_locked(&uval, uaddr);
+-
+- if (ret) {
+- queue_unlock(*hb);
+-
+- ret = get_user(uval, uaddr);
+- if (ret)
+- return ret;
+-
+- if (!(flags & FLAGS_SHARED))
+- goto retry_private;
+-
+- goto retry;
+- }
+-
+- if (uval != val) {
+- queue_unlock(*hb);
+- ret = -EWOULDBLOCK;
+- }
+-
+- return ret;
+-}
+-
+-static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
+- ktime_t *abs_time, u32 bitset)
+-{
+- struct hrtimer_sleeper timeout, *to;
+- struct restart_block *restart;
+- struct futex_hash_bucket *hb;
+- struct futex_q q = futex_q_init;
+- int ret;
+-
+- if (!bitset)
+- return -EINVAL;
+- q.bitset = bitset;
+-
+- to = futex_setup_timer(abs_time, &timeout, flags,
+- current->timer_slack_ns);
+-retry:
+- /*
+- * Prepare to wait on uaddr. On success, it holds hb->lock and q
+- * is initialized.
+- */
+- ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
+- if (ret)
+- goto out;
+-
+- /* queue_me and wait for wakeup, timeout, or a signal. */
+- futex_wait_queue_me(hb, &q, to);
+-
+- /* If we were woken (and unqueued), we succeeded, whatever. */
+- ret = 0;
+- if (!unqueue_me(&q))
+- goto out;
+- ret = -ETIMEDOUT;
+- if (to && !to->task)
+- goto out;
+-
+- /*
+- * We expect signal_pending(current), but we might be the
+- * victim of a spurious wakeup as well.
+- */
+- if (!signal_pending(current))
+- goto retry;
+-
+- ret = -ERESTARTSYS;
+- if (!abs_time)
+- goto out;
+-
+- restart = &current->restart_block;
+- restart->futex.uaddr = uaddr;
+- restart->futex.val = val;
+- restart->futex.time = *abs_time;
+- restart->futex.bitset = bitset;
+- restart->futex.flags = flags | FLAGS_HAS_TIMEOUT;
+-
+- ret = set_restart_fn(restart, futex_wait_restart);
+-
+-out:
+- if (to) {
+- hrtimer_cancel(&to->timer);
+- destroy_hrtimer_on_stack(&to->timer);
+- }
+- return ret;
+-}
+-
+-
+-static long futex_wait_restart(struct restart_block *restart)
+-{
+- u32 __user *uaddr = restart->futex.uaddr;
+- ktime_t t, *tp = NULL;
+-
+- if (restart->futex.flags & FLAGS_HAS_TIMEOUT) {
+- t = restart->futex.time;
+- tp = &t;
+- }
+- restart->fn = do_no_restart_syscall;
+-
+- return (long)futex_wait(uaddr, restart->futex.flags,
+- restart->futex.val, tp, restart->futex.bitset);
+-}
+-
+-
+-/*
+- * Userspace tried a 0 -> TID atomic transition of the futex value
+- * and failed. The kernel side here does the whole locking operation:
+- * if there are waiters then it will block as a consequence of relying
+- * on rt-mutexes, it does PI, etc. (Due to races the kernel might see
+- * a 0 value of the futex too.).
+- *
+- * Also serves as futex trylock_pi()'ing, and due semantics.
+- */
+-static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
+- ktime_t *time, int trylock)
+-{
+- struct hrtimer_sleeper timeout, *to;
+- struct task_struct *exiting = NULL;
+- struct rt_mutex_waiter rt_waiter;
+- struct futex_hash_bucket *hb;
+- struct futex_q q = futex_q_init;
+- int res, ret;
+-
+- if (!IS_ENABLED(CONFIG_FUTEX_PI))
+- return -ENOSYS;
+-
+- if (refill_pi_state_cache())
+- return -ENOMEM;
+-
+- to = futex_setup_timer(time, &timeout, flags, 0);
+-
+-retry:
+- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key, FUTEX_WRITE);
+- if (unlikely(ret != 0))
+- goto out;
+-
+-retry_private:
+- hb = queue_lock(&q);
+-
+- ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current,
+- &exiting, 0);
+- if (unlikely(ret)) {
+- /*
+- * Atomic work succeeded and we got the lock,
+- * or failed. Either way, we do _not_ block.
+- */
+- switch (ret) {
+- case 1:
+- /* We got the lock. */
+- ret = 0;
+- goto out_unlock_put_key;
+- case -EFAULT:
+- goto uaddr_faulted;
+- case -EBUSY:
+- case -EAGAIN:
+- /*
+- * Two reasons for this:
+- * - EBUSY: Task is exiting and we just wait for the
+- * exit to complete.
+- * - EAGAIN: The user space value changed.
+- */
+- queue_unlock(hb);
+- /*
+- * Handle the case where the owner is in the middle of
+- * exiting. Wait for the exit to complete otherwise
+- * this task might loop forever, aka. live lock.
+- */
+- wait_for_owner_exiting(ret, exiting);
+- cond_resched();
+- goto retry;
+- default:
+- goto out_unlock_put_key;
+- }
+- }
+-
+- WARN_ON(!q.pi_state);
+-
+- /*
+- * Only actually queue now that the atomic ops are done:
+- */
+- __queue_me(&q, hb);
+-
+- if (trylock) {
+- ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex);
+- /* Fixup the trylock return value: */
+- ret = ret ? 0 : -EWOULDBLOCK;
+- goto no_block;
+- }
+-
+- rt_mutex_init_waiter(&rt_waiter);
+-
+- /*
+- * On PREEMPT_RT_FULL, when hb->lock becomes an rt_mutex, we must not
+- * hold it while doing rt_mutex_start_proxy(), because then it will
+- * include hb->lock in the blocking chain, even through we'll not in
+- * fact hold it while blocking. This will lead it to report -EDEADLK
+- * and BUG when futex_unlock_pi() interleaves with this.
+- *
+- * Therefore acquire wait_lock while holding hb->lock, but drop the
+- * latter before calling __rt_mutex_start_proxy_lock(). This
+- * interleaves with futex_unlock_pi() -- which does a similar lock
+- * handoff -- such that the latter can observe the futex_q::pi_state
+- * before __rt_mutex_start_proxy_lock() is done.
+- */
+- raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
+- spin_unlock(q.lock_ptr);
+- /*
+- * __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
+- * such that futex_unlock_pi() is guaranteed to observe the waiter when
+- * it sees the futex_q::pi_state.
+- */
+- ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
+- raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
+-
+- if (ret) {
+- if (ret == 1)
+- ret = 0;
+- goto cleanup;
+- }
+-
+- if (unlikely(to))
+- hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS);
+-
+- ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
+-
+-cleanup:
+- spin_lock(q.lock_ptr);
+- /*
+- * If we failed to acquire the lock (deadlock/signal/timeout), we must
+- * first acquire the hb->lock before removing the lock from the
+- * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
+- * lists consistent.
+- *
+- * In particular; it is important that futex_unlock_pi() can not
+- * observe this inconsistency.
+- */
+- if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter))
+- ret = 0;
+-
+-no_block:
+- /*
+- * Fixup the pi_state owner and possibly acquire the lock if we
+- * haven't already.
+- */
+- res = fixup_owner(uaddr, &q, !ret);
+- /*
+- * If fixup_owner() returned an error, propagate that. If it acquired
+- * the lock, clear our -ETIMEDOUT or -EINTR.
+- */
+- if (res)
+- ret = (res < 0) ? res : 0;
+-
+- unqueue_me_pi(&q);
+- spin_unlock(q.lock_ptr);
+- goto out;
+-
+-out_unlock_put_key:
+- queue_unlock(hb);
+-
+-out:
+- if (to) {
+- hrtimer_cancel(&to->timer);
+- destroy_hrtimer_on_stack(&to->timer);
+- }
+- return ret != -EINTR ? ret : -ERESTARTNOINTR;
+-
+-uaddr_faulted:
+- queue_unlock(hb);
+-
+- ret = fault_in_user_writeable(uaddr);
+- if (ret)
+- goto out;
+-
+- if (!(flags & FLAGS_SHARED))
+- goto retry_private;
+-
+- goto retry;
+-}
+-
+-/*
+- * Userspace attempted a TID -> 0 atomic transition, and failed.
+- * This is the in-kernel slowpath: we look up the PI state (if any),
+- * and do the rt-mutex unlock.
+- */
+-static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
+-{
+- u32 curval, uval, vpid = task_pid_vnr(current);
+- union futex_key key = FUTEX_KEY_INIT;
+- struct futex_hash_bucket *hb;
+- struct futex_q *top_waiter;
+- int ret;
+-
+- if (!IS_ENABLED(CONFIG_FUTEX_PI))
+- return -ENOSYS;
+-
+-retry:
+- if (get_user(uval, uaddr))
+- return -EFAULT;
+- /*
+- * We release only a lock we actually own:
+- */
+- if ((uval & FUTEX_TID_MASK) != vpid)
+- return -EPERM;
+-
+- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, FUTEX_WRITE);
+- if (ret)
+- return ret;
+-
+- hb = hash_futex(&key);
+- spin_lock(&hb->lock);
+-
+- /*
+- * Check waiters first. We do not trust user space values at
+- * all and we at least want to know if user space fiddled
+- * with the futex value instead of blindly unlocking.
+- */
+- top_waiter = futex_top_waiter(hb, &key);
+- if (top_waiter) {
+- struct futex_pi_state *pi_state = top_waiter->pi_state;
+-
+- ret = -EINVAL;
+- if (!pi_state)
+- goto out_unlock;
+-
+- /*
+- * If current does not own the pi_state then the futex is
+- * inconsistent and user space fiddled with the futex value.
+- */
+- if (pi_state->owner != current)
+- goto out_unlock;
+-
+- get_pi_state(pi_state);
+- /*
+- * By taking wait_lock while still holding hb->lock, we ensure
+- * there is no point where we hold neither; and therefore
+- * wake_futex_pi() must observe a state consistent with what we
+- * observed.
+- *
+- * In particular; this forces __rt_mutex_start_proxy() to
+- * complete such that we're guaranteed to observe the
+- * rt_waiter. Also see the WARN in wake_futex_pi().
+- */
+- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+- spin_unlock(&hb->lock);
+-
+- /* drops pi_state->pi_mutex.wait_lock */
+- ret = wake_futex_pi(uaddr, uval, pi_state);
+-
+- put_pi_state(pi_state);
+-
+- /*
+- * Success, we're done! No tricky corner cases.
+- */
+- if (!ret)
+- return ret;
+- /*
+- * The atomic access to the futex value generated a
+- * pagefault, so retry the user-access and the wakeup:
+- */
+- if (ret == -EFAULT)
+- goto pi_faulted;
+- /*
+- * A unconditional UNLOCK_PI op raced against a waiter
+- * setting the FUTEX_WAITERS bit. Try again.
+- */
+- if (ret == -EAGAIN)
+- goto pi_retry;
+- /*
+- * wake_futex_pi has detected invalid state. Tell user
+- * space.
+- */
+- return ret;
+- }
+-
+- /*
+- * We have no kernel internal state, i.e. no waiters in the
+- * kernel. Waiters which are about to queue themselves are stuck
+- * on hb->lock. So we can safely ignore them. We do neither
+- * preserve the WAITERS bit not the OWNER_DIED one. We are the
+- * owner.
+- */
+- if ((ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, 0))) {
+- spin_unlock(&hb->lock);
+- switch (ret) {
+- case -EFAULT:
+- goto pi_faulted;
+-
+- case -EAGAIN:
+- goto pi_retry;
+-
+- default:
+- WARN_ON_ONCE(1);
+- return ret;
+- }
+- }
+-
+- /*
+- * If uval has changed, let user space handle it.
+- */
+- ret = (curval == uval) ? 0 : -EAGAIN;
+-
+-out_unlock:
+- spin_unlock(&hb->lock);
+- return ret;
+-
+-pi_retry:
+- cond_resched();
+- goto retry;
+-
+-pi_faulted:
+-
+- ret = fault_in_user_writeable(uaddr);
+- if (!ret)
+- goto retry;
+-
+- return ret;
+-}
+-
+-/**
+- * handle_early_requeue_pi_wakeup() - Handle early wakeup on the initial futex
+- * @hb: the hash_bucket futex_q was original enqueued on
+- * @q: the futex_q woken while waiting to be requeued
+- * @timeout: the timeout associated with the wait (NULL if none)
+- *
+- * Determine the cause for the early wakeup.
+- *
+- * Return:
+- * -EWOULDBLOCK or -ETIMEDOUT or -ERESTARTNOINTR
+- */
+-static inline
+-int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
+- struct futex_q *q,
+- struct hrtimer_sleeper *timeout)
+-{
+- int ret;
+-
+- /*
+- * With the hb lock held, we avoid races while we process the wakeup.
+- * We only need to hold hb (and not hb2) to ensure atomicity as the
+- * wakeup code can't change q.key from uaddr to uaddr2 if we hold hb.
+- * It can't be requeued from uaddr2 to something else since we don't
+- * support a PI aware source futex for requeue.
+- */
+- WARN_ON_ONCE(&hb->lock != q->lock_ptr);
+-
+- /*
+- * We were woken prior to requeue by a timeout or a signal.
+- * Unqueue the futex_q and determine which it was.
+- */
+- plist_del(&q->list, &hb->chain);
+- hb_waiters_dec(hb);
+-
+- /* Handle spurious wakeups gracefully */
+- ret = -EWOULDBLOCK;
+- if (timeout && !timeout->task)
+- ret = -ETIMEDOUT;
+- else if (signal_pending(current))
+- ret = -ERESTARTNOINTR;
+- return ret;
+-}
+-
+-/**
+- * futex_wait_requeue_pi() - Wait on uaddr and take uaddr2
+- * @uaddr: the futex we initially wait on (non-pi)
+- * @flags: futex flags (FLAGS_SHARED, FLAGS_CLOCKRT, etc.), they must be
+- * the same type, no requeueing from private to shared, etc.
+- * @val: the expected value of uaddr
+- * @abs_time: absolute timeout
+- * @bitset: 32 bit wakeup bitset set by userspace, defaults to all
+- * @uaddr2: the pi futex we will take prior to returning to user-space
+- *
+- * The caller will wait on uaddr and will be requeued by futex_requeue() to
+- * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake
+- * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to
+- * userspace. This ensures the rt_mutex maintains an owner when it has waiters;
+- * without one, the pi logic would not know which task to boost/deboost, if
+- * there was a need to.
+- *
+- * We call schedule in futex_wait_queue_me() when we enqueue and return there
+- * via the following--
+- * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()
+- * 2) wakeup on uaddr2 after a requeue
+- * 3) signal
+- * 4) timeout
+- *
+- * If 3, cleanup and return -ERESTARTNOINTR.
+- *
+- * If 2, we may then block on trying to take the rt_mutex and return via:
+- * 5) successful lock
+- * 6) signal
+- * 7) timeout
+- * 8) other lock acquisition failure
+- *
+- * If 6, return -EWOULDBLOCK (restarting the syscall would do the same).
+- *
+- * If 4 or 7, we cleanup and return with -ETIMEDOUT.
+- *
+- * Return:
+- * - 0 - On success;
+- * - <0 - On error
+- */
+-static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
+- u32 val, ktime_t *abs_time, u32 bitset,
+- u32 __user *uaddr2)
+-{
+- struct hrtimer_sleeper timeout, *to;
+- struct rt_mutex_waiter rt_waiter;
+- struct futex_hash_bucket *hb;
+- union futex_key key2 = FUTEX_KEY_INIT;
+- struct futex_q q = futex_q_init;
+- struct rt_mutex_base *pi_mutex;
+- int res, ret;
+-
+- if (!IS_ENABLED(CONFIG_FUTEX_PI))
+- return -ENOSYS;
+-
+- if (uaddr == uaddr2)
+- return -EINVAL;
+-
+- if (!bitset)
+- return -EINVAL;
+-
+- to = futex_setup_timer(abs_time, &timeout, flags,
+- current->timer_slack_ns);
+-
+- /*
+- * The waiter is allocated on our stack, manipulated by the requeue
+- * code while we sleep on uaddr.
+- */
+- rt_mutex_init_waiter(&rt_waiter);
+-
+- ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
+- if (unlikely(ret != 0))
+- goto out;
+-
+- q.bitset = bitset;
+- q.rt_waiter = &rt_waiter;
+- q.requeue_pi_key = &key2;
+-
+- /*
+- * Prepare to wait on uaddr. On success, it holds hb->lock and q
+- * is initialized.
+- */
+- ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
+- if (ret)
+- goto out;
+-
+- /*
+- * The check above which compares uaddrs is not sufficient for
+- * shared futexes. We need to compare the keys:
+- */
+- if (match_futex(&q.key, &key2)) {
+- queue_unlock(hb);
+- ret = -EINVAL;
+- goto out;
+- }
+-
+- /* Queue the futex_q, drop the hb lock, wait for wakeup. */
+- futex_wait_queue_me(hb, &q, to);
+-
+- switch (futex_requeue_pi_wakeup_sync(&q)) {
+- case Q_REQUEUE_PI_IGNORE:
+- /* The waiter is still on uaddr1 */
+- spin_lock(&hb->lock);
+- ret = handle_early_requeue_pi_wakeup(hb, &q, to);
+- spin_unlock(&hb->lock);
+- break;
+-
+- case Q_REQUEUE_PI_LOCKED:
+- /* The requeue acquired the lock */
+- if (q.pi_state && (q.pi_state->owner != current)) {
+- spin_lock(q.lock_ptr);
+- ret = fixup_owner(uaddr2, &q, true);
+- /*
+- * Drop the reference to the pi state which the
+- * requeue_pi() code acquired for us.
+- */
+- put_pi_state(q.pi_state);
+- spin_unlock(q.lock_ptr);
+- /*
+- * Adjust the return value. It's either -EFAULT or
+- * success (1) but the caller expects 0 for success.
+- */
+- ret = ret < 0 ? ret : 0;
+- }
+- break;
+-
+- case Q_REQUEUE_PI_DONE:
+- /* Requeue completed. Current is 'pi_blocked_on' the rtmutex */
+- pi_mutex = &q.pi_state->pi_mutex;
+- ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
+-
+- /* Current is not longer pi_blocked_on */
+- spin_lock(q.lock_ptr);
+- if (ret && !rt_mutex_cleanup_proxy_lock(pi_mutex, &rt_waiter))
+- ret = 0;
+-
+- debug_rt_mutex_free_waiter(&rt_waiter);
+- /*
+- * Fixup the pi_state owner and possibly acquire the lock if we
+- * haven't already.
+- */
+- res = fixup_owner(uaddr2, &q, !ret);
+- /*
+- * If fixup_owner() returned an error, propagate that. If it
+- * acquired the lock, clear -ETIMEDOUT or -EINTR.
+- */
+- if (res)
+- ret = (res < 0) ? res : 0;
+-
+- unqueue_me_pi(&q);
+- spin_unlock(q.lock_ptr);
+-
+- if (ret == -EINTR) {
+- /*
+- * We've already been requeued, but cannot restart
+- * by calling futex_lock_pi() directly. We could
+- * restart this syscall, but it would detect that
+- * the user space "val" changed and return
+- * -EWOULDBLOCK. Save the overhead of the restart
+- * and return -EWOULDBLOCK directly.
+- */
+- ret = -EWOULDBLOCK;
+- }
+- break;
+- default:
+- BUG();
+- }
+-
+-out:
+- if (to) {
+- hrtimer_cancel(&to->timer);
+- destroy_hrtimer_on_stack(&to->timer);
+- }
+- return ret;
+-}
+-
+-/*
+- * Support for robust futexes: the kernel cleans up held futexes at
+- * thread exit time.
+- *
+- * Implementation: user-space maintains a per-thread list of locks it
+- * is holding. Upon do_exit(), the kernel carefully walks this list,
+- * and marks all locks that are owned by this thread with the
+- * FUTEX_OWNER_DIED bit, and wakes up a waiter (if any). The list is
+- * always manipulated with the lock held, so the list is private and
+- * per-thread. Userspace also maintains a per-thread 'list_op_pending'
+- * field, to allow the kernel to clean up if the thread dies after
+- * acquiring the lock, but just before it could have added itself to
+- * the list. There can only be one such pending lock.
+- */
+-
+-/**
+- * sys_set_robust_list() - Set the robust-futex list head of a task
+- * @head: pointer to the list-head
+- * @len: length of the list-head, as userspace expects
+- */
+-SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head,
+- size_t, len)
+-{
+- if (!futex_cmpxchg_enabled)
+- return -ENOSYS;
+- /*
+- * The kernel knows only one size for now:
+- */
+- if (unlikely(len != sizeof(*head)))
+- return -EINVAL;
+-
+- current->robust_list = head;
+-
+- return 0;
+-}
+-
+-/**
+- * sys_get_robust_list() - Get the robust-futex list head of a task
+- * @pid: pid of the process [zero for current task]
+- * @head_ptr: pointer to a list-head pointer, the kernel fills it in
+- * @len_ptr: pointer to a length field, the kernel fills in the header size
+- */
+-SYSCALL_DEFINE3(get_robust_list, int, pid,
+- struct robust_list_head __user * __user *, head_ptr,
+- size_t __user *, len_ptr)
+-{
+- struct robust_list_head __user *head;
+- unsigned long ret;
+- struct task_struct *p;
+-
+- if (!futex_cmpxchg_enabled)
+- return -ENOSYS;
+-
+- rcu_read_lock();
+-
+- ret = -ESRCH;
+- if (!pid)
+- p = current;
+- else {
+- p = find_task_by_vpid(pid);
+- if (!p)
+- goto err_unlock;
+- }
+-
+- ret = -EPERM;
+- if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
+- goto err_unlock;
+-
+- head = p->robust_list;
+- rcu_read_unlock();
+-
+- if (put_user(sizeof(*head), len_ptr))
+- return -EFAULT;
+- return put_user(head, head_ptr);
+-
+-err_unlock:
+- rcu_read_unlock();
+-
+- return ret;
+-}
+-
+-/* Constants for the pending_op argument of handle_futex_death */
+-#define HANDLE_DEATH_PENDING true
+-#define HANDLE_DEATH_LIST false
+-
+-/*
+- * Process a futex-list entry, check whether it's owned by the
+- * dying task, and do notification if so:
+- */
+-static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
+- bool pi, bool pending_op)
+-{
+- u32 uval, nval, mval;
+- int err;
+-
+- /* Futex address must be 32bit aligned */
+- if ((((unsigned long)uaddr) % sizeof(*uaddr)) != 0)
+- return -1;
+-
+-retry:
+- if (get_user(uval, uaddr))
+- return -1;
+-
+- /*
+- * Special case for regular (non PI) futexes. The unlock path in
+- * user space has two race scenarios:
+- *
+- * 1. The unlock path releases the user space futex value and
+- * before it can execute the futex() syscall to wake up
+- * waiters it is killed.
+- *
+- * 2. A woken up waiter is killed before it can acquire the
+- * futex in user space.
+- *
+- * In both cases the TID validation below prevents a wakeup of
+- * potential waiters which can cause these waiters to block
+- * forever.
+- *
+- * In both cases the following conditions are met:
+- *
+- * 1) task->robust_list->list_op_pending != NULL
+- * @pending_op == true
+- * 2) User space futex value == 0
+- * 3) Regular futex: @pi == false
+- *
+- * If these conditions are met, it is safe to attempt waking up a
+- * potential waiter without touching the user space futex value and
+- * trying to set the OWNER_DIED bit. The user space futex value is
+- * uncontended and the rest of the user space mutex state is
+- * consistent, so a woken waiter will just take over the
+- * uncontended futex. Setting the OWNER_DIED bit would create
+- * inconsistent state and malfunction of the user space owner died
+- * handling.
+- */
+- if (pending_op && !pi && !uval) {
+- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
+- return 0;
+- }
+-
+- if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
+- return 0;
+-
+- /*
+- * Ok, this dying thread is truly holding a futex
+- * of interest. Set the OWNER_DIED bit atomically
+- * via cmpxchg, and if the value had FUTEX_WAITERS
+- * set, wake up a waiter (if any). (We have to do a
+- * futex_wake() even if OWNER_DIED is already set -
+- * to handle the rare but possible case of recursive
+- * thread-death.) The rest of the cleanup is done in
+- * userspace.
+- */
+- mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
+-
+- /*
+- * We are not holding a lock here, but we want to have
+- * the pagefault_disable/enable() protection because
+- * we want to handle the fault gracefully. If the
+- * access fails we try to fault in the futex with R/W
+- * verification via get_user_pages. get_user() above
+- * does not guarantee R/W access. If that fails we
+- * give up and leave the futex locked.
+- */
+- if ((err = cmpxchg_futex_value_locked(&nval, uaddr, uval, mval))) {
+- switch (err) {
+- case -EFAULT:
+- if (fault_in_user_writeable(uaddr))
+- return -1;
+- goto retry;
+-
+- case -EAGAIN:
+- cond_resched();
+- goto retry;
+-
+- default:
+- WARN_ON_ONCE(1);
+- return err;
+- }
+- }
+-
+- if (nval != uval)
+- goto retry;
+-
+- /*
+- * Wake robust non-PI futexes here. The wakeup of
+- * PI futexes happens in exit_pi_state():
+- */
+- if (!pi && (uval & FUTEX_WAITERS))
+- futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
+-
+- return 0;
+-}
+-
+-/*
+- * Fetch a robust-list pointer. Bit 0 signals PI futexes:
+- */
+-static inline int fetch_robust_entry(struct robust_list __user **entry,
+- struct robust_list __user * __user *head,
+- unsigned int *pi)
+-{
+- unsigned long uentry;
+-
+- if (get_user(uentry, (unsigned long __user *)head))
+- return -EFAULT;
+-
+- *entry = (void __user *)(uentry & ~1UL);
+- *pi = uentry & 1;
+-
+- return 0;
+-}
+-
+-/*
+- * Walk curr->robust_list (very carefully, it's a userspace list!)
+- * and mark any locks found there dead, and notify any waiters.
+- *
+- * We silently return on any sign of list-walking problem.
+- */
+-static void exit_robust_list(struct task_struct *curr)
+-{
+- struct robust_list_head __user *head = curr->robust_list;
+- struct robust_list __user *entry, *next_entry, *pending;
+- unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
+- unsigned int next_pi;
+- unsigned long futex_offset;
+- int rc;
+-
+- if (!futex_cmpxchg_enabled)
+- return;
+-
+- /*
+- * Fetch the list head (which was registered earlier, via
+- * sys_set_robust_list()):
+- */
+- if (fetch_robust_entry(&entry, &head->list.next, &pi))
+- return;
+- /*
+- * Fetch the relative futex offset:
+- */
+- if (get_user(futex_offset, &head->futex_offset))
+- return;
+- /*
+- * Fetch any possibly pending lock-add first, and handle it
+- * if it exists:
+- */
+- if (fetch_robust_entry(&pending, &head->list_op_pending, &pip))
+- return;
+-
+- next_entry = NULL; /* avoid warning with gcc */
+- while (entry != &head->list) {
+- /*
+- * Fetch the next entry in the list before calling
+- * handle_futex_death:
+- */
+- rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi);
+- /*
+- * A pending lock might already be on the list, so
+- * don't process it twice:
+- */
+- if (entry != pending) {
+- if (handle_futex_death((void __user *)entry + futex_offset,
+- curr, pi, HANDLE_DEATH_LIST))
+- return;
+- }
+- if (rc)
+- return;
+- entry = next_entry;
+- pi = next_pi;
+- /*
+- * Avoid excessively long or circular lists:
+- */
+- if (!--limit)
+- break;
+-
+- cond_resched();
+- }
+-
+- if (pending) {
+- handle_futex_death((void __user *)pending + futex_offset,
+- curr, pip, HANDLE_DEATH_PENDING);
+- }
+-}
+-
+-static void futex_cleanup(struct task_struct *tsk)
+-{
+- if (unlikely(tsk->robust_list)) {
+- exit_robust_list(tsk);
+- tsk->robust_list = NULL;
+- }
+-
+-#ifdef CONFIG_COMPAT
+- if (unlikely(tsk->compat_robust_list)) {
+- compat_exit_robust_list(tsk);
+- tsk->compat_robust_list = NULL;
+- }
+-#endif
+-
+- if (unlikely(!list_empty(&tsk->pi_state_list)))
+- exit_pi_state_list(tsk);
+-}
+-
+-/**
+- * futex_exit_recursive - Set the tasks futex state to FUTEX_STATE_DEAD
+- * @tsk: task to set the state on
+- *
+- * Set the futex exit state of the task lockless. The futex waiter code
+- * observes that state when a task is exiting and loops until the task has
+- * actually finished the futex cleanup. The worst case for this is that the
+- * waiter runs through the wait loop until the state becomes visible.
+- *
+- * This is called from the recursive fault handling path in do_exit().
+- *
+- * This is best effort. Either the futex exit code has run already or
+- * not. If the OWNER_DIED bit has been set on the futex then the waiter can
+- * take it over. If not, the problem is pushed back to user space. If the
+- * futex exit code did not run yet, then an already queued waiter might
+- * block forever, but there is nothing which can be done about that.
+- */
+-void futex_exit_recursive(struct task_struct *tsk)
+-{
+- /* If the state is FUTEX_STATE_EXITING then futex_exit_mutex is held */
+- if (tsk->futex_state == FUTEX_STATE_EXITING)
+- mutex_unlock(&tsk->futex_exit_mutex);
+- tsk->futex_state = FUTEX_STATE_DEAD;
+-}
+-
+-static void futex_cleanup_begin(struct task_struct *tsk)
+-{
+- /*
+- * Prevent various race issues against a concurrent incoming waiter
+- * including live locks by forcing the waiter to block on
+- * tsk->futex_exit_mutex when it observes FUTEX_STATE_EXITING in
+- * attach_to_pi_owner().
+- */
+- mutex_lock(&tsk->futex_exit_mutex);
+-
+- /*
+- * Switch the state to FUTEX_STATE_EXITING under tsk->pi_lock.
+- *
+- * This ensures that all subsequent checks of tsk->futex_state in
+- * attach_to_pi_owner() must observe FUTEX_STATE_EXITING with
+- * tsk->pi_lock held.
+- *
+- * It guarantees also that a pi_state which was queued right before
+- * the state change under tsk->pi_lock by a concurrent waiter must
+- * be observed in exit_pi_state_list().
+- */
+- raw_spin_lock_irq(&tsk->pi_lock);
+- tsk->futex_state = FUTEX_STATE_EXITING;
+- raw_spin_unlock_irq(&tsk->pi_lock);
+-}
+-
+-static void futex_cleanup_end(struct task_struct *tsk, int state)
+-{
+- /*
+- * Lockless store. The only side effect is that an observer might
+- * take another loop until it becomes visible.
+- */
+- tsk->futex_state = state;
+- /*
+- * Drop the exit protection. This unblocks waiters which observed
+- * FUTEX_STATE_EXITING to reevaluate the state.
+- */
+- mutex_unlock(&tsk->futex_exit_mutex);
+-}
+-
+-void futex_exec_release(struct task_struct *tsk)
+-{
+- /*
+- * The state handling is done for consistency, but in the case of
+- * exec() there is no way to prevent further damage as the PID stays
+- * the same. But for the unlikely and arguably buggy case that a
+- * futex is held on exec(), this provides at least as much state
+- * consistency protection which is possible.
+- */
+- futex_cleanup_begin(tsk);
+- futex_cleanup(tsk);
+- /*
+- * Reset the state to FUTEX_STATE_OK. The task is alive and about
+- * exec a new binary.
+- */
+- futex_cleanup_end(tsk, FUTEX_STATE_OK);
+-}
+-
+-void futex_exit_release(struct task_struct *tsk)
+-{
+- futex_cleanup_begin(tsk);
+- futex_cleanup(tsk);
+- futex_cleanup_end(tsk, FUTEX_STATE_DEAD);
+-}
+-
+-long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
+- u32 __user *uaddr2, u32 val2, u32 val3)
+-{
+- int cmd = op & FUTEX_CMD_MASK;
+- unsigned int flags = 0;
+-
+- if (!(op & FUTEX_PRIVATE_FLAG))
+- flags |= FLAGS_SHARED;
+-
+- if (op & FUTEX_CLOCK_REALTIME) {
+- flags |= FLAGS_CLOCKRT;
+- if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI &&
+- cmd != FUTEX_LOCK_PI2)
+- return -ENOSYS;
+- }
+-
+- switch (cmd) {
+- case FUTEX_LOCK_PI:
+- case FUTEX_LOCK_PI2:
+- case FUTEX_UNLOCK_PI:
+- case FUTEX_TRYLOCK_PI:
+- case FUTEX_WAIT_REQUEUE_PI:
+- case FUTEX_CMP_REQUEUE_PI:
+- if (!futex_cmpxchg_enabled)
+- return -ENOSYS;
+- }
+-
+- switch (cmd) {
+- case FUTEX_WAIT:
+- val3 = FUTEX_BITSET_MATCH_ANY;
+- fallthrough;
+- case FUTEX_WAIT_BITSET:
+- return futex_wait(uaddr, flags, val, timeout, val3);
+- case FUTEX_WAKE:
+- val3 = FUTEX_BITSET_MATCH_ANY;
+- fallthrough;
+- case FUTEX_WAKE_BITSET:
+- return futex_wake(uaddr, flags, val, val3);
+- case FUTEX_REQUEUE:
+- return futex_requeue(uaddr, flags, uaddr2, val, val2, NULL, 0);
+- case FUTEX_CMP_REQUEUE:
+- return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 0);
+- case FUTEX_WAKE_OP:
+- return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3);
+- case FUTEX_LOCK_PI:
+- flags |= FLAGS_CLOCKRT;
+- fallthrough;
+- case FUTEX_LOCK_PI2:
+- return futex_lock_pi(uaddr, flags, timeout, 0);
+- case FUTEX_UNLOCK_PI:
+- return futex_unlock_pi(uaddr, flags);
+- case FUTEX_TRYLOCK_PI:
+- return futex_lock_pi(uaddr, flags, NULL, 1);
+- case FUTEX_WAIT_REQUEUE_PI:
+- val3 = FUTEX_BITSET_MATCH_ANY;
+- return futex_wait_requeue_pi(uaddr, flags, val, timeout, val3,
+- uaddr2);
+- case FUTEX_CMP_REQUEUE_PI:
+- return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1);
+- }
+- return -ENOSYS;
+-}
+-
+-static __always_inline bool futex_cmd_has_timeout(u32 cmd)
+-{
+- switch (cmd) {
+- case FUTEX_WAIT:
+- case FUTEX_LOCK_PI:
+- case FUTEX_LOCK_PI2:
+- case FUTEX_WAIT_BITSET:
+- case FUTEX_WAIT_REQUEUE_PI:
+- return true;
+- }
+- return false;
+-}
+-
+-static __always_inline int
+-futex_init_timeout(u32 cmd, u32 op, struct timespec64 *ts, ktime_t *t)
+-{
+- if (!timespec64_valid(ts))
+- return -EINVAL;
+-
+- *t = timespec64_to_ktime(*ts);
+- if (cmd == FUTEX_WAIT)
+- *t = ktime_add_safe(ktime_get(), *t);
+- else if (cmd != FUTEX_LOCK_PI && !(op & FUTEX_CLOCK_REALTIME))
+- *t = timens_ktime_to_host(CLOCK_MONOTONIC, *t);
+- return 0;
+-}
+-
+-SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
+- const struct __kernel_timespec __user *, utime,
+- u32 __user *, uaddr2, u32, val3)
+-{
+- int ret, cmd = op & FUTEX_CMD_MASK;
+- ktime_t t, *tp = NULL;
+- struct timespec64 ts;
+-
+- if (utime && futex_cmd_has_timeout(cmd)) {
+- if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG))))
+- return -EFAULT;
+- if (get_timespec64(&ts, utime))
+- return -EFAULT;
+- ret = futex_init_timeout(cmd, op, &ts, &t);
+- if (ret)
+- return ret;
+- tp = &t;
+- }
+-
+- return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3);
+-}
+-
+-#ifdef CONFIG_COMPAT
+-/*
+- * Fetch a robust-list pointer. Bit 0 signals PI futexes:
+- */
+-static inline int
+-compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
+- compat_uptr_t __user *head, unsigned int *pi)
+-{
+- if (get_user(*uentry, head))
+- return -EFAULT;
+-
+- *entry = compat_ptr((*uentry) & ~1);
+- *pi = (unsigned int)(*uentry) & 1;
+-
+- return 0;
+-}
+-
+-static void __user *futex_uaddr(struct robust_list __user *entry,
+- compat_long_t futex_offset)
+-{
+- compat_uptr_t base = ptr_to_compat(entry);
+- void __user *uaddr = compat_ptr(base + futex_offset);
+-
+- return uaddr;
+-}
+-
+-/*
+- * Walk curr->robust_list (very carefully, it's a userspace list!)
+- * and mark any locks found there dead, and notify any waiters.
+- *
+- * We silently return on any sign of list-walking problem.
+- */
+-static void compat_exit_robust_list(struct task_struct *curr)
+-{
+- struct compat_robust_list_head __user *head = curr->compat_robust_list;
+- struct robust_list __user *entry, *next_entry, *pending;
+- unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
+- unsigned int next_pi;
+- compat_uptr_t uentry, next_uentry, upending;
+- compat_long_t futex_offset;
+- int rc;
+-
+- if (!futex_cmpxchg_enabled)
+- return;
+-
+- /*
+- * Fetch the list head (which was registered earlier, via
+- * sys_set_robust_list()):
+- */
+- if (compat_fetch_robust_entry(&uentry, &entry, &head->list.next, &pi))
+- return;
+- /*
+- * Fetch the relative futex offset:
+- */
+- if (get_user(futex_offset, &head->futex_offset))
+- return;
+- /*
+- * Fetch any possibly pending lock-add first, and handle it
+- * if it exists:
+- */
+- if (compat_fetch_robust_entry(&upending, &pending,
+- &head->list_op_pending, &pip))
+- return;
+-
+- next_entry = NULL; /* avoid warning with gcc */
+- while (entry != (struct robust_list __user *) &head->list) {
+- /*
+- * Fetch the next entry in the list before calling
+- * handle_futex_death:
+- */
+- rc = compat_fetch_robust_entry(&next_uentry, &next_entry,
+- (compat_uptr_t __user *)&entry->next, &next_pi);
+- /*
+- * A pending lock might already be on the list, so
+- * dont process it twice:
+- */
+- if (entry != pending) {
+- void __user *uaddr = futex_uaddr(entry, futex_offset);
+-
+- if (handle_futex_death(uaddr, curr, pi,
+- HANDLE_DEATH_LIST))
+- return;
+- }
+- if (rc)
+- return;
+- uentry = next_uentry;
+- entry = next_entry;
+- pi = next_pi;
+- /*
+- * Avoid excessively long or circular lists:
+- */
+- if (!--limit)
+- break;
+-
+- cond_resched();
+- }
+- if (pending) {
+- void __user *uaddr = futex_uaddr(pending, futex_offset);
+-
+- handle_futex_death(uaddr, curr, pip, HANDLE_DEATH_PENDING);
+- }
+-}
+-
+-COMPAT_SYSCALL_DEFINE2(set_robust_list,
+- struct compat_robust_list_head __user *, head,
+- compat_size_t, len)
+-{
+- if (!futex_cmpxchg_enabled)
+- return -ENOSYS;
+-
+- if (unlikely(len != sizeof(*head)))
+- return -EINVAL;
+-
+- current->compat_robust_list = head;
+-
+- return 0;
+-}
+-
+-COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
+- compat_uptr_t __user *, head_ptr,
+- compat_size_t __user *, len_ptr)
+-{
+- struct compat_robust_list_head __user *head;
+- unsigned long ret;
+- struct task_struct *p;
+-
+- if (!futex_cmpxchg_enabled)
+- return -ENOSYS;
+-
+- rcu_read_lock();
+-
+- ret = -ESRCH;
+- if (!pid)
+- p = current;
+- else {
+- p = find_task_by_vpid(pid);
+- if (!p)
+- goto err_unlock;
+- }
+-
+- ret = -EPERM;
+- if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
+- goto err_unlock;
+-
+- head = p->compat_robust_list;
+- rcu_read_unlock();
+-
+- if (put_user(sizeof(*head), len_ptr))
+- return -EFAULT;
+- return put_user(ptr_to_compat(head), head_ptr);
+-
+-err_unlock:
+- rcu_read_unlock();
+-
+- return ret;
+-}
+-#endif /* CONFIG_COMPAT */
+-
+-#ifdef CONFIG_COMPAT_32BIT_TIME
+-SYSCALL_DEFINE6(futex_time32, u32 __user *, uaddr, int, op, u32, val,
+- const struct old_timespec32 __user *, utime, u32 __user *, uaddr2,
+- u32, val3)
+-{
+- int ret, cmd = op & FUTEX_CMD_MASK;
+- ktime_t t, *tp = NULL;
+- struct timespec64 ts;
+-
+- if (utime && futex_cmd_has_timeout(cmd)) {
+- if (get_old_timespec32(&ts, utime))
+- return -EFAULT;
+- ret = futex_init_timeout(cmd, op, &ts, &t);
+- if (ret)
+- return ret;
+- tp = &t;
+- }
+-
+- return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3);
+-}
+-#endif /* CONFIG_COMPAT_32BIT_TIME */
+-
+-static void __init futex_detect_cmpxchg(void)
+-{
+-#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
+- u32 curval;
+-
+- /*
+- * This will fail and we want it. Some arch implementations do
+- * runtime detection of the futex_atomic_cmpxchg_inatomic()
+- * functionality. We want to know that before we call in any
+- * of the complex code paths. Also we want to prevent
+- * registration of robust lists in that case. NULL is
+- * guaranteed to fault and we get -EFAULT on functional
+- * implementation, the non-functional ones will return
+- * -ENOSYS.
+- */
+- if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
+- futex_cmpxchg_enabled = 1;
+-#endif
+-}
+-
+-static int __init futex_init(void)
+-{
+- unsigned int futex_shift;
+- unsigned long i;
+-
+-#if CONFIG_BASE_SMALL
+- futex_hashsize = 16;
+-#else
+- futex_hashsize = roundup_pow_of_two(256 * num_possible_cpus());
+-#endif
+-
+- futex_queues = alloc_large_system_hash("futex", sizeof(*futex_queues),
+- futex_hashsize, 0,
+- futex_hashsize < 256 ? HASH_SMALL : 0,
+- &futex_shift, NULL,
+- futex_hashsize, futex_hashsize);
+- futex_hashsize = 1UL << futex_shift;
+-
+- futex_detect_cmpxchg();
+-
+- for (i = 0; i < futex_hashsize; i++) {
+- atomic_set(&futex_queues[i].waiters, 0);
+- plist_head_init(&futex_queues[i].chain);
+- spin_lock_init(&futex_queues[i].lock);
+- }
+-
+- return 0;
+-}
+-core_initcall(futex_init);
+diff --git a/kernel/futex/Makefile b/kernel/futex/Makefile
+new file mode 100644
+index 000000000..b77188d1f
+--- /dev/null
++++ b/kernel/futex/Makefile
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-y += core.o syscalls.o pi.o requeue.o waitwake.o
+diff --git a/kernel/futex/core.c b/kernel/futex/core.c
+new file mode 100644
+index 000000000..25d8a88b3
+--- /dev/null
++++ b/kernel/futex/core.c
+@@ -0,0 +1,1176 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Fast Userspace Mutexes (which I call "Futexes!").
++ * (C) Rusty Russell, IBM 2002
++ *
++ * Generalized futexes, futex requeueing, misc fixes by Ingo Molnar
++ * (C) Copyright 2003 Red Hat Inc, All Rights Reserved
++ *
++ * Removed page pinning, fix privately mapped COW pages and other cleanups
++ * (C) Copyright 2003, 2004 Jamie Lokier
++ *
++ * Robust futex support started by Ingo Molnar
++ * (C) Copyright 2006 Red Hat Inc, All Rights Reserved
++ * Thanks to Thomas Gleixner for suggestions, analysis and fixes.
++ *
++ * PI-futex support started by Ingo Molnar and Thomas Gleixner
++ * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
++ * Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
++ *
++ * PRIVATE futexes by Eric Dumazet
++ * Copyright (C) 2007 Eric Dumazet <dada1@cosmosbay.com>
++ *
++ * Requeue-PI support by Darren Hart <dvhltc@us.ibm.com>
++ * Copyright (C) IBM Corporation, 2009
++ * Thanks to Thomas Gleixner for conceptual design and careful reviews.
++ *
++ * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
++ * enough at me, Linus for the original (flawed) idea, Matthew
++ * Kirkwood for proof-of-concept implementation.
++ *
++ * "The futexes are also cursed."
++ * "But they come in a choice of three flavours!"
++ */
++#include <linux/compat.h>
++#include <linux/jhash.h>
++#include <linux/pagemap.h>
++#include <linux/memblock.h>
++#include <linux/fault-inject.h>
++#include <linux/slab.h>
++
++#include "futex.h"
++#include "../locking/rtmutex_common.h"
++
++#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
++int __read_mostly futex_cmpxchg_enabled;
++#endif
++
++
++/*
++ * The base of the bucket array and its size are always used together
++ * (after initialization only in futex_hash()), so ensure that they
++ * reside in the same cacheline.
++ */
++static struct {
++ struct futex_hash_bucket *queues;
++ unsigned long hashsize;
++} __futex_data __read_mostly __aligned(2*sizeof(long));
++#define futex_queues (__futex_data.queues)
++#define futex_hashsize (__futex_data.hashsize)
++
++
++/*
++ * Fault injections for futexes.
++ */
++#ifdef CONFIG_FAIL_FUTEX
++
++static struct {
++ struct fault_attr attr;
++
++ bool ignore_private;
++} fail_futex = {
++ .attr = FAULT_ATTR_INITIALIZER,
++ .ignore_private = false,
++};
++
++static int __init setup_fail_futex(char *str)
++{
++ return setup_fault_attr(&fail_futex.attr, str);
++}
++__setup("fail_futex=", setup_fail_futex);
++
++bool should_fail_futex(bool fshared)
++{
++ if (fail_futex.ignore_private && !fshared)
++ return false;
++
++ return should_fail(&fail_futex.attr, 1);
++}
++
++#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
++
++static int __init fail_futex_debugfs(void)
++{
++ umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
++ struct dentry *dir;
++
++ dir = fault_create_debugfs_attr("fail_futex", NULL,
++ &fail_futex.attr);
++ if (IS_ERR(dir))
++ return PTR_ERR(dir);
++
++ debugfs_create_bool("ignore-private", mode, dir,
++ &fail_futex.ignore_private);
++ return 0;
++}
++
++late_initcall(fail_futex_debugfs);
++
++#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
++
++#endif /* CONFIG_FAIL_FUTEX */
++
++/**
++ * futex_hash - Return the hash bucket in the global hash
++ * @key: Pointer to the futex key for which the hash is calculated
++ *
++ * We hash on the keys returned from get_futex_key (see below) and return the
++ * corresponding hash bucket in the global hash.
++ */
++struct futex_hash_bucket *futex_hash(union futex_key *key)
++{
++ u32 hash = jhash2((u32 *)key, offsetof(typeof(*key), both.offset) / 4,
++ key->both.offset);
++
++ return &futex_queues[hash & (futex_hashsize - 1)];
++}
++
++
++/**
++ * futex_setup_timer - set up the sleeping hrtimer.
++ * @time: ptr to the given timeout value
++ * @timeout: the hrtimer_sleeper structure to be set up
++ * @flags: futex flags
++ * @range_ns: optional range in ns
++ *
++ * Return: Initialized hrtimer_sleeper structure or NULL if no timeout
++ * value given
++ */
++struct hrtimer_sleeper *
++futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
++ int flags, u64 range_ns)
++{
++ if (!time)
++ return NULL;
++
++ hrtimer_init_sleeper_on_stack(timeout, (flags & FLAGS_CLOCKRT) ?
++ CLOCK_REALTIME : CLOCK_MONOTONIC,
++ HRTIMER_MODE_ABS);
++ /*
++ * If range_ns is 0, calling hrtimer_set_expires_range_ns() is
++ * effectively the same as calling hrtimer_set_expires().
++ */
++ hrtimer_set_expires_range_ns(&timeout->timer, *time, range_ns);
++
++ return timeout;
++}
++
++/*
++ * Generate a machine wide unique identifier for this inode.
++ *
++ * This relies on u64 not wrapping in the life-time of the machine; which with
++ * 1ns resolution means almost 585 years.
++ *
++ * This further relies on the fact that a well formed program will not unmap
++ * the file while it has a (shared) futex waiting on it. This mapping will have
++ * a file reference which pins the mount and inode.
++ *
++ * If for some reason an inode gets evicted and read back in again, it will get
++ * a new sequence number and will _NOT_ match, even though it is the exact same
++ * file.
++ *
++ * It is important that futex_match() will never have a false-positive, esp.
++ * for PI futexes that can mess up the state. The above argues that false-negatives
++ * are only possible for malformed programs.
++ */
++static u64 get_inode_sequence_number(struct inode *inode)
++{
++ static atomic64_t i_seq;
++ u64 old;
++
++ /* Does the inode already have a sequence number? */
++ old = atomic64_read(&inode->i_sequence);
++ if (likely(old))
++ return old;
++
++ for (;;) {
++ u64 new = atomic64_add_return(1, &i_seq);
++ if (WARN_ON_ONCE(!new))
++ continue;
++
++ old = atomic64_cmpxchg_relaxed(&inode->i_sequence, 0, new);
++ if (old)
++ return old;
++ return new;
++ }
++}
++
++/**
++ * get_futex_key() - Get parameters which are the keys for a futex
++ * @uaddr: virtual address of the futex
++ * @fshared: false for a PROCESS_PRIVATE futex, true for PROCESS_SHARED
++ * @key: address where result is stored.
++ * @rw: mapping needs to be read/write (values: FUTEX_READ,
++ * FUTEX_WRITE)
++ *
++ * Return: a negative error code or 0
++ *
++ * The key words are stored in @key on success.
++ *
++ * For shared mappings (when @fshared), the key is:
++ *
++ * ( inode->i_sequence, page->index, offset_within_page )
++ *
++ * [ also see get_inode_sequence_number() ]
++ *
++ * For private mappings (or when !@fshared), the key is:
++ *
++ * ( current->mm, address, 0 )
++ *
++ * This allows (cross process, where applicable) identification of the futex
++ * without keeping the page pinned for the duration of the FUTEX_WAIT.
++ *
++ * lock_page() might sleep, the caller should not hold a spinlock.
++ */
++int get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key,
++ enum futex_access rw)
++{
++ unsigned long address = (unsigned long)uaddr;
++ struct mm_struct *mm = current->mm;
++ struct page *page, *tail;
++ struct address_space *mapping;
++ int err, ro = 0;
++
++ /*
++ * The futex address must be "naturally" aligned.
++ */
++ key->both.offset = address % PAGE_SIZE;
++ if (unlikely((address % sizeof(u32)) != 0))
++ return -EINVAL;
++ address -= key->both.offset;
++
++ if (unlikely(!access_ok(uaddr, sizeof(u32))))
++ return -EFAULT;
++
++ if (unlikely(should_fail_futex(fshared)))
++ return -EFAULT;
++
++ /*
++ * PROCESS_PRIVATE futexes are fast.
++ * As the mm cannot disappear under us and the 'key' only needs
++ * virtual address, we dont even have to find the underlying vma.
++ * Note : We do have to check 'uaddr' is a valid user address,
++ * but access_ok() should be faster than find_vma()
++ */
++ if (!fshared) {
++ key->private.mm = mm;
++ key->private.address = address;
++ return 0;
++ }
++
++again:
++ /* Ignore any VERIFY_READ mapping (futex common case) */
++ if (unlikely(should_fail_futex(true)))
++ return -EFAULT;
++
++ err = get_user_pages_fast(address, 1, FOLL_WRITE, &page);
++ /*
++ * If write access is not required (eg. FUTEX_WAIT), try
++ * and get read-only access.
++ */
++ if (err == -EFAULT && rw == FUTEX_READ) {
++ err = get_user_pages_fast(address, 1, 0, &page);
++ ro = 1;
++ }
++ if (err < 0)
++ return err;
++ else
++ err = 0;
++
++ /*
++ * The treatment of mapping from this point on is critical. The page
++ * lock protects many things but in this context the page lock
++ * stabilizes mapping, prevents inode freeing in the shared
++ * file-backed region case and guards against movement to swap cache.
++ *
++ * Strictly speaking the page lock is not needed in all cases being
++ * considered here and page lock forces unnecessarily serialization
++ * From this point on, mapping will be re-verified if necessary and
++ * page lock will be acquired only if it is unavoidable
++ *
++ * Mapping checks require the head page for any compound page so the
++ * head page and mapping is looked up now. For anonymous pages, it
++ * does not matter if the page splits in the future as the key is
++ * based on the address. For filesystem-backed pages, the tail is
++ * required as the index of the page determines the key. For
++ * base pages, there is no tail page and tail == page.
++ */
++ tail = page;
++ page = compound_head(page);
++ mapping = READ_ONCE(page->mapping);
++
++ /*
++ * If page->mapping is NULL, then it cannot be a PageAnon
++ * page; but it might be the ZERO_PAGE or in the gate area or
++ * in a special mapping (all cases which we are happy to fail);
++ * or it may have been a good file page when get_user_pages_fast
++ * found it, but truncated or holepunched or subjected to
++ * invalidate_complete_page2 before we got the page lock (also
++ * cases which we are happy to fail). And we hold a reference,
++ * so refcount care in invalidate_complete_page's remove_mapping
++ * prevents drop_caches from setting mapping to NULL beneath us.
++ *
++ * The case we do have to guard against is when memory pressure made
++ * shmem_writepage move it from filecache to swapcache beneath us:
++ * an unlikely race, but we do need to retry for page->mapping.
++ */
++ if (unlikely(!mapping)) {
++ int shmem_swizzled;
++
++ /*
++ * Page lock is required to identify which special case above
++ * applies. If this is really a shmem page then the page lock
++ * will prevent unexpected transitions.
++ */
++ lock_page(page);
++ shmem_swizzled = PageSwapCache(page) || page->mapping;
++ unlock_page(page);
++ put_page(page);
++
++ if (shmem_swizzled)
++ goto again;
++
++ return -EFAULT;
++ }
++
++ /*
++ * Private mappings are handled in a simple way.
++ *
++ * If the futex key is stored on an anonymous page, then the associated
++ * object is the mm which is implicitly pinned by the calling process.
++ *
++ * NOTE: When userspace waits on a MAP_SHARED mapping, even if
++ * it's a read-only handle, it's expected that futexes attach to
++ * the object not the particular process.
++ */
++ if (PageAnon(page)) {
++ /*
++ * A RO anonymous page will never change and thus doesn't make
++ * sense for futex operations.
++ */
++ if (unlikely(should_fail_futex(true)) || ro) {
++ err = -EFAULT;
++ goto out;
++ }
++
++ key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
++ key->private.mm = mm;
++ key->private.address = address;
++
++ } else {
++ struct inode *inode;
++
++ /*
++ * The associated futex object in this case is the inode and
++ * the page->mapping must be traversed. Ordinarily this should
++ * be stabilised under page lock but it's not strictly
++ * necessary in this case as we just want to pin the inode, not
++ * update the radix tree or anything like that.
++ *
++ * The RCU read lock is taken as the inode is finally freed
++ * under RCU. If the mapping still matches expectations then the
++ * mapping->host can be safely accessed as being a valid inode.
++ */
++ rcu_read_lock();
++
++ if (READ_ONCE(page->mapping) != mapping) {
++ rcu_read_unlock();
++ put_page(page);
++
++ goto again;
++ }
++
++ inode = READ_ONCE(mapping->host);
++ if (!inode) {
++ rcu_read_unlock();
++ put_page(page);
++
++ goto again;
++ }
++
++ key->both.offset |= FUT_OFF_INODE; /* inode-based key */
++ key->shared.i_seq = get_inode_sequence_number(inode);
++ key->shared.pgoff = page_to_pgoff(tail);
++ rcu_read_unlock();
++ }
++
++out:
++ put_page(page);
++ return err;
++}
++
++/**
++ * fault_in_user_writeable() - Fault in user address and verify RW access
++ * @uaddr: pointer to faulting user space address
++ *
++ * Slow path to fixup the fault we just took in the atomic write
++ * access to @uaddr.
++ *
++ * We have no generic implementation of a non-destructive write to the
++ * user address. We know that we faulted in the atomic pagefault
++ * disabled section so we can as well avoid the #PF overhead by
++ * calling get_user_pages() right away.
++ */
++int fault_in_user_writeable(u32 __user *uaddr)
++{
++ struct mm_struct *mm = current->mm;
++ int ret;
++
++ mmap_read_lock(mm);
++ ret = fixup_user_fault(mm, (unsigned long)uaddr,
++ FAULT_FLAG_WRITE, NULL);
++ mmap_read_unlock(mm);
++
++ return ret < 0 ? ret : 0;
++}
++
++/**
++ * futex_top_waiter() - Return the highest priority waiter on a futex
++ * @hb: the hash bucket the futex_q's reside in
++ * @key: the futex key (to distinguish it from other futex futex_q's)
++ *
++ * Must be called with the hb lock held.
++ */
++struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb, union futex_key *key)
++{
++ struct futex_q *this;
++
++ plist_for_each_entry(this, &hb->chain, list) {
++ if (futex_match(&this->key, key))
++ return this;
++ }
++ return NULL;
++}
++
++int futex_cmpxchg_value_locked(u32 *curval, u32 __user *uaddr, u32 uval, u32 newval)
++{
++ int ret;
++
++ pagefault_disable();
++ ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
++ pagefault_enable();
++
++ return ret;
++}
++
++int futex_get_value_locked(u32 *dest, u32 __user *from)
++{
++ int ret;
++
++ pagefault_disable();
++ ret = __get_user(*dest, from);
++ pagefault_enable();
++
++ return ret ? -EFAULT : 0;
++}
++
++/**
++ * wait_for_owner_exiting - Block until the owner has exited
++ * @ret: owner's current futex lock status
++ * @exiting: Pointer to the exiting task
++ *
++ * Caller must hold a refcount on @exiting.
++ */
++void wait_for_owner_exiting(int ret, struct task_struct *exiting)
++{
++ if (ret != -EBUSY) {
++ WARN_ON_ONCE(exiting);
++ return;
++ }
++
++ if (WARN_ON_ONCE(ret == -EBUSY && !exiting))
++ return;
++
++ mutex_lock(&exiting->futex_exit_mutex);
++ /*
++ * No point in doing state checking here. If the waiter got here
++ * while the task was in exec()->exec_futex_release() then it can
++ * have any FUTEX_STATE_* value when the waiter has acquired the
++ * mutex. OK, if running, EXITING or DEAD if it reached exit()
++ * already. Highly unlikely and not a problem. Just one more round
++ * through the futex maze.
++ */
++ mutex_unlock(&exiting->futex_exit_mutex);
++
++ put_task_struct(exiting);
++}
++
++/**
++ * __futex_unqueue() - Remove the futex_q from its futex_hash_bucket
++ * @q: The futex_q to unqueue
++ *
++ * The q->lock_ptr must not be NULL and must be held by the caller.
++ */
++void __futex_unqueue(struct futex_q *q)
++{
++ struct futex_hash_bucket *hb;
++
++ if (WARN_ON_SMP(!q->lock_ptr) || WARN_ON(plist_node_empty(&q->list)))
++ return;
++ lockdep_assert_held(q->lock_ptr);
++
++ hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock);
++ plist_del(&q->list, &hb->chain);
++ futex_hb_waiters_dec(hb);
++}
++
++/* The key must be already stored in q->key. */
++struct futex_hash_bucket *futex_q_lock(struct futex_q *q)
++ __acquires(&hb->lock)
++{
++ struct futex_hash_bucket *hb;
++
++ hb = futex_hash(&q->key);
++
++ /*
++ * Increment the counter before taking the lock so that
++ * a potential waker won't miss a to-be-slept task that is
++ * waiting for the spinlock. This is safe as all futex_q_lock()
++ * users end up calling futex_queue(). Similarly, for housekeeping,
++ * decrement the counter at futex_q_unlock() when some error has
++ * occurred and we don't end up adding the task to the list.
++ */
++ futex_hb_waiters_inc(hb); /* implies smp_mb(); (A) */
++
++ q->lock_ptr = &hb->lock;
++
++ spin_lock(&hb->lock);
++ return hb;
++}
++
++void futex_q_unlock(struct futex_hash_bucket *hb)
++ __releases(&hb->lock)
++{
++ spin_unlock(&hb->lock);
++ futex_hb_waiters_dec(hb);
++}
++
++void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb)
++{
++ int prio;
++
++ /*
++ * The priority used to register this element is
++ * - either the real thread-priority for the real-time threads
++ * (i.e. threads with a priority lower than MAX_RT_PRIO)
++ * - or MAX_RT_PRIO for non-RT threads.
++ * Thus, all RT-threads are woken first in priority order, and
++ * the others are woken last, in FIFO order.
++ */
++ prio = min(current->normal_prio, MAX_RT_PRIO);
++
++ plist_node_init(&q->list, prio);
++ plist_add(&q->list, &hb->chain);
++ q->task = current;
++}
++
++/**
++ * futex_unqueue() - Remove the futex_q from its futex_hash_bucket
++ * @q: The futex_q to unqueue
++ *
++ * The q->lock_ptr must not be held by the caller. A call to futex_unqueue() must
++ * be paired with exactly one earlier call to futex_queue().
++ *
++ * Return:
++ * - 1 - if the futex_q was still queued (and we removed unqueued it);
++ * - 0 - if the futex_q was already removed by the waking thread
++ */
++int futex_unqueue(struct futex_q *q)
++{
++ spinlock_t *lock_ptr;
++ int ret = 0;
++
++ /* In the common case we don't take the spinlock, which is nice. */
++retry:
++ /*
++ * q->lock_ptr can change between this read and the following spin_lock.
++ * Use READ_ONCE to forbid the compiler from reloading q->lock_ptr and
++ * optimizing lock_ptr out of the logic below.
++ */
++ lock_ptr = READ_ONCE(q->lock_ptr);
++ if (lock_ptr != NULL) {
++ spin_lock(lock_ptr);
++ /*
++ * q->lock_ptr can change between reading it and
++ * spin_lock(), causing us to take the wrong lock. This
++ * corrects the race condition.
++ *
++ * Reasoning goes like this: if we have the wrong lock,
++ * q->lock_ptr must have changed (maybe several times)
++ * between reading it and the spin_lock(). It can
++ * change again after the spin_lock() but only if it was
++ * already changed before the spin_lock(). It cannot,
++ * however, change back to the original value. Therefore
++ * we can detect whether we acquired the correct lock.
++ */
++ if (unlikely(lock_ptr != q->lock_ptr)) {
++ spin_unlock(lock_ptr);
++ goto retry;
++ }
++ __futex_unqueue(q);
++
++ BUG_ON(q->pi_state);
++
++ spin_unlock(lock_ptr);
++ ret = 1;
++ }
++
++ return ret;
++}
++
++/*
++ * PI futexes can not be requeued and must remove themselves from the
++ * hash bucket. The hash bucket lock (i.e. lock_ptr) is held.
++ */
++void futex_unqueue_pi(struct futex_q *q)
++{
++ __futex_unqueue(q);
++
++ BUG_ON(!q->pi_state);
++ put_pi_state(q->pi_state);
++ q->pi_state = NULL;
++}
++
++/* Constants for the pending_op argument of handle_futex_death */
++#define HANDLE_DEATH_PENDING true
++#define HANDLE_DEATH_LIST false
++
++/*
++ * Process a futex-list entry, check whether it's owned by the
++ * dying task, and do notification if so:
++ */
++static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr,
++ bool pi, bool pending_op)
++{
++ u32 uval, nval, mval;
++ int err;
++
++ /* Futex address must be 32bit aligned */
++ if ((((unsigned long)uaddr) % sizeof(*uaddr)) != 0)
++ return -1;
++
++retry:
++ if (get_user(uval, uaddr))
++ return -1;
++
++ /*
++ * Special case for regular (non PI) futexes. The unlock path in
++ * user space has two race scenarios:
++ *
++ * 1. The unlock path releases the user space futex value and
++ * before it can execute the futex() syscall to wake up
++ * waiters it is killed.
++ *
++ * 2. A woken up waiter is killed before it can acquire the
++ * futex in user space.
++ *
++ * In both cases the TID validation below prevents a wakeup of
++ * potential waiters which can cause these waiters to block
++ * forever.
++ *
++ * In both cases the following conditions are met:
++ *
++ * 1) task->robust_list->list_op_pending != NULL
++ * @pending_op == true
++ * 2) User space futex value == 0
++ * 3) Regular futex: @pi == false
++ *
++ * If these conditions are met, it is safe to attempt waking up a
++ * potential waiter without touching the user space futex value and
++ * trying to set the OWNER_DIED bit. The user space futex value is
++ * uncontended and the rest of the user space mutex state is
++ * consistent, so a woken waiter will just take over the
++ * uncontended futex. Setting the OWNER_DIED bit would create
++ * inconsistent state and malfunction of the user space owner died
++ * handling.
++ */
++ if (pending_op && !pi && !uval) {
++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
++ return 0;
++ }
++
++ if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr))
++ return 0;
++
++ /*
++ * Ok, this dying thread is truly holding a futex
++ * of interest. Set the OWNER_DIED bit atomically
++ * via cmpxchg, and if the value had FUTEX_WAITERS
++ * set, wake up a waiter (if any). (We have to do a
++ * futex_wake() even if OWNER_DIED is already set -
++ * to handle the rare but possible case of recursive
++ * thread-death.) The rest of the cleanup is done in
++ * userspace.
++ */
++ mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
++
++ /*
++ * We are not holding a lock here, but we want to have
++ * the pagefault_disable/enable() protection because
++ * we want to handle the fault gracefully. If the
++ * access fails we try to fault in the futex with R/W
++ * verification via get_user_pages. get_user() above
++ * does not guarantee R/W access. If that fails we
++ * give up and leave the futex locked.
++ */
++ if ((err = futex_cmpxchg_value_locked(&nval, uaddr, uval, mval))) {
++ switch (err) {
++ case -EFAULT:
++ if (fault_in_user_writeable(uaddr))
++ return -1;
++ goto retry;
++
++ case -EAGAIN:
++ cond_resched();
++ goto retry;
++
++ default:
++ WARN_ON_ONCE(1);
++ return err;
++ }
++ }
++
++ if (nval != uval)
++ goto retry;
++
++ /*
++ * Wake robust non-PI futexes here. The wakeup of
++ * PI futexes happens in exit_pi_state():
++ */
++ if (!pi && (uval & FUTEX_WAITERS))
++ futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY);
++
++ return 0;
++}
++
++/*
++ * Fetch a robust-list pointer. Bit 0 signals PI futexes:
++ */
++static inline int fetch_robust_entry(struct robust_list __user **entry,
++ struct robust_list __user * __user *head,
++ unsigned int *pi)
++{
++ unsigned long uentry;
++
++ if (get_user(uentry, (unsigned long __user *)head))
++ return -EFAULT;
++
++ *entry = (void __user *)(uentry & ~1UL);
++ *pi = uentry & 1;
++
++ return 0;
++}
++
++/*
++ * Walk curr->robust_list (very carefully, it's a userspace list!)
++ * and mark any locks found there dead, and notify any waiters.
++ *
++ * We silently return on any sign of list-walking problem.
++ */
++static void exit_robust_list(struct task_struct *curr)
++{
++ struct robust_list_head __user *head = curr->robust_list;
++ struct robust_list __user *entry, *next_entry, *pending;
++ unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
++ unsigned int next_pi;
++ unsigned long futex_offset;
++ int rc;
++
++ if (!futex_cmpxchg_enabled)
++ return;
++
++ /*
++ * Fetch the list head (which was registered earlier, via
++ * sys_set_robust_list()):
++ */
++ if (fetch_robust_entry(&entry, &head->list.next, &pi))
++ return;
++ /*
++ * Fetch the relative futex offset:
++ */
++ if (get_user(futex_offset, &head->futex_offset))
++ return;
++ /*
++ * Fetch any possibly pending lock-add first, and handle it
++ * if it exists:
++ */
++ if (fetch_robust_entry(&pending, &head->list_op_pending, &pip))
++ return;
++
++ next_entry = NULL; /* avoid warning with gcc */
++ while (entry != &head->list) {
++ /*
++ * Fetch the next entry in the list before calling
++ * handle_futex_death:
++ */
++ rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi);
++ /*
++ * A pending lock might already be on the list, so
++ * don't process it twice:
++ */
++ if (entry != pending) {
++ if (handle_futex_death((void __user *)entry + futex_offset,
++ curr, pi, HANDLE_DEATH_LIST))
++ return;
++ }
++ if (rc)
++ return;
++ entry = next_entry;
++ pi = next_pi;
++ /*
++ * Avoid excessively long or circular lists:
++ */
++ if (!--limit)
++ break;
++
++ cond_resched();
++ }
++
++ if (pending) {
++ handle_futex_death((void __user *)pending + futex_offset,
++ curr, pip, HANDLE_DEATH_PENDING);
++ }
++}
++
++#ifdef CONFIG_COMPAT
++static void __user *futex_uaddr(struct robust_list __user *entry,
++ compat_long_t futex_offset)
++{
++ compat_uptr_t base = ptr_to_compat(entry);
++ void __user *uaddr = compat_ptr(base + futex_offset);
++
++ return uaddr;
++}
++
++/*
++ * Fetch a robust-list pointer. Bit 0 signals PI futexes:
++ */
++static inline int
++compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
++ compat_uptr_t __user *head, unsigned int *pi)
++{
++ if (get_user(*uentry, head))
++ return -EFAULT;
++
++ *entry = compat_ptr((*uentry) & ~1);
++ *pi = (unsigned int)(*uentry) & 1;
++
++ return 0;
++}
++
++/*
++ * Walk curr->robust_list (very carefully, it's a userspace list!)
++ * and mark any locks found there dead, and notify any waiters.
++ *
++ * We silently return on any sign of list-walking problem.
++ */
++static void compat_exit_robust_list(struct task_struct *curr)
++{
++ struct compat_robust_list_head __user *head = curr->compat_robust_list;
++ struct robust_list __user *entry, *next_entry, *pending;
++ unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
++ unsigned int next_pi;
++ compat_uptr_t uentry, next_uentry, upending;
++ compat_long_t futex_offset;
++ int rc;
++
++ if (!futex_cmpxchg_enabled)
++ return;
++
++ /*
++ * Fetch the list head (which was registered earlier, via
++ * sys_set_robust_list()):
++ */
++ if (compat_fetch_robust_entry(&uentry, &entry, &head->list.next, &pi))
++ return;
++ /*
++ * Fetch the relative futex offset:
++ */
++ if (get_user(futex_offset, &head->futex_offset))
++ return;
++ /*
++ * Fetch any possibly pending lock-add first, and handle it
++ * if it exists:
++ */
++ if (compat_fetch_robust_entry(&upending, &pending,
++ &head->list_op_pending, &pip))
++ return;
++
++ next_entry = NULL; /* avoid warning with gcc */
++ while (entry != (struct robust_list __user *) &head->list) {
++ /*
++ * Fetch the next entry in the list before calling
++ * handle_futex_death:
++ */
++ rc = compat_fetch_robust_entry(&next_uentry, &next_entry,
++ (compat_uptr_t __user *)&entry->next, &next_pi);
++ /*
++ * A pending lock might already be on the list, so
++ * dont process it twice:
++ */
++ if (entry != pending) {
++ void __user *uaddr = futex_uaddr(entry, futex_offset);
++
++ if (handle_futex_death(uaddr, curr, pi,
++ HANDLE_DEATH_LIST))
++ return;
++ }
++ if (rc)
++ return;
++ uentry = next_uentry;
++ entry = next_entry;
++ pi = next_pi;
++ /*
++ * Avoid excessively long or circular lists:
++ */
++ if (!--limit)
++ break;
++
++ cond_resched();
++ }
++ if (pending) {
++ void __user *uaddr = futex_uaddr(pending, futex_offset);
++
++ handle_futex_death(uaddr, curr, pip, HANDLE_DEATH_PENDING);
++ }
++}
++#endif
++
++#ifdef CONFIG_FUTEX_PI
++
++/*
++ * This task is holding PI mutexes at exit time => bad.
++ * Kernel cleans up PI-state, but userspace is likely hosed.
++ * (Robust-futex cleanup is separate and might save the day for userspace.)
++ */
++static void exit_pi_state_list(struct task_struct *curr)
++{
++ struct list_head *next, *head = &curr->pi_state_list;
++ struct futex_pi_state *pi_state;
++ struct futex_hash_bucket *hb;
++ union futex_key key = FUTEX_KEY_INIT;
++
++ if (!futex_cmpxchg_enabled)
++ return;
++ /*
++ * We are a ZOMBIE and nobody can enqueue itself on
++ * pi_state_list anymore, but we have to be careful
++ * versus waiters unqueueing themselves:
++ */
++ raw_spin_lock_irq(&curr->pi_lock);
++ while (!list_empty(head)) {
++ next = head->next;
++ pi_state = list_entry(next, struct futex_pi_state, list);
++ key = pi_state->key;
++ hb = futex_hash(&key);
++
++ /*
++ * We can race against put_pi_state() removing itself from the
++ * list (a waiter going away). put_pi_state() will first
++ * decrement the reference count and then modify the list, so
++ * its possible to see the list entry but fail this reference
++ * acquire.
++ *
++ * In that case; drop the locks to let put_pi_state() make
++ * progress and retry the loop.
++ */
++ if (!refcount_inc_not_zero(&pi_state->refcount)) {
++ raw_spin_unlock_irq(&curr->pi_lock);
++ cpu_relax();
++ raw_spin_lock_irq(&curr->pi_lock);
++ continue;
++ }
++ raw_spin_unlock_irq(&curr->pi_lock);
++
++ spin_lock(&hb->lock);
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++ raw_spin_lock(&curr->pi_lock);
++ /*
++ * We dropped the pi-lock, so re-check whether this
++ * task still owns the PI-state:
++ */
++ if (head->next != next) {
++ /* retain curr->pi_lock for the loop invariant */
++ raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
++ spin_unlock(&hb->lock);
++ put_pi_state(pi_state);
++ continue;
++ }
++
++ WARN_ON(pi_state->owner != curr);
++ WARN_ON(list_empty(&pi_state->list));
++ list_del_init(&pi_state->list);
++ pi_state->owner = NULL;
++
++ raw_spin_unlock(&curr->pi_lock);
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ spin_unlock(&hb->lock);
++
++ rt_mutex_futex_unlock(&pi_state->pi_mutex);
++ put_pi_state(pi_state);
++
++ raw_spin_lock_irq(&curr->pi_lock);
++ }
++ raw_spin_unlock_irq(&curr->pi_lock);
++}
++#else
++static inline void exit_pi_state_list(struct task_struct *curr) { }
++#endif
++
++static void futex_cleanup(struct task_struct *tsk)
++{
++ if (unlikely(tsk->robust_list)) {
++ exit_robust_list(tsk);
++ tsk->robust_list = NULL;
++ }
++
++#ifdef CONFIG_COMPAT
++ if (unlikely(tsk->compat_robust_list)) {
++ compat_exit_robust_list(tsk);
++ tsk->compat_robust_list = NULL;
++ }
++#endif
++
++ if (unlikely(!list_empty(&tsk->pi_state_list)))
++ exit_pi_state_list(tsk);
++}
++
++/**
++ * futex_exit_recursive - Set the tasks futex state to FUTEX_STATE_DEAD
++ * @tsk: task to set the state on
++ *
++ * Set the futex exit state of the task lockless. The futex waiter code
++ * observes that state when a task is exiting and loops until the task has
++ * actually finished the futex cleanup. The worst case for this is that the
++ * waiter runs through the wait loop until the state becomes visible.
++ *
++ * This is called from the recursive fault handling path in do_exit().
++ *
++ * This is best effort. Either the futex exit code has run already or
++ * not. If the OWNER_DIED bit has been set on the futex then the waiter can
++ * take it over. If not, the problem is pushed back to user space. If the
++ * futex exit code did not run yet, then an already queued waiter might
++ * block forever, but there is nothing which can be done about that.
++ */
++void futex_exit_recursive(struct task_struct *tsk)
++{
++ /* If the state is FUTEX_STATE_EXITING then futex_exit_mutex is held */
++ if (tsk->futex_state == FUTEX_STATE_EXITING)
++ mutex_unlock(&tsk->futex_exit_mutex);
++ tsk->futex_state = FUTEX_STATE_DEAD;
++}
++
++static void futex_cleanup_begin(struct task_struct *tsk)
++{
++ /*
++ * Prevent various race issues against a concurrent incoming waiter
++ * including live locks by forcing the waiter to block on
++ * tsk->futex_exit_mutex when it observes FUTEX_STATE_EXITING in
++ * attach_to_pi_owner().
++ */
++ mutex_lock(&tsk->futex_exit_mutex);
++
++ /*
++ * Switch the state to FUTEX_STATE_EXITING under tsk->pi_lock.
++ *
++ * This ensures that all subsequent checks of tsk->futex_state in
++ * attach_to_pi_owner() must observe FUTEX_STATE_EXITING with
++ * tsk->pi_lock held.
++ *
++ * It guarantees also that a pi_state which was queued right before
++ * the state change under tsk->pi_lock by a concurrent waiter must
++ * be observed in exit_pi_state_list().
++ */
++ raw_spin_lock_irq(&tsk->pi_lock);
++ tsk->futex_state = FUTEX_STATE_EXITING;
++ raw_spin_unlock_irq(&tsk->pi_lock);
++}
++
++static void futex_cleanup_end(struct task_struct *tsk, int state)
++{
++ /*
++ * Lockless store. The only side effect is that an observer might
++ * take another loop until it becomes visible.
++ */
++ tsk->futex_state = state;
++ /*
++ * Drop the exit protection. This unblocks waiters which observed
++ * FUTEX_STATE_EXITING to reevaluate the state.
++ */
++ mutex_unlock(&tsk->futex_exit_mutex);
++}
++
++void futex_exec_release(struct task_struct *tsk)
++{
++ /*
++ * The state handling is done for consistency, but in the case of
++ * exec() there is no way to prevent further damage as the PID stays
++ * the same. But for the unlikely and arguably buggy case that a
++ * futex is held on exec(), this provides at least as much state
++ * consistency protection which is possible.
++ */
++ futex_cleanup_begin(tsk);
++ futex_cleanup(tsk);
++ /*
++ * Reset the state to FUTEX_STATE_OK. The task is alive and about
++ * exec a new binary.
++ */
++ futex_cleanup_end(tsk, FUTEX_STATE_OK);
++}
++
++void futex_exit_release(struct task_struct *tsk)
++{
++ futex_cleanup_begin(tsk);
++ futex_cleanup(tsk);
++ futex_cleanup_end(tsk, FUTEX_STATE_DEAD);
++}
++
++static void __init futex_detect_cmpxchg(void)
++{
++#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
++ u32 curval;
++
++ /*
++ * This will fail and we want it. Some arch implementations do
++ * runtime detection of the futex_atomic_cmpxchg_inatomic()
++ * functionality. We want to know that before we call in any
++ * of the complex code paths. Also we want to prevent
++ * registration of robust lists in that case. NULL is
++ * guaranteed to fault and we get -EFAULT on functional
++ * implementation, the non-functional ones will return
++ * -ENOSYS.
++ */
++ if (futex_cmpxchg_value_locked(&curval, NULL, 0, 0) == -EFAULT)
++ futex_cmpxchg_enabled = 1;
++#endif
++}
++
++static int __init futex_init(void)
++{
++ unsigned int futex_shift;
++ unsigned long i;
++
++#if CONFIG_BASE_SMALL
++ futex_hashsize = 16;
++#else
++ futex_hashsize = roundup_pow_of_two(256 * num_possible_cpus());
++#endif
++
++ futex_queues = alloc_large_system_hash("futex", sizeof(*futex_queues),
++ futex_hashsize, 0,
++ futex_hashsize < 256 ? HASH_SMALL : 0,
++ &futex_shift, NULL,
++ futex_hashsize, futex_hashsize);
++ futex_hashsize = 1UL << futex_shift;
++
++ futex_detect_cmpxchg();
++
++ for (i = 0; i < futex_hashsize; i++) {
++ atomic_set(&futex_queues[i].waiters, 0);
++ plist_head_init(&futex_queues[i].chain);
++ spin_lock_init(&futex_queues[i].lock);
++ }
++
++ return 0;
++}
++core_initcall(futex_init);
+diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h
+new file mode 100644
+index 000000000..948fcf317
+--- /dev/null
++++ b/kernel/futex/futex.h
+@@ -0,0 +1,295 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _FUTEX_H
++#define _FUTEX_H
++
++#include <linux/futex.h>
++#include <linux/sched/wake_q.h>
++
++#include <asm/futex.h>
++
++/*
++ * Futex flags used to encode options to functions and preserve them across
++ * restarts.
++ */
++#ifdef CONFIG_MMU
++# define FLAGS_SHARED 0x01
++#else
++/*
++ * NOMMU does not have per process address space. Let the compiler optimize
++ * code away.
++ */
++# define FLAGS_SHARED 0x00
++#endif
++#define FLAGS_CLOCKRT 0x02
++#define FLAGS_HAS_TIMEOUT 0x04
++
++#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
++#define futex_cmpxchg_enabled 1
++#else
++extern int __read_mostly futex_cmpxchg_enabled;
++#endif
++
++#ifdef CONFIG_FAIL_FUTEX
++extern bool should_fail_futex(bool fshared);
++#else
++static inline bool should_fail_futex(bool fshared)
++{
++ return false;
++}
++#endif
++
++/*
++ * Hash buckets are shared by all the futex_keys that hash to the same
++ * location. Each key may have multiple futex_q structures, one for each task
++ * waiting on a futex.
++ */
++struct futex_hash_bucket {
++ atomic_t waiters;
++ spinlock_t lock;
++ struct plist_head chain;
++} ____cacheline_aligned_in_smp;
++
++/*
++ * Priority Inheritance state:
++ */
++struct futex_pi_state {
++ /*
++ * list of 'owned' pi_state instances - these have to be
++ * cleaned up in do_exit() if the task exits prematurely:
++ */
++ struct list_head list;
++
++ /*
++ * The PI object:
++ */
++ struct rt_mutex_base pi_mutex;
++
++ struct task_struct *owner;
++ refcount_t refcount;
++
++ union futex_key key;
++} __randomize_layout;
++
++/**
++ * struct futex_q - The hashed futex queue entry, one per waiting task
++ * @list: priority-sorted list of tasks waiting on this futex
++ * @task: the task waiting on the futex
++ * @lock_ptr: the hash bucket lock
++ * @key: the key the futex is hashed on
++ * @pi_state: optional priority inheritance state
++ * @rt_waiter: rt_waiter storage for use with requeue_pi
++ * @requeue_pi_key: the requeue_pi target futex key
++ * @bitset: bitset for the optional bitmasked wakeup
++ * @requeue_state: State field for futex_requeue_pi()
++ * @requeue_wait: RCU wait for futex_requeue_pi() (RT only)
++ *
++ * We use this hashed waitqueue, instead of a normal wait_queue_entry_t, so
++ * we can wake only the relevant ones (hashed queues may be shared).
++ *
++ * A futex_q has a woken state, just like tasks have TASK_RUNNING.
++ * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
++ * The order of wakeup is always to make the first condition true, then
++ * the second.
++ *
++ * PI futexes are typically woken before they are removed from the hash list via
++ * the rt_mutex code. See futex_unqueue_pi().
++ */
++struct futex_q {
++ struct plist_node list;
++
++ struct task_struct *task;
++ spinlock_t *lock_ptr;
++ union futex_key key;
++ struct futex_pi_state *pi_state;
++ struct rt_mutex_waiter *rt_waiter;
++ union futex_key *requeue_pi_key;
++ u32 bitset;
++ atomic_t requeue_state;
++#ifdef CONFIG_PREEMPT_RT
++ struct rcuwait requeue_wait;
++#endif
++} __randomize_layout;
++
++extern const struct futex_q futex_q_init;
++
++enum futex_access {
++ FUTEX_READ,
++ FUTEX_WRITE
++};
++
++extern int get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key,
++ enum futex_access rw);
++
++extern struct hrtimer_sleeper *
++futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
++ int flags, u64 range_ns);
++
++extern struct futex_hash_bucket *futex_hash(union futex_key *key);
++
++/**
++ * futex_match - Check whether two futex keys are equal
++ * @key1: Pointer to key1
++ * @key2: Pointer to key2
++ *
++ * Return 1 if two futex_keys are equal, 0 otherwise.
++ */
++static inline int futex_match(union futex_key *key1, union futex_key *key2)
++{
++ return (key1 && key2
++ && key1->both.word == key2->both.word
++ && key1->both.ptr == key2->both.ptr
++ && key1->both.offset == key2->both.offset);
++}
++
++extern int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
++ struct futex_q *q, struct futex_hash_bucket **hb);
++extern void futex_wait_queue(struct futex_hash_bucket *hb, struct futex_q *q,
++ struct hrtimer_sleeper *timeout);
++extern void futex_wake_mark(struct wake_q_head *wake_q, struct futex_q *q);
++
++extern int fault_in_user_writeable(u32 __user *uaddr);
++extern int futex_cmpxchg_value_locked(u32 *curval, u32 __user *uaddr, u32 uval, u32 newval);
++extern int futex_get_value_locked(u32 *dest, u32 __user *from);
++extern struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb, union futex_key *key);
++
++extern void __futex_unqueue(struct futex_q *q);
++extern void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb);
++extern int futex_unqueue(struct futex_q *q);
++
++/**
++ * futex_queue() - Enqueue the futex_q on the futex_hash_bucket
++ * @q: The futex_q to enqueue
++ * @hb: The destination hash bucket
++ *
++ * The hb->lock must be held by the caller, and is released here. A call to
++ * futex_queue() is typically paired with exactly one call to futex_unqueue(). The
++ * exceptions involve the PI related operations, which may use futex_unqueue_pi()
++ * or nothing if the unqueue is done as part of the wake process and the unqueue
++ * state is implicit in the state of woken task (see futex_wait_requeue_pi() for
++ * an example).
++ */
++static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket *hb)
++ __releases(&hb->lock)
++{
++ __futex_queue(q, hb);
++ spin_unlock(&hb->lock);
++}
++
++extern void futex_unqueue_pi(struct futex_q *q);
++
++extern void wait_for_owner_exiting(int ret, struct task_struct *exiting);
++
++/*
++ * Reflects a new waiter being added to the waitqueue.
++ */
++static inline void futex_hb_waiters_inc(struct futex_hash_bucket *hb)
++{
++#ifdef CONFIG_SMP
++ atomic_inc(&hb->waiters);
++ /*
++ * Full barrier (A), see the ordering comment above.
++ */
++ smp_mb__after_atomic();
++#endif
++}
++
++/*
++ * Reflects a waiter being removed from the waitqueue by wakeup
++ * paths.
++ */
++static inline void futex_hb_waiters_dec(struct futex_hash_bucket *hb)
++{
++#ifdef CONFIG_SMP
++ atomic_dec(&hb->waiters);
++#endif
++}
++
++static inline int futex_hb_waiters_pending(struct futex_hash_bucket *hb)
++{
++#ifdef CONFIG_SMP
++ /*
++ * Full barrier (B), see the ordering comment above.
++ */
++ smp_mb();
++ return atomic_read(&hb->waiters);
++#else
++ return 1;
++#endif
++}
++
++extern struct futex_hash_bucket *futex_q_lock(struct futex_q *q);
++extern void futex_q_unlock(struct futex_hash_bucket *hb);
++
++
++extern int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
++ union futex_key *key,
++ struct futex_pi_state **ps,
++ struct task_struct *task,
++ struct task_struct **exiting,
++ int set_waiters);
++
++extern int refill_pi_state_cache(void);
++extern void get_pi_state(struct futex_pi_state *pi_state);
++extern void put_pi_state(struct futex_pi_state *pi_state);
++extern int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked);
++
++/*
++ * Express the locking dependencies for lockdep:
++ */
++static inline void
++double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
++{
++ if (hb1 > hb2)
++ swap(hb1, hb2);
++
++ spin_lock(&hb1->lock);
++ if (hb1 != hb2)
++ spin_lock_nested(&hb2->lock, SINGLE_DEPTH_NESTING);
++}
++
++static inline void
++double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
++{
++ spin_unlock(&hb1->lock);
++ if (hb1 != hb2)
++ spin_unlock(&hb2->lock);
++}
++
++/* syscalls */
++
++extern int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, u32
++ val, ktime_t *abs_time, u32 bitset, u32 __user
++ *uaddr2);
++
++extern int futex_requeue(u32 __user *uaddr1, unsigned int flags,
++ u32 __user *uaddr2, int nr_wake, int nr_requeue,
++ u32 *cmpval, int requeue_pi);
++
++extern int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
++ ktime_t *abs_time, u32 bitset);
++
++/**
++ * struct futex_vector - Auxiliary struct for futex_waitv()
++ * @w: Userspace provided data
++ * @q: Kernel side data
++ *
++ * Struct used to build an array with all data need for futex_waitv()
++ */
++struct futex_vector {
++ struct futex_waitv w;
++ struct futex_q q;
++};
++
++extern int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
++ struct hrtimer_sleeper *to);
++
++extern int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset);
++
++extern int futex_wake_op(u32 __user *uaddr1, unsigned int flags,
++ u32 __user *uaddr2, int nr_wake, int nr_wake2, int op);
++
++extern int futex_unlock_pi(u32 __user *uaddr, unsigned int flags);
++
++extern int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock);
++
++#endif /* _FUTEX_H */
+diff --git a/kernel/futex/pi.c b/kernel/futex/pi.c
+new file mode 100644
+index 000000000..183b28c32
+--- /dev/null
++++ b/kernel/futex/pi.c
+@@ -0,0 +1,1233 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#include <linux/slab.h>
++#include <linux/sched/task.h>
++
++#include "futex.h"
++#include "../locking/rtmutex_common.h"
++
++/*
++ * PI code:
++ */
++int refill_pi_state_cache(void)
++{
++ struct futex_pi_state *pi_state;
++
++ if (likely(current->pi_state_cache))
++ return 0;
++
++ pi_state = kzalloc(sizeof(*pi_state), GFP_KERNEL);
++
++ if (!pi_state)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&pi_state->list);
++ /* pi_mutex gets initialized later */
++ pi_state->owner = NULL;
++ refcount_set(&pi_state->refcount, 1);
++ pi_state->key = FUTEX_KEY_INIT;
++
++ current->pi_state_cache = pi_state;
++
++ return 0;
++}
++
++static struct futex_pi_state *alloc_pi_state(void)
++{
++ struct futex_pi_state *pi_state = current->pi_state_cache;
++
++ WARN_ON(!pi_state);
++ current->pi_state_cache = NULL;
++
++ return pi_state;
++}
++
++static void pi_state_update_owner(struct futex_pi_state *pi_state,
++ struct task_struct *new_owner)
++{
++ struct task_struct *old_owner = pi_state->owner;
++
++ lockdep_assert_held(&pi_state->pi_mutex.wait_lock);
++
++ if (old_owner) {
++ raw_spin_lock(&old_owner->pi_lock);
++ WARN_ON(list_empty(&pi_state->list));
++ list_del_init(&pi_state->list);
++ raw_spin_unlock(&old_owner->pi_lock);
++ }
++
++ if (new_owner) {
++ raw_spin_lock(&new_owner->pi_lock);
++ WARN_ON(!list_empty(&pi_state->list));
++ list_add(&pi_state->list, &new_owner->pi_state_list);
++ pi_state->owner = new_owner;
++ raw_spin_unlock(&new_owner->pi_lock);
++ }
++}
++
++void get_pi_state(struct futex_pi_state *pi_state)
++{
++ WARN_ON_ONCE(!refcount_inc_not_zero(&pi_state->refcount));
++}
++
++/*
++ * Drops a reference to the pi_state object and frees or caches it
++ * when the last reference is gone.
++ */
++void put_pi_state(struct futex_pi_state *pi_state)
++{
++ if (!pi_state)
++ return;
++
++ if (!refcount_dec_and_test(&pi_state->refcount))
++ return;
++
++ /*
++ * If pi_state->owner is NULL, the owner is most probably dying
++ * and has cleaned up the pi_state already
++ */
++ if (pi_state->owner) {
++ unsigned long flags;
++
++ raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags);
++ pi_state_update_owner(pi_state, NULL);
++ rt_mutex_proxy_unlock(&pi_state->pi_mutex);
++ raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags);
++ }
++
++ if (current->pi_state_cache) {
++ kfree(pi_state);
++ } else {
++ /*
++ * pi_state->list is already empty.
++ * clear pi_state->owner.
++ * refcount is at 0 - put it back to 1.
++ */
++ pi_state->owner = NULL;
++ refcount_set(&pi_state->refcount, 1);
++ current->pi_state_cache = pi_state;
++ }
++}
++
++/*
++ * We need to check the following states:
++ *
++ * Waiter | pi_state | pi->owner | uTID | uODIED | ?
++ *
++ * [1] NULL | --- | --- | 0 | 0/1 | Valid
++ * [2] NULL | --- | --- | >0 | 0/1 | Valid
++ *
++ * [3] Found | NULL | -- | Any | 0/1 | Invalid
++ *
++ * [4] Found | Found | NULL | 0 | 1 | Valid
++ * [5] Found | Found | NULL | >0 | 1 | Invalid
++ *
++ * [6] Found | Found | task | 0 | 1 | Valid
++ *
++ * [7] Found | Found | NULL | Any | 0 | Invalid
++ *
++ * [8] Found | Found | task | ==taskTID | 0/1 | Valid
++ * [9] Found | Found | task | 0 | 0 | Invalid
++ * [10] Found | Found | task | !=taskTID | 0/1 | Invalid
++ *
++ * [1] Indicates that the kernel can acquire the futex atomically. We
++ * came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
++ *
++ * [2] Valid, if TID does not belong to a kernel thread. If no matching
++ * thread is found then it indicates that the owner TID has died.
++ *
++ * [3] Invalid. The waiter is queued on a non PI futex
++ *
++ * [4] Valid state after exit_robust_list(), which sets the user space
++ * value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
++ *
++ * [5] The user space value got manipulated between exit_robust_list()
++ * and exit_pi_state_list()
++ *
++ * [6] Valid state after exit_pi_state_list() which sets the new owner in
++ * the pi_state but cannot access the user space value.
++ *
++ * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
++ *
++ * [8] Owner and user space value match
++ *
++ * [9] There is no transient state which sets the user space TID to 0
++ * except exit_robust_list(), but this is indicated by the
++ * FUTEX_OWNER_DIED bit. See [4]
++ *
++ * [10] There is no transient state which leaves owner and user space
++ * TID out of sync. Except one error case where the kernel is denied
++ * write access to the user address, see fixup_pi_state_owner().
++ *
++ *
++ * Serialization and lifetime rules:
++ *
++ * hb->lock:
++ *
++ * hb -> futex_q, relation
++ * futex_q -> pi_state, relation
++ *
++ * (cannot be raw because hb can contain arbitrary amount
++ * of futex_q's)
++ *
++ * pi_mutex->wait_lock:
++ *
++ * {uval, pi_state}
++ *
++ * (and pi_mutex 'obviously')
++ *
++ * p->pi_lock:
++ *
++ * p->pi_state_list -> pi_state->list, relation
++ * pi_mutex->owner -> pi_state->owner, relation
++ *
++ * pi_state->refcount:
++ *
++ * pi_state lifetime
++ *
++ *
++ * Lock order:
++ *
++ * hb->lock
++ * pi_mutex->wait_lock
++ * p->pi_lock
++ *
++ */
++
++/*
++ * Validate that the existing waiter has a pi_state and sanity check
++ * the pi_state against the user space value. If correct, attach to
++ * it.
++ */
++static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
++ struct futex_pi_state *pi_state,
++ struct futex_pi_state **ps)
++{
++ pid_t pid = uval & FUTEX_TID_MASK;
++ u32 uval2;
++ int ret;
++
++ /*
++ * Userspace might have messed up non-PI and PI futexes [3]
++ */
++ if (unlikely(!pi_state))
++ return -EINVAL;
++
++ /*
++ * We get here with hb->lock held, and having found a
++ * futex_top_waiter(). This means that futex_lock_pi() of said futex_q
++ * has dropped the hb->lock in between futex_queue() and futex_unqueue_pi(),
++ * which in turn means that futex_lock_pi() still has a reference on
++ * our pi_state.
++ *
++ * The waiter holding a reference on @pi_state also protects against
++ * the unlocked put_pi_state() in futex_unlock_pi(), futex_lock_pi()
++ * and futex_wait_requeue_pi() as it cannot go to 0 and consequently
++ * free pi_state before we can take a reference ourselves.
++ */
++ WARN_ON(!refcount_read(&pi_state->refcount));
++
++ /*
++ * Now that we have a pi_state, we can acquire wait_lock
++ * and do the state validation.
++ */
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++
++ /*
++ * Since {uval, pi_state} is serialized by wait_lock, and our current
++ * uval was read without holding it, it can have changed. Verify it
++ * still is what we expect it to be, otherwise retry the entire
++ * operation.
++ */
++ if (futex_get_value_locked(&uval2, uaddr))
++ goto out_efault;
++
++ if (uval != uval2)
++ goto out_eagain;
++
++ /*
++ * Handle the owner died case:
++ */
++ if (uval & FUTEX_OWNER_DIED) {
++ /*
++ * exit_pi_state_list sets owner to NULL and wakes the
++ * topmost waiter. The task which acquires the
++ * pi_state->rt_mutex will fixup owner.
++ */
++ if (!pi_state->owner) {
++ /*
++ * No pi state owner, but the user space TID
++ * is not 0. Inconsistent state. [5]
++ */
++ if (pid)
++ goto out_einval;
++ /*
++ * Take a ref on the state and return success. [4]
++ */
++ goto out_attach;
++ }
++
++ /*
++ * If TID is 0, then either the dying owner has not
++ * yet executed exit_pi_state_list() or some waiter
++ * acquired the rtmutex in the pi state, but did not
++ * yet fixup the TID in user space.
++ *
++ * Take a ref on the state and return success. [6]
++ */
++ if (!pid)
++ goto out_attach;
++ } else {
++ /*
++ * If the owner died bit is not set, then the pi_state
++ * must have an owner. [7]
++ */
++ if (!pi_state->owner)
++ goto out_einval;
++ }
++
++ /*
++ * Bail out if user space manipulated the futex value. If pi
++ * state exists then the owner TID must be the same as the
++ * user space TID. [9/10]
++ */
++ if (pid != task_pid_vnr(pi_state->owner))
++ goto out_einval;
++
++out_attach:
++ get_pi_state(pi_state);
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ *ps = pi_state;
++ return 0;
++
++out_einval:
++ ret = -EINVAL;
++ goto out_error;
++
++out_eagain:
++ ret = -EAGAIN;
++ goto out_error;
++
++out_efault:
++ ret = -EFAULT;
++ goto out_error;
++
++out_error:
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ return ret;
++}
++
++static int handle_exit_race(u32 __user *uaddr, u32 uval,
++ struct task_struct *tsk)
++{
++ u32 uval2;
++
++ /*
++ * If the futex exit state is not yet FUTEX_STATE_DEAD, tell the
++ * caller that the alleged owner is busy.
++ */
++ if (tsk && tsk->futex_state != FUTEX_STATE_DEAD)
++ return -EBUSY;
++
++ /*
++ * Reread the user space value to handle the following situation:
++ *
++ * CPU0 CPU1
++ *
++ * sys_exit() sys_futex()
++ * do_exit() futex_lock_pi()
++ * futex_lock_pi_atomic()
++ * exit_signals(tsk) No waiters:
++ * tsk->flags |= PF_EXITING; *uaddr == 0x00000PID
++ * mm_release(tsk) Set waiter bit
++ * exit_robust_list(tsk) { *uaddr = 0x80000PID;
++ * Set owner died attach_to_pi_owner() {
++ * *uaddr = 0xC0000000; tsk = get_task(PID);
++ * } if (!tsk->flags & PF_EXITING) {
++ * ... attach();
++ * tsk->futex_state = } else {
++ * FUTEX_STATE_DEAD; if (tsk->futex_state !=
++ * FUTEX_STATE_DEAD)
++ * return -EAGAIN;
++ * return -ESRCH; <--- FAIL
++ * }
++ *
++ * Returning ESRCH unconditionally is wrong here because the
++ * user space value has been changed by the exiting task.
++ *
++ * The same logic applies to the case where the exiting task is
++ * already gone.
++ */
++ if (futex_get_value_locked(&uval2, uaddr))
++ return -EFAULT;
++
++ /* If the user space value has changed, try again. */
++ if (uval2 != uval)
++ return -EAGAIN;
++
++ /*
++ * The exiting task did not have a robust list, the robust list was
++ * corrupted or the user space value in *uaddr is simply bogus.
++ * Give up and tell user space.
++ */
++ return -ESRCH;
++}
++
++static void __attach_to_pi_owner(struct task_struct *p, union futex_key *key,
++ struct futex_pi_state **ps)
++{
++ /*
++ * No existing pi state. First waiter. [2]
++ *
++ * This creates pi_state, we have hb->lock held, this means nothing can
++ * observe this state, wait_lock is irrelevant.
++ */
++ struct futex_pi_state *pi_state = alloc_pi_state();
++
++ /*
++ * Initialize the pi_mutex in locked state and make @p
++ * the owner of it:
++ */
++ rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p);
++
++ /* Store the key for possible exit cleanups: */
++ pi_state->key = *key;
++
++ WARN_ON(!list_empty(&pi_state->list));
++ list_add(&pi_state->list, &p->pi_state_list);
++ /*
++ * Assignment without holding pi_state->pi_mutex.wait_lock is safe
++ * because there is no concurrency as the object is not published yet.
++ */
++ pi_state->owner = p;
++
++ *ps = pi_state;
++}
++/*
++ * Lookup the task for the TID provided from user space and attach to
++ * it after doing proper sanity checks.
++ */
++static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key,
++ struct futex_pi_state **ps,
++ struct task_struct **exiting)
++{
++ pid_t pid = uval & FUTEX_TID_MASK;
++ struct task_struct *p;
++
++ /*
++ * We are the first waiter - try to look up the real owner and attach
++ * the new pi_state to it, but bail out when TID = 0 [1]
++ *
++ * The !pid check is paranoid. None of the call sites should end up
++ * with pid == 0, but better safe than sorry. Let the caller retry
++ */
++ if (!pid)
++ return -EAGAIN;
++ p = find_get_task_by_vpid(pid);
++ if (!p)
++ return handle_exit_race(uaddr, uval, NULL);
++
++ if (unlikely(p->flags & PF_KTHREAD)) {
++ put_task_struct(p);
++ return -EPERM;
++ }
++
++ /*
++ * We need to look at the task state to figure out, whether the
++ * task is exiting. To protect against the change of the task state
++ * in futex_exit_release(), we do this protected by p->pi_lock:
++ */
++ raw_spin_lock_irq(&p->pi_lock);
++ if (unlikely(p->futex_state != FUTEX_STATE_OK)) {
++ /*
++ * The task is on the way out. When the futex state is
++ * FUTEX_STATE_DEAD, we know that the task has finished
++ * the cleanup:
++ */
++ int ret = handle_exit_race(uaddr, uval, p);
++
++ raw_spin_unlock_irq(&p->pi_lock);
++ /*
++ * If the owner task is between FUTEX_STATE_EXITING and
++ * FUTEX_STATE_DEAD then store the task pointer and keep
++ * the reference on the task struct. The calling code will
++ * drop all locks, wait for the task to reach
++ * FUTEX_STATE_DEAD and then drop the refcount. This is
++ * required to prevent a live lock when the current task
++ * preempted the exiting task between the two states.
++ */
++ if (ret == -EBUSY)
++ *exiting = p;
++ else
++ put_task_struct(p);
++ return ret;
++ }
++
++ __attach_to_pi_owner(p, key, ps);
++ raw_spin_unlock_irq(&p->pi_lock);
++
++ put_task_struct(p);
++
++ return 0;
++}
++
++static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval)
++{
++ int err;
++ u32 curval;
++
++ if (unlikely(should_fail_futex(true)))
++ return -EFAULT;
++
++ err = futex_cmpxchg_value_locked(&curval, uaddr, uval, newval);
++ if (unlikely(err))
++ return err;
++
++ /* If user space value changed, let the caller retry */
++ return curval != uval ? -EAGAIN : 0;
++}
++
++/**
++ * futex_lock_pi_atomic() - Atomic work required to acquire a pi aware futex
++ * @uaddr: the pi futex user address
++ * @hb: the pi futex hash bucket
++ * @key: the futex key associated with uaddr and hb
++ * @ps: the pi_state pointer where we store the result of the
++ * lookup
++ * @task: the task to perform the atomic lock work for. This will
++ * be "current" except in the case of requeue pi.
++ * @exiting: Pointer to store the task pointer of the owner task
++ * which is in the middle of exiting
++ * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0)
++ *
++ * Return:
++ * - 0 - ready to wait;
++ * - 1 - acquired the lock;
++ * - <0 - error
++ *
++ * The hb->lock must be held by the caller.
++ *
++ * @exiting is only set when the return value is -EBUSY. If so, this holds
++ * a refcount on the exiting task on return and the caller needs to drop it
++ * after waiting for the exit to complete.
++ */
++int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
++ union futex_key *key,
++ struct futex_pi_state **ps,
++ struct task_struct *task,
++ struct task_struct **exiting,
++ int set_waiters)
++{
++ u32 uval, newval, vpid = task_pid_vnr(task);
++ struct futex_q *top_waiter;
++ int ret;
++
++ /*
++ * Read the user space value first so we can validate a few
++ * things before proceeding further.
++ */
++ if (futex_get_value_locked(&uval, uaddr))
++ return -EFAULT;
++
++ if (unlikely(should_fail_futex(true)))
++ return -EFAULT;
++
++ /*
++ * Detect deadlocks.
++ */
++ if ((unlikely((uval & FUTEX_TID_MASK) == vpid)))
++ return -EDEADLK;
++
++ if ((unlikely(should_fail_futex(true))))
++ return -EDEADLK;
++
++ /*
++ * Lookup existing state first. If it exists, try to attach to
++ * its pi_state.
++ */
++ top_waiter = futex_top_waiter(hb, key);
++ if (top_waiter)
++ return attach_to_pi_state(uaddr, uval, top_waiter->pi_state, ps);
++
++ /*
++ * No waiter and user TID is 0. We are here because the
++ * waiters or the owner died bit is set or called from
++ * requeue_cmp_pi or for whatever reason something took the
++ * syscall.
++ */
++ if (!(uval & FUTEX_TID_MASK)) {
++ /*
++ * We take over the futex. No other waiters and the user space
++ * TID is 0. We preserve the owner died bit.
++ */
++ newval = uval & FUTEX_OWNER_DIED;
++ newval |= vpid;
++
++ /* The futex requeue_pi code can enforce the waiters bit */
++ if (set_waiters)
++ newval |= FUTEX_WAITERS;
++
++ ret = lock_pi_update_atomic(uaddr, uval, newval);
++ if (ret)
++ return ret;
++
++ /*
++ * If the waiter bit was requested the caller also needs PI
++ * state attached to the new owner of the user space futex.
++ *
++ * @task is guaranteed to be alive and it cannot be exiting
++ * because it is either sleeping or waiting in
++ * futex_requeue_pi_wakeup_sync().
++ *
++ * No need to do the full attach_to_pi_owner() exercise
++ * because @task is known and valid.
++ */
++ if (set_waiters) {
++ raw_spin_lock_irq(&task->pi_lock);
++ __attach_to_pi_owner(task, key, ps);
++ raw_spin_unlock_irq(&task->pi_lock);
++ }
++ return 1;
++ }
++
++ /*
++ * First waiter. Set the waiters bit before attaching ourself to
++ * the owner. If owner tries to unlock, it will be forced into
++ * the kernel and blocked on hb->lock.
++ */
++ newval = uval | FUTEX_WAITERS;
++ ret = lock_pi_update_atomic(uaddr, uval, newval);
++ if (ret)
++ return ret;
++ /*
++ * If the update of the user space value succeeded, we try to
++ * attach to the owner. If that fails, no harm done, we only
++ * set the FUTEX_WAITERS bit in the user space variable.
++ */
++ return attach_to_pi_owner(uaddr, newval, key, ps, exiting);
++}
++
++/*
++ * Caller must hold a reference on @pi_state.
++ */
++static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state)
++{
++ struct rt_mutex_waiter *top_waiter;
++ struct task_struct *new_owner;
++ bool postunlock = false;
++ DEFINE_RT_WAKE_Q(wqh);
++ u32 curval, newval;
++ int ret = 0;
++
++ top_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex);
++ if (WARN_ON_ONCE(!top_waiter)) {
++ /*
++ * As per the comment in futex_unlock_pi() this should not happen.
++ *
++ * When this happens, give up our locks and try again, giving
++ * the futex_lock_pi() instance time to complete, either by
++ * waiting on the rtmutex or removing itself from the futex
++ * queue.
++ */
++ ret = -EAGAIN;
++ goto out_unlock;
++ }
++
++ new_owner = top_waiter->task;
++
++ /*
++ * We pass it to the next owner. The WAITERS bit is always kept
++ * enabled while there is PI state around. We cleanup the owner
++ * died bit, because we are the owner.
++ */
++ newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
++
++ if (unlikely(should_fail_futex(true))) {
++ ret = -EFAULT;
++ goto out_unlock;
++ }
++
++ ret = futex_cmpxchg_value_locked(&curval, uaddr, uval, newval);
++ if (!ret && (curval != uval)) {
++ /*
++ * If a unconditional UNLOCK_PI operation (user space did not
++ * try the TID->0 transition) raced with a waiter setting the
++ * FUTEX_WAITERS flag between get_user() and locking the hash
++ * bucket lock, retry the operation.
++ */
++ if ((FUTEX_TID_MASK & curval) == uval)
++ ret = -EAGAIN;
++ else
++ ret = -EINVAL;
++ }
++
++ if (!ret) {
++ /*
++ * This is a point of no return; once we modified the uval
++ * there is no going back and subsequent operations must
++ * not fail.
++ */
++ pi_state_update_owner(pi_state, new_owner);
++ postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wqh);
++ }
++
++out_unlock:
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++
++ if (postunlock)
++ rt_mutex_postunlock(&wqh);
++
++ return ret;
++}
++
++static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
++ struct task_struct *argowner)
++{
++ struct futex_pi_state *pi_state = q->pi_state;
++ struct task_struct *oldowner, *newowner;
++ u32 uval, curval, newval, newtid;
++ int err = 0;
++
++ oldowner = pi_state->owner;
++
++ /*
++ * We are here because either:
++ *
++ * - we stole the lock and pi_state->owner needs updating to reflect
++ * that (@argowner == current),
++ *
++ * or:
++ *
++ * - someone stole our lock and we need to fix things to point to the
++ * new owner (@argowner == NULL).
++ *
++ * Either way, we have to replace the TID in the user space variable.
++ * This must be atomic as we have to preserve the owner died bit here.
++ *
++ * Note: We write the user space value _before_ changing the pi_state
++ * because we can fault here. Imagine swapped out pages or a fork
++ * that marked all the anonymous memory readonly for cow.
++ *
++ * Modifying pi_state _before_ the user space value would leave the
++ * pi_state in an inconsistent state when we fault here, because we
++ * need to drop the locks to handle the fault. This might be observed
++ * in the PID checks when attaching to PI state .
++ */
++retry:
++ if (!argowner) {
++ if (oldowner != current) {
++ /*
++ * We raced against a concurrent self; things are
++ * already fixed up. Nothing to do.
++ */
++ return 0;
++ }
++
++ if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) {
++ /* We got the lock. pi_state is correct. Tell caller. */
++ return 1;
++ }
++
++ /*
++ * The trylock just failed, so either there is an owner or
++ * there is a higher priority waiter than this one.
++ */
++ newowner = rt_mutex_owner(&pi_state->pi_mutex);
++ /*
++ * If the higher priority waiter has not yet taken over the
++ * rtmutex then newowner is NULL. We can't return here with
++ * that state because it's inconsistent vs. the user space
++ * state. So drop the locks and try again. It's a valid
++ * situation and not any different from the other retry
++ * conditions.
++ */
++ if (unlikely(!newowner)) {
++ err = -EAGAIN;
++ goto handle_err;
++ }
++ } else {
++ WARN_ON_ONCE(argowner != current);
++ if (oldowner == current) {
++ /*
++ * We raced against a concurrent self; things are
++ * already fixed up. Nothing to do.
++ */
++ return 1;
++ }
++ newowner = argowner;
++ }
++
++ newtid = task_pid_vnr(newowner) | FUTEX_WAITERS;
++ /* Owner died? */
++ if (!pi_state->owner)
++ newtid |= FUTEX_OWNER_DIED;
++
++ err = futex_get_value_locked(&uval, uaddr);
++ if (err)
++ goto handle_err;
++
++ for (;;) {
++ newval = (uval & FUTEX_OWNER_DIED) | newtid;
++
++ err = futex_cmpxchg_value_locked(&curval, uaddr, uval, newval);
++ if (err)
++ goto handle_err;
++
++ if (curval == uval)
++ break;
++ uval = curval;
++ }
++
++ /*
++ * We fixed up user space. Now we need to fix the pi_state
++ * itself.
++ */
++ pi_state_update_owner(pi_state, newowner);
++
++ return argowner == current;
++
++ /*
++ * In order to reschedule or handle a page fault, we need to drop the
++ * locks here. In the case of a fault, this gives the other task
++ * (either the highest priority waiter itself or the task which stole
++ * the rtmutex) the chance to try the fixup of the pi_state. So once we
++ * are back from handling the fault we need to check the pi_state after
++ * reacquiring the locks and before trying to do another fixup. When
++ * the fixup has been done already we simply return.
++ *
++ * Note: we hold both hb->lock and pi_mutex->wait_lock. We can safely
++ * drop hb->lock since the caller owns the hb -> futex_q relation.
++ * Dropping the pi_mutex->wait_lock requires the state revalidate.
++ */
++handle_err:
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ spin_unlock(q->lock_ptr);
++
++ switch (err) {
++ case -EFAULT:
++ err = fault_in_user_writeable(uaddr);
++ break;
++
++ case -EAGAIN:
++ cond_resched();
++ err = 0;
++ break;
++
++ default:
++ WARN_ON_ONCE(1);
++ break;
++ }
++
++ spin_lock(q->lock_ptr);
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++
++ /*
++ * Check if someone else fixed it for us:
++ */
++ if (pi_state->owner != oldowner)
++ return argowner == current;
++
++ /* Retry if err was -EAGAIN or the fault in succeeded */
++ if (!err)
++ goto retry;
++
++ /*
++ * fault_in_user_writeable() failed so user state is immutable. At
++ * best we can make the kernel state consistent but user state will
++ * be most likely hosed and any subsequent unlock operation will be
++ * rejected due to PI futex rule [10].
++ *
++ * Ensure that the rtmutex owner is also the pi_state owner despite
++ * the user space value claiming something different. There is no
++ * point in unlocking the rtmutex if current is the owner as it
++ * would need to wait until the next waiter has taken the rtmutex
++ * to guarantee consistent state. Keep it simple. Userspace asked
++ * for this wreckaged state.
++ *
++ * The rtmutex has an owner - either current or some other
++ * task. See the EAGAIN loop above.
++ */
++ pi_state_update_owner(pi_state, rt_mutex_owner(&pi_state->pi_mutex));
++
++ return err;
++}
++
++static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
++ struct task_struct *argowner)
++{
++ struct futex_pi_state *pi_state = q->pi_state;
++ int ret;
++
++ lockdep_assert_held(q->lock_ptr);
++
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++ ret = __fixup_pi_state_owner(uaddr, q, argowner);
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ return ret;
++}
++
++/**
++ * fixup_pi_owner() - Post lock pi_state and corner case management
++ * @uaddr: user address of the futex
++ * @q: futex_q (contains pi_state and access to the rt_mutex)
++ * @locked: if the attempt to take the rt_mutex succeeded (1) or not (0)
++ *
++ * After attempting to lock an rt_mutex, this function is called to cleanup
++ * the pi_state owner as well as handle race conditions that may allow us to
++ * acquire the lock. Must be called with the hb lock held.
++ *
++ * Return:
++ * - 1 - success, lock taken;
++ * - 0 - success, lock not taken;
++ * - <0 - on error (-EFAULT)
++ */
++int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked)
++{
++ if (locked) {
++ /*
++ * Got the lock. We might not be the anticipated owner if we
++ * did a lock-steal - fix up the PI-state in that case:
++ *
++ * Speculative pi_state->owner read (we don't hold wait_lock);
++ * since we own the lock pi_state->owner == current is the
++ * stable state, anything else needs more attention.
++ */
++ if (q->pi_state->owner != current)
++ return fixup_pi_state_owner(uaddr, q, current);
++ return 1;
++ }
++
++ /*
++ * If we didn't get the lock; check if anybody stole it from us. In
++ * that case, we need to fix up the uval to point to them instead of
++ * us, otherwise bad things happen. [10]
++ *
++ * Another speculative read; pi_state->owner == current is unstable
++ * but needs our attention.
++ */
++ if (q->pi_state->owner == current)
++ return fixup_pi_state_owner(uaddr, q, NULL);
++
++ /*
++ * Paranoia check. If we did not take the lock, then we should not be
++ * the owner of the rt_mutex. Warn and establish consistent state.
++ */
++ if (WARN_ON_ONCE(rt_mutex_owner(&q->pi_state->pi_mutex) == current))
++ return fixup_pi_state_owner(uaddr, q, current);
++
++ return 0;
++}
++
++/*
++ * Userspace tried a 0 -> TID atomic transition of the futex value
++ * and failed. The kernel side here does the whole locking operation:
++ * if there are waiters then it will block as a consequence of relying
++ * on rt-mutexes, it does PI, etc. (Due to races the kernel might see
++ * a 0 value of the futex too.).
++ *
++ * Also serves as futex trylock_pi()'ing, and due semantics.
++ */
++int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock)
++{
++ struct hrtimer_sleeper timeout, *to;
++ struct task_struct *exiting = NULL;
++ struct rt_mutex_waiter rt_waiter;
++ struct futex_hash_bucket *hb;
++ struct futex_q q = futex_q_init;
++ int res, ret;
++
++ if (!IS_ENABLED(CONFIG_FUTEX_PI))
++ return -ENOSYS;
++
++ if (refill_pi_state_cache())
++ return -ENOMEM;
++
++ to = futex_setup_timer(time, &timeout, flags, 0);
++
++retry:
++ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key, FUTEX_WRITE);
++ if (unlikely(ret != 0))
++ goto out;
++
++retry_private:
++ hb = futex_q_lock(&q);
++
++ ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current,
++ &exiting, 0);
++ if (unlikely(ret)) {
++ /*
++ * Atomic work succeeded and we got the lock,
++ * or failed. Either way, we do _not_ block.
++ */
++ switch (ret) {
++ case 1:
++ /* We got the lock. */
++ ret = 0;
++ goto out_unlock_put_key;
++ case -EFAULT:
++ goto uaddr_faulted;
++ case -EBUSY:
++ case -EAGAIN:
++ /*
++ * Two reasons for this:
++ * - EBUSY: Task is exiting and we just wait for the
++ * exit to complete.
++ * - EAGAIN: The user space value changed.
++ */
++ futex_q_unlock(hb);
++ /*
++ * Handle the case where the owner is in the middle of
++ * exiting. Wait for the exit to complete otherwise
++ * this task might loop forever, aka. live lock.
++ */
++ wait_for_owner_exiting(ret, exiting);
++ cond_resched();
++ goto retry;
++ default:
++ goto out_unlock_put_key;
++ }
++ }
++
++ WARN_ON(!q.pi_state);
++
++ /*
++ * Only actually queue now that the atomic ops are done:
++ */
++ __futex_queue(&q, hb);
++
++ if (trylock) {
++ ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex);
++ /* Fixup the trylock return value: */
++ ret = ret ? 0 : -EWOULDBLOCK;
++ goto no_block;
++ }
++
++ rt_mutex_init_waiter(&rt_waiter);
++
++ /*
++ * On PREEMPT_RT_FULL, when hb->lock becomes an rt_mutex, we must not
++ * hold it while doing rt_mutex_start_proxy(), because then it will
++ * include hb->lock in the blocking chain, even through we'll not in
++ * fact hold it while blocking. This will lead it to report -EDEADLK
++ * and BUG when futex_unlock_pi() interleaves with this.
++ *
++ * Therefore acquire wait_lock while holding hb->lock, but drop the
++ * latter before calling __rt_mutex_start_proxy_lock(). This
++ * interleaves with futex_unlock_pi() -- which does a similar lock
++ * handoff -- such that the latter can observe the futex_q::pi_state
++ * before __rt_mutex_start_proxy_lock() is done.
++ */
++ raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
++ spin_unlock(q.lock_ptr);
++ /*
++ * __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
++ * such that futex_unlock_pi() is guaranteed to observe the waiter when
++ * it sees the futex_q::pi_state.
++ */
++ ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
++ raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
++
++ if (ret) {
++ if (ret == 1)
++ ret = 0;
++ goto cleanup;
++ }
++
++ if (unlikely(to))
++ hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS);
++
++ ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
++
++cleanup:
++ spin_lock(q.lock_ptr);
++ /*
++ * If we failed to acquire the lock (deadlock/signal/timeout), we must
++ * first acquire the hb->lock before removing the lock from the
++ * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
++ * lists consistent.
++ *
++ * In particular; it is important that futex_unlock_pi() can not
++ * observe this inconsistency.
++ */
++ if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter))
++ ret = 0;
++
++no_block:
++ /*
++ * Fixup the pi_state owner and possibly acquire the lock if we
++ * haven't already.
++ */
++ res = fixup_pi_owner(uaddr, &q, !ret);
++ /*
++ * If fixup_pi_owner() returned an error, propagate that. If it acquired
++ * the lock, clear our -ETIMEDOUT or -EINTR.
++ */
++ if (res)
++ ret = (res < 0) ? res : 0;
++
++ futex_unqueue_pi(&q);
++ spin_unlock(q.lock_ptr);
++ goto out;
++
++out_unlock_put_key:
++ futex_q_unlock(hb);
++
++out:
++ if (to) {
++ hrtimer_cancel(&to->timer);
++ destroy_hrtimer_on_stack(&to->timer);
++ }
++ return ret != -EINTR ? ret : -ERESTARTNOINTR;
++
++uaddr_faulted:
++ futex_q_unlock(hb);
++
++ ret = fault_in_user_writeable(uaddr);
++ if (ret)
++ goto out;
++
++ if (!(flags & FLAGS_SHARED))
++ goto retry_private;
++
++ goto retry;
++}
++
++/*
++ * Userspace attempted a TID -> 0 atomic transition, and failed.
++ * This is the in-kernel slowpath: we look up the PI state (if any),
++ * and do the rt-mutex unlock.
++ */
++int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
++{
++ u32 curval, uval, vpid = task_pid_vnr(current);
++ union futex_key key = FUTEX_KEY_INIT;
++ struct futex_hash_bucket *hb;
++ struct futex_q *top_waiter;
++ int ret;
++
++ if (!IS_ENABLED(CONFIG_FUTEX_PI))
++ return -ENOSYS;
++
++retry:
++ if (get_user(uval, uaddr))
++ return -EFAULT;
++ /*
++ * We release only a lock we actually own:
++ */
++ if ((uval & FUTEX_TID_MASK) != vpid)
++ return -EPERM;
++
++ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, FUTEX_WRITE);
++ if (ret)
++ return ret;
++
++ hb = futex_hash(&key);
++ spin_lock(&hb->lock);
++
++ /*
++ * Check waiters first. We do not trust user space values at
++ * all and we at least want to know if user space fiddled
++ * with the futex value instead of blindly unlocking.
++ */
++ top_waiter = futex_top_waiter(hb, &key);
++ if (top_waiter) {
++ struct futex_pi_state *pi_state = top_waiter->pi_state;
++
++ ret = -EINVAL;
++ if (!pi_state)
++ goto out_unlock;
++
++ /*
++ * If current does not own the pi_state then the futex is
++ * inconsistent and user space fiddled with the futex value.
++ */
++ if (pi_state->owner != current)
++ goto out_unlock;
++
++ get_pi_state(pi_state);
++ /*
++ * By taking wait_lock while still holding hb->lock, we ensure
++ * there is no point where we hold neither; and therefore
++ * wake_futex_p() must observe a state consistent with what we
++ * observed.
++ *
++ * In particular; this forces __rt_mutex_start_proxy() to
++ * complete such that we're guaranteed to observe the
++ * rt_waiter. Also see the WARN in wake_futex_pi().
++ */
++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++ spin_unlock(&hb->lock);
++
++ /* drops pi_state->pi_mutex.wait_lock */
++ ret = wake_futex_pi(uaddr, uval, pi_state);
++
++ put_pi_state(pi_state);
++
++ /*
++ * Success, we're done! No tricky corner cases.
++ */
++ if (!ret)
++ return ret;
++ /*
++ * The atomic access to the futex value generated a
++ * pagefault, so retry the user-access and the wakeup:
++ */
++ if (ret == -EFAULT)
++ goto pi_faulted;
++ /*
++ * A unconditional UNLOCK_PI op raced against a waiter
++ * setting the FUTEX_WAITERS bit. Try again.
++ */
++ if (ret == -EAGAIN)
++ goto pi_retry;
++ /*
++ * wake_futex_pi has detected invalid state. Tell user
++ * space.
++ */
++ return ret;
++ }
++
++ /*
++ * We have no kernel internal state, i.e. no waiters in the
++ * kernel. Waiters which are about to queue themselves are stuck
++ * on hb->lock. So we can safely ignore them. We do neither
++ * preserve the WAITERS bit not the OWNER_DIED one. We are the
++ * owner.
++ */
++ if ((ret = futex_cmpxchg_value_locked(&curval, uaddr, uval, 0))) {
++ spin_unlock(&hb->lock);
++ switch (ret) {
++ case -EFAULT:
++ goto pi_faulted;
++
++ case -EAGAIN:
++ goto pi_retry;
++
++ default:
++ WARN_ON_ONCE(1);
++ return ret;
++ }
++ }
++
++ /*
++ * If uval has changed, let user space handle it.
++ */
++ ret = (curval == uval) ? 0 : -EAGAIN;
++
++out_unlock:
++ spin_unlock(&hb->lock);
++ return ret;
++
++pi_retry:
++ cond_resched();
++ goto retry;
++
++pi_faulted:
++
++ ret = fault_in_user_writeable(uaddr);
++ if (!ret)
++ goto retry;
++
++ return ret;
++}
++
+diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c
+new file mode 100644
+index 000000000..cba8b1a6a
+--- /dev/null
++++ b/kernel/futex/requeue.c
+@@ -0,0 +1,897 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#include <linux/sched/signal.h>
++
++#include "futex.h"
++#include "../locking/rtmutex_common.h"
++
++/*
++ * On PREEMPT_RT, the hash bucket lock is a 'sleeping' spinlock with an
++ * underlying rtmutex. The task which is about to be requeued could have
++ * just woken up (timeout, signal). After the wake up the task has to
++ * acquire hash bucket lock, which is held by the requeue code. As a task
++ * can only be blocked on _ONE_ rtmutex at a time, the proxy lock blocking
++ * and the hash bucket lock blocking would collide and corrupt state.
++ *
++ * On !PREEMPT_RT this is not a problem and everything could be serialized
++ * on hash bucket lock, but aside of having the benefit of common code,
++ * this allows to avoid doing the requeue when the task is already on the
++ * way out and taking the hash bucket lock of the original uaddr1 when the
++ * requeue has been completed.
++ *
++ * The following state transitions are valid:
++ *
++ * On the waiter side:
++ * Q_REQUEUE_PI_NONE -> Q_REQUEUE_PI_IGNORE
++ * Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_WAIT
++ *
++ * On the requeue side:
++ * Q_REQUEUE_PI_NONE -> Q_REQUEUE_PI_INPROGRESS
++ * Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_DONE/LOCKED
++ * Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_NONE (requeue failed)
++ * Q_REQUEUE_PI_WAIT -> Q_REQUEUE_PI_DONE/LOCKED
++ * Q_REQUEUE_PI_WAIT -> Q_REQUEUE_PI_IGNORE (requeue failed)
++ *
++ * The requeue side ignores a waiter with state Q_REQUEUE_PI_IGNORE as this
++ * signals that the waiter is already on the way out. It also means that
++ * the waiter is still on the 'wait' futex, i.e. uaddr1.
++ *
++ * The waiter side signals early wakeup to the requeue side either through
++ * setting state to Q_REQUEUE_PI_IGNORE or to Q_REQUEUE_PI_WAIT depending
++ * on the current state. In case of Q_REQUEUE_PI_IGNORE it can immediately
++ * proceed to take the hash bucket lock of uaddr1. If it set state to WAIT,
++ * which means the wakeup is interleaving with a requeue in progress it has
++ * to wait for the requeue side to change the state. Either to DONE/LOCKED
++ * or to IGNORE. DONE/LOCKED means the waiter q is now on the uaddr2 futex
++ * and either blocked (DONE) or has acquired it (LOCKED). IGNORE is set by
++ * the requeue side when the requeue attempt failed via deadlock detection
++ * and therefore the waiter q is still on the uaddr1 futex.
++ */
++enum {
++ Q_REQUEUE_PI_NONE = 0,
++ Q_REQUEUE_PI_IGNORE,
++ Q_REQUEUE_PI_IN_PROGRESS,
++ Q_REQUEUE_PI_WAIT,
++ Q_REQUEUE_PI_DONE,
++ Q_REQUEUE_PI_LOCKED,
++};
++
++const struct futex_q futex_q_init = {
++ /* list gets initialized in futex_queue()*/
++ .key = FUTEX_KEY_INIT,
++ .bitset = FUTEX_BITSET_MATCH_ANY,
++ .requeue_state = ATOMIC_INIT(Q_REQUEUE_PI_NONE),
++};
++
++/**
++ * requeue_futex() - Requeue a futex_q from one hb to another
++ * @q: the futex_q to requeue
++ * @hb1: the source hash_bucket
++ * @hb2: the target hash_bucket
++ * @key2: the new key for the requeued futex_q
++ */
++static inline
++void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
++ struct futex_hash_bucket *hb2, union futex_key *key2)
++{
++
++ /*
++ * If key1 and key2 hash to the same bucket, no need to
++ * requeue.
++ */
++ if (likely(&hb1->chain != &hb2->chain)) {
++ plist_del(&q->list, &hb1->chain);
++ futex_hb_waiters_dec(hb1);
++ futex_hb_waiters_inc(hb2);
++ plist_add(&q->list, &hb2->chain);
++ q->lock_ptr = &hb2->lock;
++ }
++ q->key = *key2;
++}
++
++static inline bool futex_requeue_pi_prepare(struct futex_q *q,
++ struct futex_pi_state *pi_state)
++{
++ int old, new;
++
++ /*
++ * Set state to Q_REQUEUE_PI_IN_PROGRESS unless an early wakeup has
++ * already set Q_REQUEUE_PI_IGNORE to signal that requeue should
++ * ignore the waiter.
++ */
++ old = atomic_read_acquire(&q->requeue_state);
++ do {
++ if (old == Q_REQUEUE_PI_IGNORE)
++ return false;
++
++ /*
++ * futex_proxy_trylock_atomic() might have set it to
++ * IN_PROGRESS and a interleaved early wake to WAIT.
++ *
++ * It was considered to have an extra state for that
++ * trylock, but that would just add more conditionals
++ * all over the place for a dubious value.
++ */
++ if (old != Q_REQUEUE_PI_NONE)
++ break;
++
++ new = Q_REQUEUE_PI_IN_PROGRESS;
++ } while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
++
++ q->pi_state = pi_state;
++ return true;
++}
++
++static inline void futex_requeue_pi_complete(struct futex_q *q, int locked)
++{
++ int old, new;
++
++ old = atomic_read_acquire(&q->requeue_state);
++ do {
++ if (old == Q_REQUEUE_PI_IGNORE)
++ return;
++
++ if (locked >= 0) {
++ /* Requeue succeeded. Set DONE or LOCKED */
++ WARN_ON_ONCE(old != Q_REQUEUE_PI_IN_PROGRESS &&
++ old != Q_REQUEUE_PI_WAIT);
++ new = Q_REQUEUE_PI_DONE + locked;
++ } else if (old == Q_REQUEUE_PI_IN_PROGRESS) {
++ /* Deadlock, no early wakeup interleave */
++ new = Q_REQUEUE_PI_NONE;
++ } else {
++ /* Deadlock, early wakeup interleave. */
++ WARN_ON_ONCE(old != Q_REQUEUE_PI_WAIT);
++ new = Q_REQUEUE_PI_IGNORE;
++ }
++ } while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
++
++#ifdef CONFIG_PREEMPT_RT
++ /* If the waiter interleaved with the requeue let it know */
++ if (unlikely(old == Q_REQUEUE_PI_WAIT))
++ rcuwait_wake_up(&q->requeue_wait);
++#endif
++}
++
++static inline int futex_requeue_pi_wakeup_sync(struct futex_q *q)
++{
++ int old, new;
++
++ old = atomic_read_acquire(&q->requeue_state);
++ do {
++ /* Is requeue done already? */
++ if (old >= Q_REQUEUE_PI_DONE)
++ return old;
++
++ /*
++ * If not done, then tell the requeue code to either ignore
++ * the waiter or to wake it up once the requeue is done.
++ */
++ new = Q_REQUEUE_PI_WAIT;
++ if (old == Q_REQUEUE_PI_NONE)
++ new = Q_REQUEUE_PI_IGNORE;
++ } while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
++
++ /* If the requeue was in progress, wait for it to complete */
++ if (old == Q_REQUEUE_PI_IN_PROGRESS) {
++#ifdef CONFIG_PREEMPT_RT
++ rcuwait_wait_event(&q->requeue_wait,
++ atomic_read(&q->requeue_state) != Q_REQUEUE_PI_WAIT,
++ TASK_UNINTERRUPTIBLE);
++#else
++ (void)atomic_cond_read_relaxed(&q->requeue_state, VAL != Q_REQUEUE_PI_WAIT);
++#endif
++ }
++
++ /*
++ * Requeue is now either prohibited or complete. Reread state
++ * because during the wait above it might have changed. Nothing
++ * will modify q->requeue_state after this point.
++ */
++ return atomic_read(&q->requeue_state);
++}
++
++/**
++ * requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
++ * @q: the futex_q
++ * @key: the key of the requeue target futex
++ * @hb: the hash_bucket of the requeue target futex
++ *
++ * During futex_requeue, with requeue_pi=1, it is possible to acquire the
++ * target futex if it is uncontended or via a lock steal.
++ *
++ * 1) Set @q::key to the requeue target futex key so the waiter can detect
++ * the wakeup on the right futex.
++ *
++ * 2) Dequeue @q from the hash bucket.
++ *
++ * 3) Set @q::rt_waiter to NULL so the woken up task can detect atomic lock
++ * acquisition.
++ *
++ * 4) Set the q->lock_ptr to the requeue target hb->lock for the case that
++ * the waiter has to fixup the pi state.
++ *
++ * 5) Complete the requeue state so the waiter can make progress. After
++ * this point the waiter task can return from the syscall immediately in
++ * case that the pi state does not have to be fixed up.
++ *
++ * 6) Wake the waiter task.
++ *
++ * Must be called with both q->lock_ptr and hb->lock held.
++ */
++static inline
++void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
++ struct futex_hash_bucket *hb)
++{
++ q->key = *key;
++
++ __futex_unqueue(q);
++
++ WARN_ON(!q->rt_waiter);
++ q->rt_waiter = NULL;
++
++ q->lock_ptr = &hb->lock;
++
++ /* Signal locked state to the waiter */
++ futex_requeue_pi_complete(q, 1);
++ wake_up_state(q->task, TASK_NORMAL);
++}
++
++/**
++ * futex_proxy_trylock_atomic() - Attempt an atomic lock for the top waiter
++ * @pifutex: the user address of the to futex
++ * @hb1: the from futex hash bucket, must be locked by the caller
++ * @hb2: the to futex hash bucket, must be locked by the caller
++ * @key1: the from futex key
++ * @key2: the to futex key
++ * @ps: address to store the pi_state pointer
++ * @exiting: Pointer to store the task pointer of the owner task
++ * which is in the middle of exiting
++ * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0)
++ *
++ * Try and get the lock on behalf of the top waiter if we can do it atomically.
++ * Wake the top waiter if we succeed. If the caller specified set_waiters,
++ * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit.
++ * hb1 and hb2 must be held by the caller.
++ *
++ * @exiting is only set when the return value is -EBUSY. If so, this holds
++ * a refcount on the exiting task on return and the caller needs to drop it
++ * after waiting for the exit to complete.
++ *
++ * Return:
++ * - 0 - failed to acquire the lock atomically;
++ * - >0 - acquired the lock, return value is vpid of the top_waiter
++ * - <0 - error
++ */
++static int
++futex_proxy_trylock_atomic(u32 __user *pifutex, struct futex_hash_bucket *hb1,
++ struct futex_hash_bucket *hb2, union futex_key *key1,
++ union futex_key *key2, struct futex_pi_state **ps,
++ struct task_struct **exiting, int set_waiters)
++{
++ struct futex_q *top_waiter = NULL;
++ u32 curval;
++ int ret;
++
++ if (futex_get_value_locked(&curval, pifutex))
++ return -EFAULT;
++
++ if (unlikely(should_fail_futex(true)))
++ return -EFAULT;
++
++ /*
++ * Find the top_waiter and determine if there are additional waiters.
++ * If the caller intends to requeue more than 1 waiter to pifutex,
++ * force futex_lock_pi_atomic() to set the FUTEX_WAITERS bit now,
++ * as we have means to handle the possible fault. If not, don't set
++ * the bit unnecessarily as it will force the subsequent unlock to enter
++ * the kernel.
++ */
++ top_waiter = futex_top_waiter(hb1, key1);
++
++ /* There are no waiters, nothing for us to do. */
++ if (!top_waiter)
++ return 0;
++
++ /*
++ * Ensure that this is a waiter sitting in futex_wait_requeue_pi()
++ * and waiting on the 'waitqueue' futex which is always !PI.
++ */
++ if (!top_waiter->rt_waiter || top_waiter->pi_state)
++ return -EINVAL;
++
++ /* Ensure we requeue to the expected futex. */
++ if (!futex_match(top_waiter->requeue_pi_key, key2))
++ return -EINVAL;
++
++ /* Ensure that this does not race against an early wakeup */
++ if (!futex_requeue_pi_prepare(top_waiter, NULL))
++ return -EAGAIN;
++
++ /*
++ * Try to take the lock for top_waiter and set the FUTEX_WAITERS bit
++ * in the contended case or if @set_waiters is true.
++ *
++ * In the contended case PI state is attached to the lock owner. If
++ * the user space lock can be acquired then PI state is attached to
++ * the new owner (@top_waiter->task) when @set_waiters is true.
++ */
++ ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
++ exiting, set_waiters);
++ if (ret == 1) {
++ /*
++ * Lock was acquired in user space and PI state was
++ * attached to @top_waiter->task. That means state is fully
++ * consistent and the waiter can return to user space
++ * immediately after the wakeup.
++ */
++ requeue_pi_wake_futex(top_waiter, key2, hb2);
++ } else if (ret < 0) {
++ /* Rewind top_waiter::requeue_state */
++ futex_requeue_pi_complete(top_waiter, ret);
++ } else {
++ /*
++ * futex_lock_pi_atomic() did not acquire the user space
++ * futex, but managed to establish the proxy lock and pi
++ * state. top_waiter::requeue_state cannot be fixed up here
++ * because the waiter is not enqueued on the rtmutex
++ * yet. This is handled at the callsite depending on the
++ * result of rt_mutex_start_proxy_lock() which is
++ * guaranteed to be reached with this function returning 0.
++ */
++ }
++ return ret;
++}
++
++/**
++ * futex_requeue() - Requeue waiters from uaddr1 to uaddr2
++ * @uaddr1: source futex user address
++ * @flags: futex flags (FLAGS_SHARED, etc.)
++ * @uaddr2: target futex user address
++ * @nr_wake: number of waiters to wake (must be 1 for requeue_pi)
++ * @nr_requeue: number of waiters to requeue (0-INT_MAX)
++ * @cmpval: @uaddr1 expected value (or %NULL)
++ * @requeue_pi: if we are attempting to requeue from a non-pi futex to a
++ * pi futex (pi to pi requeue is not supported)
++ *
++ * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
++ * uaddr2 atomically on behalf of the top waiter.
++ *
++ * Return:
++ * - >=0 - on success, the number of tasks requeued or woken;
++ * - <0 - on error
++ */
++int futex_requeue(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
++ int nr_wake, int nr_requeue, u32 *cmpval, int requeue_pi)
++{
++ union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
++ int task_count = 0, ret;
++ struct futex_pi_state *pi_state = NULL;
++ struct futex_hash_bucket *hb1, *hb2;
++ struct futex_q *this, *next;
++ DEFINE_WAKE_Q(wake_q);
++
++ if (nr_wake < 0 || nr_requeue < 0)
++ return -EINVAL;
++
++ /*
++ * When PI not supported: return -ENOSYS if requeue_pi is true,
++ * consequently the compiler knows requeue_pi is always false past
++ * this point which will optimize away all the conditional code
++ * further down.
++ */
++ if (!IS_ENABLED(CONFIG_FUTEX_PI) && requeue_pi)
++ return -ENOSYS;
++
++ if (requeue_pi) {
++ /*
++ * Requeue PI only works on two distinct uaddrs. This
++ * check is only valid for private futexes. See below.
++ */
++ if (uaddr1 == uaddr2)
++ return -EINVAL;
++
++ /*
++ * futex_requeue() allows the caller to define the number
++ * of waiters to wake up via the @nr_wake argument. With
++ * REQUEUE_PI, waking up more than one waiter is creating
++ * more problems than it solves. Waking up a waiter makes
++ * only sense if the PI futex @uaddr2 is uncontended as
++ * this allows the requeue code to acquire the futex
++ * @uaddr2 before waking the waiter. The waiter can then
++ * return to user space without further action. A secondary
++ * wakeup would just make the futex_wait_requeue_pi()
++ * handling more complex, because that code would have to
++ * look up pi_state and do more or less all the handling
++ * which the requeue code has to do for the to be requeued
++ * waiters. So restrict the number of waiters to wake to
++ * one, and only wake it up when the PI futex is
++ * uncontended. Otherwise requeue it and let the unlock of
++ * the PI futex handle the wakeup.
++ *
++ * All REQUEUE_PI users, e.g. pthread_cond_signal() and
++ * pthread_cond_broadcast() must use nr_wake=1.
++ */
++ if (nr_wake != 1)
++ return -EINVAL;
++
++ /*
++ * requeue_pi requires a pi_state, try to allocate it now
++ * without any locks in case it fails.
++ */
++ if (refill_pi_state_cache())
++ return -ENOMEM;
++ }
++
++retry:
++ ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
++ if (unlikely(ret != 0))
++ return ret;
++ ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
++ requeue_pi ? FUTEX_WRITE : FUTEX_READ);
++ if (unlikely(ret != 0))
++ return ret;
++
++ /*
++ * The check above which compares uaddrs is not sufficient for
++ * shared futexes. We need to compare the keys:
++ */
++ if (requeue_pi && futex_match(&key1, &key2))
++ return -EINVAL;
++
++ hb1 = futex_hash(&key1);
++ hb2 = futex_hash(&key2);
++
++retry_private:
++ futex_hb_waiters_inc(hb2);
++ double_lock_hb(hb1, hb2);
++
++ if (likely(cmpval != NULL)) {
++ u32 curval;
++
++ ret = futex_get_value_locked(&curval, uaddr1);
++
++ if (unlikely(ret)) {
++ double_unlock_hb(hb1, hb2);
++ futex_hb_waiters_dec(hb2);
++
++ ret = get_user(curval, uaddr1);
++ if (ret)
++ return ret;
++
++ if (!(flags & FLAGS_SHARED))
++ goto retry_private;
++
++ goto retry;
++ }
++ if (curval != *cmpval) {
++ ret = -EAGAIN;
++ goto out_unlock;
++ }
++ }
++
++ if (requeue_pi) {
++ struct task_struct *exiting = NULL;
++
++ /*
++ * Attempt to acquire uaddr2 and wake the top waiter. If we
++ * intend to requeue waiters, force setting the FUTEX_WAITERS
++ * bit. We force this here where we are able to easily handle
++ * faults rather in the requeue loop below.
++ *
++ * Updates topwaiter::requeue_state if a top waiter exists.
++ */
++ ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1,
++ &key2, &pi_state,
++ &exiting, nr_requeue);
++
++ /*
++ * At this point the top_waiter has either taken uaddr2 or
++ * is waiting on it. In both cases pi_state has been
++ * established and an initial refcount on it. In case of an
++ * error there's nothing.
++ *
++ * The top waiter's requeue_state is up to date:
++ *
++ * - If the lock was acquired atomically (ret == 1), then
++ * the state is Q_REQUEUE_PI_LOCKED.
++ *
++ * The top waiter has been dequeued and woken up and can
++ * return to user space immediately. The kernel/user
++ * space state is consistent. In case that there must be
++ * more waiters requeued the WAITERS bit in the user
++ * space futex is set so the top waiter task has to go
++ * into the syscall slowpath to unlock the futex. This
++ * will block until this requeue operation has been
++ * completed and the hash bucket locks have been
++ * dropped.
++ *
++ * - If the trylock failed with an error (ret < 0) then
++ * the state is either Q_REQUEUE_PI_NONE, i.e. "nothing
++ * happened", or Q_REQUEUE_PI_IGNORE when there was an
++ * interleaved early wakeup.
++ *
++ * - If the trylock did not succeed (ret == 0) then the
++ * state is either Q_REQUEUE_PI_IN_PROGRESS or
++ * Q_REQUEUE_PI_WAIT if an early wakeup interleaved.
++ * This will be cleaned up in the loop below, which
++ * cannot fail because futex_proxy_trylock_atomic() did
++ * the same sanity checks for requeue_pi as the loop
++ * below does.
++ */
++ switch (ret) {
++ case 0:
++ /* We hold a reference on the pi state. */
++ break;
++
++ case 1:
++ /*
++ * futex_proxy_trylock_atomic() acquired the user space
++ * futex. Adjust task_count.
++ */
++ task_count++;
++ ret = 0;
++ break;
++
++ /*
++ * If the above failed, then pi_state is NULL and
++ * waiter::requeue_state is correct.
++ */
++ case -EFAULT:
++ double_unlock_hb(hb1, hb2);
++ futex_hb_waiters_dec(hb2);
++ ret = fault_in_user_writeable(uaddr2);
++ if (!ret)
++ goto retry;
++ return ret;
++ case -EBUSY:
++ case -EAGAIN:
++ /*
++ * Two reasons for this:
++ * - EBUSY: Owner is exiting and we just wait for the
++ * exit to complete.
++ * - EAGAIN: The user space value changed.
++ */
++ double_unlock_hb(hb1, hb2);
++ futex_hb_waiters_dec(hb2);
++ /*
++ * Handle the case where the owner is in the middle of
++ * exiting. Wait for the exit to complete otherwise
++ * this task might loop forever, aka. live lock.
++ */
++ wait_for_owner_exiting(ret, exiting);
++ cond_resched();
++ goto retry;
++ default:
++ goto out_unlock;
++ }
++ }
++
++ plist_for_each_entry_safe(this, next, &hb1->chain, list) {
++ if (task_count - nr_wake >= nr_requeue)
++ break;
++
++ if (!futex_match(&this->key, &key1))
++ continue;
++
++ /*
++ * FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI should always
++ * be paired with each other and no other futex ops.
++ *
++ * We should never be requeueing a futex_q with a pi_state,
++ * which is awaiting a futex_unlock_pi().
++ */
++ if ((requeue_pi && !this->rt_waiter) ||
++ (!requeue_pi && this->rt_waiter) ||
++ this->pi_state) {
++ ret = -EINVAL;
++ break;
++ }
++
++ /* Plain futexes just wake or requeue and are done */
++ if (!requeue_pi) {
++ if (++task_count <= nr_wake)
++ futex_wake_mark(&wake_q, this);
++ else
++ requeue_futex(this, hb1, hb2, &key2);
++ continue;
++ }
++
++ /* Ensure we requeue to the expected futex for requeue_pi. */
++ if (!futex_match(this->requeue_pi_key, &key2)) {
++ ret = -EINVAL;
++ break;
++ }
++
++ /*
++ * Requeue nr_requeue waiters and possibly one more in the case
++ * of requeue_pi if we couldn't acquire the lock atomically.
++ *
++ * Prepare the waiter to take the rt_mutex. Take a refcount
++ * on the pi_state and store the pointer in the futex_q
++ * object of the waiter.
++ */
++ get_pi_state(pi_state);
++
++ /* Don't requeue when the waiter is already on the way out. */
++ if (!futex_requeue_pi_prepare(this, pi_state)) {
++ /*
++ * Early woken waiter signaled that it is on the
++ * way out. Drop the pi_state reference and try the
++ * next waiter. @this->pi_state is still NULL.
++ */
++ put_pi_state(pi_state);
++ continue;
++ }
++
++ ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
++ this->rt_waiter,
++ this->task);
++
++ if (ret == 1) {
++ /*
++ * We got the lock. We do neither drop the refcount
++ * on pi_state nor clear this->pi_state because the
++ * waiter needs the pi_state for cleaning up the
++ * user space value. It will drop the refcount
++ * after doing so. this::requeue_state is updated
++ * in the wakeup as well.
++ */
++ requeue_pi_wake_futex(this, &key2, hb2);
++ task_count++;
++ } else if (!ret) {
++ /* Waiter is queued, move it to hb2 */
++ requeue_futex(this, hb1, hb2, &key2);
++ futex_requeue_pi_complete(this, 0);
++ task_count++;
++ } else {
++ /*
++ * rt_mutex_start_proxy_lock() detected a potential
++ * deadlock when we tried to queue that waiter.
++ * Drop the pi_state reference which we took above
++ * and remove the pointer to the state from the
++ * waiters futex_q object.
++ */
++ this->pi_state = NULL;
++ put_pi_state(pi_state);
++ futex_requeue_pi_complete(this, ret);
++ /*
++ * We stop queueing more waiters and let user space
++ * deal with the mess.
++ */
++ break;
++ }
++ }
++
++ /*
++ * We took an extra initial reference to the pi_state in
++ * futex_proxy_trylock_atomic(). We need to drop it here again.
++ */
++ put_pi_state(pi_state);
++
++out_unlock:
++ double_unlock_hb(hb1, hb2);
++ wake_up_q(&wake_q);
++ futex_hb_waiters_dec(hb2);
++ return ret ? ret : task_count;
++}
++
++/**
++ * handle_early_requeue_pi_wakeup() - Handle early wakeup on the initial futex
++ * @hb: the hash_bucket futex_q was original enqueued on
++ * @q: the futex_q woken while waiting to be requeued
++ * @timeout: the timeout associated with the wait (NULL if none)
++ *
++ * Determine the cause for the early wakeup.
++ *
++ * Return:
++ * -EWOULDBLOCK or -ETIMEDOUT or -ERESTARTNOINTR
++ */
++static inline
++int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
++ struct futex_q *q,
++ struct hrtimer_sleeper *timeout)
++{
++ int ret;
++
++ /*
++ * With the hb lock held, we avoid races while we process the wakeup.
++ * We only need to hold hb (and not hb2) to ensure atomicity as the
++ * wakeup code can't change q.key from uaddr to uaddr2 if we hold hb.
++ * It can't be requeued from uaddr2 to something else since we don't
++ * support a PI aware source futex for requeue.
++ */
++ WARN_ON_ONCE(&hb->lock != q->lock_ptr);
++
++ /*
++ * We were woken prior to requeue by a timeout or a signal.
++ * Unqueue the futex_q and determine which it was.
++ */
++ plist_del(&q->list, &hb->chain);
++ futex_hb_waiters_dec(hb);
++
++ /* Handle spurious wakeups gracefully */
++ ret = -EWOULDBLOCK;
++ if (timeout && !timeout->task)
++ ret = -ETIMEDOUT;
++ else if (signal_pending(current))
++ ret = -ERESTARTNOINTR;
++ return ret;
++}
++
++/**
++ * futex_wait_requeue_pi() - Wait on uaddr and take uaddr2
++ * @uaddr: the futex we initially wait on (non-pi)
++ * @flags: futex flags (FLAGS_SHARED, FLAGS_CLOCKRT, etc.), they must be
++ * the same type, no requeueing from private to shared, etc.
++ * @val: the expected value of uaddr
++ * @abs_time: absolute timeout
++ * @bitset: 32 bit wakeup bitset set by userspace, defaults to all
++ * @uaddr2: the pi futex we will take prior to returning to user-space
++ *
++ * The caller will wait on uaddr and will be requeued by futex_requeue() to
++ * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake
++ * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to
++ * userspace. This ensures the rt_mutex maintains an owner when it has waiters;
++ * without one, the pi logic would not know which task to boost/deboost, if
++ * there was a need to.
++ *
++ * We call schedule in futex_wait_queue() when we enqueue and return there
++ * via the following--
++ * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()
++ * 2) wakeup on uaddr2 after a requeue
++ * 3) signal
++ * 4) timeout
++ *
++ * If 3, cleanup and return -ERESTARTNOINTR.
++ *
++ * If 2, we may then block on trying to take the rt_mutex and return via:
++ * 5) successful lock
++ * 6) signal
++ * 7) timeout
++ * 8) other lock acquisition failure
++ *
++ * If 6, return -EWOULDBLOCK (restarting the syscall would do the same).
++ *
++ * If 4 or 7, we cleanup and return with -ETIMEDOUT.
++ *
++ * Return:
++ * - 0 - On success;
++ * - <0 - On error
++ */
++int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
++ u32 val, ktime_t *abs_time, u32 bitset,
++ u32 __user *uaddr2)
++{
++ struct hrtimer_sleeper timeout, *to;
++ struct rt_mutex_waiter rt_waiter;
++ struct futex_hash_bucket *hb;
++ union futex_key key2 = FUTEX_KEY_INIT;
++ struct futex_q q = futex_q_init;
++ struct rt_mutex_base *pi_mutex;
++ int res, ret;
++
++ if (!IS_ENABLED(CONFIG_FUTEX_PI))
++ return -ENOSYS;
++
++ if (uaddr == uaddr2)
++ return -EINVAL;
++
++ if (!bitset)
++ return -EINVAL;
++
++ to = futex_setup_timer(abs_time, &timeout, flags,
++ current->timer_slack_ns);
++
++ /*
++ * The waiter is allocated on our stack, manipulated by the requeue
++ * code while we sleep on uaddr.
++ */
++ rt_mutex_init_waiter(&rt_waiter);
++
++ ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
++ if (unlikely(ret != 0))
++ goto out;
++
++ q.bitset = bitset;
++ q.rt_waiter = &rt_waiter;
++ q.requeue_pi_key = &key2;
++
++ /*
++ * Prepare to wait on uaddr. On success, it holds hb->lock and q
++ * is initialized.
++ */
++ ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
++ if (ret)
++ goto out;
++
++ /*
++ * The check above which compares uaddrs is not sufficient for
++ * shared futexes. We need to compare the keys:
++ */
++ if (futex_match(&q.key, &key2)) {
++ futex_q_unlock(hb);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* Queue the futex_q, drop the hb lock, wait for wakeup. */
++ futex_wait_queue(hb, &q, to);
++
++ switch (futex_requeue_pi_wakeup_sync(&q)) {
++ case Q_REQUEUE_PI_IGNORE:
++ /* The waiter is still on uaddr1 */
++ spin_lock(&hb->lock);
++ ret = handle_early_requeue_pi_wakeup(hb, &q, to);
++ spin_unlock(&hb->lock);
++ break;
++
++ case Q_REQUEUE_PI_LOCKED:
++ /* The requeue acquired the lock */
++ if (q.pi_state && (q.pi_state->owner != current)) {
++ spin_lock(q.lock_ptr);
++ ret = fixup_pi_owner(uaddr2, &q, true);
++ /*
++ * Drop the reference to the pi state which the
++ * requeue_pi() code acquired for us.
++ */
++ put_pi_state(q.pi_state);
++ spin_unlock(q.lock_ptr);
++ /*
++ * Adjust the return value. It's either -EFAULT or
++ * success (1) but the caller expects 0 for success.
++ */
++ ret = ret < 0 ? ret : 0;
++ }
++ break;
++
++ case Q_REQUEUE_PI_DONE:
++ /* Requeue completed. Current is 'pi_blocked_on' the rtmutex */
++ pi_mutex = &q.pi_state->pi_mutex;
++ ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
++
++ /* Current is not longer pi_blocked_on */
++ spin_lock(q.lock_ptr);
++ if (ret && !rt_mutex_cleanup_proxy_lock(pi_mutex, &rt_waiter))
++ ret = 0;
++
++ debug_rt_mutex_free_waiter(&rt_waiter);
++ /*
++ * Fixup the pi_state owner and possibly acquire the lock if we
++ * haven't already.
++ */
++ res = fixup_pi_owner(uaddr2, &q, !ret);
++ /*
++ * If fixup_pi_owner() returned an error, propagate that. If it
++ * acquired the lock, clear -ETIMEDOUT or -EINTR.
++ */
++ if (res)
++ ret = (res < 0) ? res : 0;
++
++ futex_unqueue_pi(&q);
++ spin_unlock(q.lock_ptr);
++
++ if (ret == -EINTR) {
++ /*
++ * We've already been requeued, but cannot restart
++ * by calling futex_lock_pi() directly. We could
++ * restart this syscall, but it would detect that
++ * the user space "val" changed and return
++ * -EWOULDBLOCK. Save the overhead of the restart
++ * and return -EWOULDBLOCK directly.
++ */
++ ret = -EWOULDBLOCK;
++ }
++ break;
++ default:
++ BUG();
++ }
++
++out:
++ if (to) {
++ hrtimer_cancel(&to->timer);
++ destroy_hrtimer_on_stack(&to->timer);
++ }
++ return ret;
++}
++
+diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
+new file mode 100644
+index 000000000..368e9c17f
+--- /dev/null
++++ b/kernel/futex/syscalls.c
+@@ -0,0 +1,396 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#include <linux/compat.h>
++#include <linux/syscalls.h>
++#include <linux/time_namespace.h>
++
++#include "futex.h"
++
++/*
++ * Support for robust futexes: the kernel cleans up held futexes at
++ * thread exit time.
++ *
++ * Implementation: user-space maintains a per-thread list of locks it
++ * is holding. Upon do_exit(), the kernel carefully walks this list,
++ * and marks all locks that are owned by this thread with the
++ * FUTEX_OWNER_DIED bit, and wakes up a waiter (if any). The list is
++ * always manipulated with the lock held, so the list is private and
++ * per-thread. Userspace also maintains a per-thread 'list_op_pending'
++ * field, to allow the kernel to clean up if the thread dies after
++ * acquiring the lock, but just before it could have added itself to
++ * the list. There can only be one such pending lock.
++ */
++
++/**
++ * sys_set_robust_list() - Set the robust-futex list head of a task
++ * @head: pointer to the list-head
++ * @len: length of the list-head, as userspace expects
++ */
++SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head,
++ size_t, len)
++{
++ if (!futex_cmpxchg_enabled)
++ return -ENOSYS;
++ /*
++ * The kernel knows only one size for now:
++ */
++ if (unlikely(len != sizeof(*head)))
++ return -EINVAL;
++
++ current->robust_list = head;
++
++ return 0;
++}
++
++/**
++ * sys_get_robust_list() - Get the robust-futex list head of a task
++ * @pid: pid of the process [zero for current task]
++ * @head_ptr: pointer to a list-head pointer, the kernel fills it in
++ * @len_ptr: pointer to a length field, the kernel fills in the header size
++ */
++SYSCALL_DEFINE3(get_robust_list, int, pid,
++ struct robust_list_head __user * __user *, head_ptr,
++ size_t __user *, len_ptr)
++{
++ struct robust_list_head __user *head;
++ unsigned long ret;
++ struct task_struct *p;
++
++ if (!futex_cmpxchg_enabled)
++ return -ENOSYS;
++
++ rcu_read_lock();
++
++ ret = -ESRCH;
++ if (!pid)
++ p = current;
++ else {
++ p = find_task_by_vpid(pid);
++ if (!p)
++ goto err_unlock;
++ }
++
++ ret = -EPERM;
++ if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
++ goto err_unlock;
++
++ head = p->robust_list;
++ rcu_read_unlock();
++
++ if (put_user(sizeof(*head), len_ptr))
++ return -EFAULT;
++ return put_user(head, head_ptr);
++
++err_unlock:
++ rcu_read_unlock();
++
++ return ret;
++}
++
++long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
++ u32 __user *uaddr2, u32 val2, u32 val3)
++{
++ int cmd = op & FUTEX_CMD_MASK;
++ unsigned int flags = 0;
++
++ if (!(op & FUTEX_PRIVATE_FLAG))
++ flags |= FLAGS_SHARED;
++
++ if (op & FUTEX_CLOCK_REALTIME) {
++ flags |= FLAGS_CLOCKRT;
++ if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI &&
++ cmd != FUTEX_LOCK_PI2)
++ return -ENOSYS;
++ }
++
++ switch (cmd) {
++ case FUTEX_LOCK_PI:
++ case FUTEX_LOCK_PI2:
++ case FUTEX_UNLOCK_PI:
++ case FUTEX_TRYLOCK_PI:
++ case FUTEX_WAIT_REQUEUE_PI:
++ case FUTEX_CMP_REQUEUE_PI:
++ if (!futex_cmpxchg_enabled)
++ return -ENOSYS;
++ }
++
++ switch (cmd) {
++ case FUTEX_WAIT:
++ val3 = FUTEX_BITSET_MATCH_ANY;
++ fallthrough;
++ case FUTEX_WAIT_BITSET:
++ return futex_wait(uaddr, flags, val, timeout, val3);
++ case FUTEX_WAKE:
++ val3 = FUTEX_BITSET_MATCH_ANY;
++ fallthrough;
++ case FUTEX_WAKE_BITSET:
++ return futex_wake(uaddr, flags, val, val3);
++ case FUTEX_REQUEUE:
++ return futex_requeue(uaddr, flags, uaddr2, val, val2, NULL, 0);
++ case FUTEX_CMP_REQUEUE:
++ return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 0);
++ case FUTEX_WAKE_OP:
++ return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3);
++ case FUTEX_LOCK_PI:
++ flags |= FLAGS_CLOCKRT;
++ fallthrough;
++ case FUTEX_LOCK_PI2:
++ return futex_lock_pi(uaddr, flags, timeout, 0);
++ case FUTEX_UNLOCK_PI:
++ return futex_unlock_pi(uaddr, flags);
++ case FUTEX_TRYLOCK_PI:
++ return futex_lock_pi(uaddr, flags, NULL, 1);
++ case FUTEX_WAIT_REQUEUE_PI:
++ val3 = FUTEX_BITSET_MATCH_ANY;
++ return futex_wait_requeue_pi(uaddr, flags, val, timeout, val3,
++ uaddr2);
++ case FUTEX_CMP_REQUEUE_PI:
++ return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1);
++ }
++ return -ENOSYS;
++}
++
++static __always_inline bool futex_cmd_has_timeout(u32 cmd)
++{
++ switch (cmd) {
++ case FUTEX_WAIT:
++ case FUTEX_LOCK_PI:
++ case FUTEX_LOCK_PI2:
++ case FUTEX_WAIT_BITSET:
++ case FUTEX_WAIT_REQUEUE_PI:
++ return true;
++ }
++ return false;
++}
++
++static __always_inline int
++futex_init_timeout(u32 cmd, u32 op, struct timespec64 *ts, ktime_t *t)
++{
++ if (!timespec64_valid(ts))
++ return -EINVAL;
++
++ *t = timespec64_to_ktime(*ts);
++ if (cmd == FUTEX_WAIT)
++ *t = ktime_add_safe(ktime_get(), *t);
++ else if (cmd != FUTEX_LOCK_PI && !(op & FUTEX_CLOCK_REALTIME))
++ *t = timens_ktime_to_host(CLOCK_MONOTONIC, *t);
++ return 0;
++}
++
++SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
++ const struct __kernel_timespec __user *, utime,
++ u32 __user *, uaddr2, u32, val3)
++{
++ int ret, cmd = op & FUTEX_CMD_MASK;
++ ktime_t t, *tp = NULL;
++ struct timespec64 ts;
++
++ if (utime && futex_cmd_has_timeout(cmd)) {
++ if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG))))
++ return -EFAULT;
++ if (get_timespec64(&ts, utime))
++ return -EFAULT;
++ ret = futex_init_timeout(cmd, op, &ts, &t);
++ if (ret)
++ return ret;
++ tp = &t;
++ }
++
++ return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3);
++}
++
++/* Mask of available flags for each futex in futex_waitv list */
++#define FUTEXV_WAITER_MASK (FUTEX_32 | FUTEX_PRIVATE_FLAG)
++
++/**
++ * futex_parse_waitv - Parse a waitv array from userspace
++ * @futexv: Kernel side list of waiters to be filled
++ * @uwaitv: Userspace list to be parsed
++ * @nr_futexes: Length of futexv
++ *
++ * Return: Error code on failure, 0 on success
++ */
++static int futex_parse_waitv(struct futex_vector *futexv,
++ struct futex_waitv __user *uwaitv,
++ unsigned int nr_futexes)
++{
++ struct futex_waitv aux;
++ unsigned int i;
++
++ for (i = 0; i < nr_futexes; i++) {
++ if (copy_from_user(&aux, &uwaitv[i], sizeof(aux)))
++ return -EFAULT;
++
++ if ((aux.flags & ~FUTEXV_WAITER_MASK) || aux.__reserved)
++ return -EINVAL;
++
++ if (!(aux.flags & FUTEX_32))
++ return -EINVAL;
++
++ futexv[i].w.flags = aux.flags;
++ futexv[i].w.val = aux.val;
++ futexv[i].w.uaddr = aux.uaddr;
++ futexv[i].q = futex_q_init;
++ }
++
++ return 0;
++}
++
++/**
++ * sys_futex_waitv - Wait on a list of futexes
++ * @waiters: List of futexes to wait on
++ * @nr_futexes: Length of futexv
++ * @flags: Flag for timeout (monotonic/realtime)
++ * @timeout: Optional absolute timeout.
++ * @clockid: Clock to be used for the timeout, realtime or monotonic.
++ *
++ * Given an array of `struct futex_waitv`, wait on each uaddr. The thread wakes
++ * if a futex_wake() is performed at any uaddr. The syscall returns immediately
++ * if any waiter has *uaddr != val. *timeout is an optional timeout value for the
++ * operation. Each waiter has individual flags. The `flags` argument for the
++ * syscall should be used solely for specifying the timeout as realtime, if
++ * needed. Flags for private futexes, sizes, etc. should be used on the
++ * individual flags of each waiter.
++ *
++ * Returns the array index of one of the awaken futexes. There's no given
++ * information of how many were awakened, or any particular attribute of it (if
++ * it's the first awakened, if it is of the smaller index...).
++ */
++
++SYSCALL_DEFINE5(futex_waitv, struct futex_waitv __user *, waiters,
++ unsigned int, nr_futexes, unsigned int, flags,
++ struct __kernel_timespec __user *, timeout, clockid_t, clockid)
++{
++ struct hrtimer_sleeper to;
++ struct futex_vector *futexv;
++ struct timespec64 ts;
++ ktime_t time;
++ int ret;
++
++ /* This syscall supports no flags for now */
++ if (flags)
++ return -EINVAL;
++
++ if (!nr_futexes || nr_futexes > FUTEX_WAITV_MAX || !waiters)
++ return -EINVAL;
++
++ if (timeout) {
++ int flag_clkid = 0, flag_init = 0;
++
++ if (clockid == CLOCK_REALTIME) {
++ flag_clkid = FLAGS_CLOCKRT;
++ flag_init = FUTEX_CLOCK_REALTIME;
++ }
++
++ if (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC)
++ return -EINVAL;
++
++ if (get_timespec64(&ts, timeout))
++ return -EFAULT;
++
++ /*
++ * Since there's no opcode for futex_waitv, use
++ * FUTEX_WAIT_BITSET that uses absolute timeout as well
++ */
++ ret = futex_init_timeout(FUTEX_WAIT_BITSET, flag_init, &ts, &time);
++ if (ret)
++ return ret;
++
++ futex_setup_timer(&time, &to, flag_clkid, 0);
++ }
++
++ futexv = kcalloc(nr_futexes, sizeof(*futexv), GFP_KERNEL);
++ if (!futexv)
++ return -ENOMEM;
++
++ ret = futex_parse_waitv(futexv, waiters, nr_futexes);
++ if (!ret)
++ ret = futex_wait_multiple(futexv, nr_futexes, timeout ? &to : NULL);
++
++ if (timeout) {
++ hrtimer_cancel(&to.timer);
++ destroy_hrtimer_on_stack(&to.timer);
++ }
++
++ kfree(futexv);
++ return ret;
++}
++
++#ifdef CONFIG_COMPAT
++COMPAT_SYSCALL_DEFINE2(set_robust_list,
++ struct compat_robust_list_head __user *, head,
++ compat_size_t, len)
++{
++ if (!futex_cmpxchg_enabled)
++ return -ENOSYS;
++
++ if (unlikely(len != sizeof(*head)))
++ return -EINVAL;
++
++ current->compat_robust_list = head;
++
++ return 0;
++}
++
++COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
++ compat_uptr_t __user *, head_ptr,
++ compat_size_t __user *, len_ptr)
++{
++ struct compat_robust_list_head __user *head;
++ unsigned long ret;
++ struct task_struct *p;
++
++ if (!futex_cmpxchg_enabled)
++ return -ENOSYS;
++
++ rcu_read_lock();
++
++ ret = -ESRCH;
++ if (!pid)
++ p = current;
++ else {
++ p = find_task_by_vpid(pid);
++ if (!p)
++ goto err_unlock;
++ }
++
++ ret = -EPERM;
++ if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
++ goto err_unlock;
++
++ head = p->compat_robust_list;
++ rcu_read_unlock();
++
++ if (put_user(sizeof(*head), len_ptr))
++ return -EFAULT;
++ return put_user(ptr_to_compat(head), head_ptr);
++
++err_unlock:
++ rcu_read_unlock();
++
++ return ret;
++}
++#endif /* CONFIG_COMPAT */
++
++#ifdef CONFIG_COMPAT_32BIT_TIME
++SYSCALL_DEFINE6(futex_time32, u32 __user *, uaddr, int, op, u32, val,
++ const struct old_timespec32 __user *, utime, u32 __user *, uaddr2,
++ u32, val3)
++{
++ int ret, cmd = op & FUTEX_CMD_MASK;
++ ktime_t t, *tp = NULL;
++ struct timespec64 ts;
++
++ if (utime && futex_cmd_has_timeout(cmd)) {
++ if (get_old_timespec32(&ts, utime))
++ return -EFAULT;
++ ret = futex_init_timeout(cmd, op, &ts, &t);
++ if (ret)
++ return ret;
++ tp = &t;
++ }
++
++ return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3);
++}
++#endif /* CONFIG_COMPAT_32BIT_TIME */
++
+diff --git a/kernel/futex/waitwake.c b/kernel/futex/waitwake.c
+new file mode 100644
+index 000000000..b45597aab
+--- /dev/null
++++ b/kernel/futex/waitwake.c
+@@ -0,0 +1,708 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#include <linux/sched/task.h>
++#include <linux/sched/signal.h>
++#include <linux/freezer.h>
++
++#include "futex.h"
++
++/*
++ * READ this before attempting to hack on futexes!
++ *
++ * Basic futex operation and ordering guarantees
++ * =============================================
++ *
++ * The waiter reads the futex value in user space and calls
++ * futex_wait(). This function computes the hash bucket and acquires
++ * the hash bucket lock. After that it reads the futex user space value
++ * again and verifies that the data has not changed. If it has not changed
++ * it enqueues itself into the hash bucket, releases the hash bucket lock
++ * and schedules.
++ *
++ * The waker side modifies the user space value of the futex and calls
++ * futex_wake(). This function computes the hash bucket and acquires the
++ * hash bucket lock. Then it looks for waiters on that futex in the hash
++ * bucket and wakes them.
++ *
++ * In futex wake up scenarios where no tasks are blocked on a futex, taking
++ * the hb spinlock can be avoided and simply return. In order for this
++ * optimization to work, ordering guarantees must exist so that the waiter
++ * being added to the list is acknowledged when the list is concurrently being
++ * checked by the waker, avoiding scenarios like the following:
++ *
++ * CPU 0 CPU 1
++ * val = *futex;
++ * sys_futex(WAIT, futex, val);
++ * futex_wait(futex, val);
++ * uval = *futex;
++ * *futex = newval;
++ * sys_futex(WAKE, futex);
++ * futex_wake(futex);
++ * if (queue_empty())
++ * return;
++ * if (uval == val)
++ * lock(hash_bucket(futex));
++ * queue();
++ * unlock(hash_bucket(futex));
++ * schedule();
++ *
++ * This would cause the waiter on CPU 0 to wait forever because it
++ * missed the transition of the user space value from val to newval
++ * and the waker did not find the waiter in the hash bucket queue.
++ *
++ * The correct serialization ensures that a waiter either observes
++ * the changed user space value before blocking or is woken by a
++ * concurrent waker:
++ *
++ * CPU 0 CPU 1
++ * val = *futex;
++ * sys_futex(WAIT, futex, val);
++ * futex_wait(futex, val);
++ *
++ * waiters++; (a)
++ * smp_mb(); (A) <-- paired with -.
++ * |
++ * lock(hash_bucket(futex)); |
++ * |
++ * uval = *futex; |
++ * | *futex = newval;
++ * | sys_futex(WAKE, futex);
++ * | futex_wake(futex);
++ * |
++ * `--------> smp_mb(); (B)
++ * if (uval == val)
++ * queue();
++ * unlock(hash_bucket(futex));
++ * schedule(); if (waiters)
++ * lock(hash_bucket(futex));
++ * else wake_waiters(futex);
++ * waiters--; (b) unlock(hash_bucket(futex));
++ *
++ * Where (A) orders the waiters increment and the futex value read through
++ * atomic operations (see futex_hb_waiters_inc) and where (B) orders the write
++ * to futex and the waiters read (see futex_hb_waiters_pending()).
++ *
++ * This yields the following case (where X:=waiters, Y:=futex):
++ *
++ * X = Y = 0
++ *
++ * w[X]=1 w[Y]=1
++ * MB MB
++ * r[Y]=y r[X]=x
++ *
++ * Which guarantees that x==0 && y==0 is impossible; which translates back into
++ * the guarantee that we cannot both miss the futex variable change and the
++ * enqueue.
++ *
++ * Note that a new waiter is accounted for in (a) even when it is possible that
++ * the wait call can return error, in which case we backtrack from it in (b).
++ * Refer to the comment in futex_q_lock().
++ *
++ * Similarly, in order to account for waiters being requeued on another
++ * address we always increment the waiters for the destination bucket before
++ * acquiring the lock. It then decrements them again after releasing it -
++ * the code that actually moves the futex(es) between hash buckets (requeue_futex)
++ * will do the additional required waiter count housekeeping. This is done for
++ * double_lock_hb() and double_unlock_hb(), respectively.
++ */
++
++/*
++ * The hash bucket lock must be held when this is called.
++ * Afterwards, the futex_q must not be accessed. Callers
++ * must ensure to later call wake_up_q() for the actual
++ * wakeups to occur.
++ */
++void futex_wake_mark(struct wake_q_head *wake_q, struct futex_q *q)
++{
++ struct task_struct *p = q->task;
++
++ if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
++ return;
++
++ get_task_struct(p);
++ __futex_unqueue(q);
++ /*
++ * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
++ * is written, without taking any locks. This is possible in the event
++ * of a spurious wakeup, for example. A memory barrier is required here
++ * to prevent the following store to lock_ptr from getting ahead of the
++ * plist_del in __futex_unqueue().
++ */
++ smp_store_release(&q->lock_ptr, NULL);
++
++ /*
++ * Queue the task for later wakeup for after we've released
++ * the hb->lock.
++ */
++ wake_q_add_safe(wake_q, p);
++}
++
++/*
++ * Wake up waiters matching bitset queued on this futex (uaddr).
++ */
++int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
++{
++ struct futex_hash_bucket *hb;
++ struct futex_q *this, *next;
++ union futex_key key = FUTEX_KEY_INIT;
++ int ret;
++ DEFINE_WAKE_Q(wake_q);
++
++ if (!bitset)
++ return -EINVAL;
++
++ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, FUTEX_READ);
++ if (unlikely(ret != 0))
++ return ret;
++
++ hb = futex_hash(&key);
++
++ /* Make sure we really have tasks to wakeup */
++ if (!futex_hb_waiters_pending(hb))
++ return ret;
++
++ spin_lock(&hb->lock);
++
++ plist_for_each_entry_safe(this, next, &hb->chain, list) {
++ if (futex_match (&this->key, &key)) {
++ if (this->pi_state || this->rt_waiter) {
++ ret = -EINVAL;
++ break;
++ }
++
++ /* Check if one of the bits is set in both bitsets */
++ if (!(this->bitset & bitset))
++ continue;
++
++ futex_wake_mark(&wake_q, this);
++ if (++ret >= nr_wake)
++ break;
++ }
++ }
++
++ spin_unlock(&hb->lock);
++ wake_up_q(&wake_q);
++ return ret;
++}
++
++static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
++{
++ unsigned int op = (encoded_op & 0x70000000) >> 28;
++ unsigned int cmp = (encoded_op & 0x0f000000) >> 24;
++ int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 11);
++ int cmparg = sign_extend32(encoded_op & 0x00000fff, 11);
++ int oldval, ret;
++
++ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
++ if (oparg < 0 || oparg > 31) {
++ char comm[sizeof(current->comm)];
++ /*
++ * kill this print and return -EINVAL when userspace
++ * is sane again
++ */
++ pr_info_ratelimited("futex_wake_op: %s tries to shift op by %d; fix this program\n",
++ get_task_comm(comm, current), oparg);
++ oparg &= 31;
++ }
++ oparg = 1 << oparg;
++ }
++
++ pagefault_disable();
++ ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
++ pagefault_enable();
++ if (ret)
++ return ret;
++
++ switch (cmp) {
++ case FUTEX_OP_CMP_EQ:
++ return oldval == cmparg;
++ case FUTEX_OP_CMP_NE:
++ return oldval != cmparg;
++ case FUTEX_OP_CMP_LT:
++ return oldval < cmparg;
++ case FUTEX_OP_CMP_GE:
++ return oldval >= cmparg;
++ case FUTEX_OP_CMP_LE:
++ return oldval <= cmparg;
++ case FUTEX_OP_CMP_GT:
++ return oldval > cmparg;
++ default:
++ return -ENOSYS;
++ }
++}
++
++/*
++ * Wake up all waiters hashed on the physical page that is mapped
++ * to this virtual address:
++ */
++int futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
++ int nr_wake, int nr_wake2, int op)
++{
++ union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
++ struct futex_hash_bucket *hb1, *hb2;
++ struct futex_q *this, *next;
++ int ret, op_ret;
++ DEFINE_WAKE_Q(wake_q);
++
++retry:
++ ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, FUTEX_READ);
++ if (unlikely(ret != 0))
++ return ret;
++ ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
++ if (unlikely(ret != 0))
++ return ret;
++
++ hb1 = futex_hash(&key1);
++ hb2 = futex_hash(&key2);
++
++retry_private:
++ double_lock_hb(hb1, hb2);
++ op_ret = futex_atomic_op_inuser(op, uaddr2);
++ if (unlikely(op_ret < 0)) {
++ double_unlock_hb(hb1, hb2);
++
++ if (!IS_ENABLED(CONFIG_MMU) ||
++ unlikely(op_ret != -EFAULT && op_ret != -EAGAIN)) {
++ /*
++ * we don't get EFAULT from MMU faults if we don't have
++ * an MMU, but we might get them from range checking
++ */
++ ret = op_ret;
++ return ret;
++ }
++
++ if (op_ret == -EFAULT) {
++ ret = fault_in_user_writeable(uaddr2);
++ if (ret)
++ return ret;
++ }
++
++ cond_resched();
++ if (!(flags & FLAGS_SHARED))
++ goto retry_private;
++ goto retry;
++ }
++
++ plist_for_each_entry_safe(this, next, &hb1->chain, list) {
++ if (futex_match (&this->key, &key1)) {
++ if (this->pi_state || this->rt_waiter) {
++ ret = -EINVAL;
++ goto out_unlock;
++ }
++ futex_wake_mark(&wake_q, this);
++ if (++ret >= nr_wake)
++ break;
++ }
++ }
++
++ if (op_ret > 0) {
++ op_ret = 0;
++ plist_for_each_entry_safe(this, next, &hb2->chain, list) {
++ if (futex_match (&this->key, &key2)) {
++ if (this->pi_state || this->rt_waiter) {
++ ret = -EINVAL;
++ goto out_unlock;
++ }
++ futex_wake_mark(&wake_q, this);
++ if (++op_ret >= nr_wake2)
++ break;
++ }
++ }
++ ret += op_ret;
++ }
++
++out_unlock:
++ double_unlock_hb(hb1, hb2);
++ wake_up_q(&wake_q);
++ return ret;
++}
++
++static long futex_wait_restart(struct restart_block *restart);
++
++/**
++ * futex_wait_queue() - futex_queue() and wait for wakeup, timeout, or signal
++ * @hb: the futex hash bucket, must be locked by the caller
++ * @q: the futex_q to queue up on
++ * @timeout: the prepared hrtimer_sleeper, or null for no timeout
++ */
++void futex_wait_queue(struct futex_hash_bucket *hb, struct futex_q *q,
++ struct hrtimer_sleeper *timeout)
++{
++ /*
++ * The task state is guaranteed to be set before another task can
++ * wake it. set_current_state() is implemented using smp_store_mb() and
++ * futex_queue() calls spin_unlock() upon completion, both serializing
++ * access to the hash list and forcing another memory barrier.
++ */
++ set_current_state(TASK_INTERRUPTIBLE);
++ futex_queue(q, hb);
++
++ /* Arm the timer */
++ if (timeout)
++ hrtimer_sleeper_start_expires(timeout, HRTIMER_MODE_ABS);
++
++ /*
++ * If we have been removed from the hash list, then another task
++ * has tried to wake us, and we can skip the call to schedule().
++ */
++ if (likely(!plist_node_empty(&q->list))) {
++ /*
++ * If the timer has already expired, current will already be
++ * flagged for rescheduling. Only call schedule if there
++ * is no timeout, or if it has yet to expire.
++ */
++ if (!timeout || timeout->task)
++ freezable_schedule();
++ }
++ __set_current_state(TASK_RUNNING);
++}
++
++/**
++ * unqueue_multiple - Remove various futexes from their hash bucket
++ * @v: The list of futexes to unqueue
++ * @count: Number of futexes in the list
++ *
++ * Helper to unqueue a list of futexes. This can't fail.
++ *
++ * Return:
++ * - >=0 - Index of the last futex that was awoken;
++ * - -1 - No futex was awoken
++ */
++static int unqueue_multiple(struct futex_vector *v, int count)
++{
++ int ret = -1, i;
++
++ for (i = 0; i < count; i++) {
++ if (!futex_unqueue(&v[i].q))
++ ret = i;
++ }
++
++ return ret;
++}
++
++/**
++ * futex_wait_multiple_setup - Prepare to wait and enqueue multiple futexes
++ * @vs: The futex list to wait on
++ * @count: The size of the list
++ * @awaken: Index of the last awoken futex, if any. Used to notify the
++ * caller that it can return this index to userspace (return parameter)
++ *
++ * Prepare multiple futexes in a single step and enqueue them. This may fail if
++ * the futex list is invalid or if any futex was already awoken. On success the
++ * task is ready to interruptible sleep.
++ *
++ * Return:
++ * - 1 - One of the futexes was awaken by another thread
++ * - 0 - Success
++ * - <0 - -EFAULT, -EWOULDBLOCK or -EINVAL
++ */
++static int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *awaken)
++{
++ struct futex_hash_bucket *hb;
++ bool retry = false;
++ int ret, i;
++ u32 uval;
++
++ /*
++ * Enqueuing multiple futexes is tricky, because we need to enqueue
++ * each futex in the list before dealing with the next one to avoid
++ * deadlocking on the hash bucket. But, before enqueuing, we need to
++ * make sure that current->state is TASK_INTERRUPTIBLE, so we don't
++ * absorb any awake events, which cannot be done before the
++ * get_futex_key of the next key, because it calls get_user_pages,
++ * which can sleep. Thus, we fetch the list of futexes keys in two
++ * steps, by first pinning all the memory keys in the futex key, and
++ * only then we read each key and queue the corresponding futex.
++ *
++ * Private futexes doesn't need to recalculate hash in retry, so skip
++ * get_futex_key() when retrying.
++ */
++retry:
++ for (i = 0; i < count; i++) {
++ if ((vs[i].w.flags & FUTEX_PRIVATE_FLAG) && retry)
++ continue;
++
++ ret = get_futex_key(u64_to_user_ptr(vs[i].w.uaddr),
++ !(vs[i].w.flags & FUTEX_PRIVATE_FLAG),
++ &vs[i].q.key, FUTEX_READ);
++
++ if (unlikely(ret))
++ return ret;
++ }
++
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ for (i = 0; i < count; i++) {
++ u32 __user *uaddr = (u32 __user *)(unsigned long)vs[i].w.uaddr;
++ struct futex_q *q = &vs[i].q;
++ u32 val = (u32)vs[i].w.val;
++
++ hb = futex_q_lock(q);
++ ret = futex_get_value_locked(&uval, uaddr);
++
++ if (!ret && uval == val) {
++ /*
++ * The bucket lock can't be held while dealing with the
++ * next futex. Queue each futex at this moment so hb can
++ * be unlocked.
++ */
++ futex_queue(q, hb);
++ continue;
++ }
++
++ futex_q_unlock(hb);
++ __set_current_state(TASK_RUNNING);
++
++ /*
++ * Even if something went wrong, if we find out that a futex
++ * was awaken, we don't return error and return this index to
++ * userspace
++ */
++ *awaken = unqueue_multiple(vs, i);
++ if (*awaken >= 0)
++ return 1;
++
++ if (ret) {
++ /*
++ * If we need to handle a page fault, we need to do so
++ * without any lock and any enqueued futex (otherwise
++ * we could lose some wakeup). So we do it here, after
++ * undoing all the work done so far. In success, we
++ * retry all the work.
++ */
++ if (get_user(uval, uaddr))
++ return -EFAULT;
++
++ retry = true;
++ goto retry;
++ }
++
++ if (uval != val)
++ return -EWOULDBLOCK;
++ }
++
++ return 0;
++}
++
++/**
++ * futex_sleep_multiple - Check sleeping conditions and sleep
++ * @vs: List of futexes to wait for
++ * @count: Length of vs
++ * @to: Timeout
++ *
++ * Sleep if and only if the timeout hasn't expired and no futex on the list has
++ * been awaken.
++ */
++static void futex_sleep_multiple(struct futex_vector *vs, unsigned int count,
++ struct hrtimer_sleeper *to)
++{
++ if (to && !to->task)
++ return;
++
++ for (; count; count--, vs++) {
++ if (!READ_ONCE(vs->q.lock_ptr))
++ return;
++ }
++
++ freezable_schedule();
++}
++
++/**
++ * futex_wait_multiple - Prepare to wait on and enqueue several futexes
++ * @vs: The list of futexes to wait on
++ * @count: The number of objects
++ * @to: Timeout before giving up and returning to userspace
++ *
++ * Entry point for the FUTEX_WAIT_MULTIPLE futex operation, this function
++ * sleeps on a group of futexes and returns on the first futex that is
++ * wake, or after the timeout has elapsed.
++ *
++ * Return:
++ * - >=0 - Hint to the futex that was awoken
++ * - <0 - On error
++ */
++int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
++ struct hrtimer_sleeper *to)
++{
++ int ret, hint = 0;
++
++ if (to)
++ hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS);
++
++ while (1) {
++ ret = futex_wait_multiple_setup(vs, count, &hint);
++ if (ret) {
++ if (ret > 0) {
++ /* A futex was awaken during setup */
++ ret = hint;
++ }
++ return ret;
++ }
++
++ futex_sleep_multiple(vs, count, to);
++
++ __set_current_state(TASK_RUNNING);
++
++ ret = unqueue_multiple(vs, count);
++ if (ret >= 0)
++ return ret;
++
++ if (to && !to->task)
++ return -ETIMEDOUT;
++ else if (signal_pending(current))
++ return -ERESTARTSYS;
++ /*
++ * The final case is a spurious wakeup, for
++ * which just retry.
++ */
++ }
++}
++
++/**
++ * futex_wait_setup() - Prepare to wait on a futex
++ * @uaddr: the futex userspace address
++ * @val: the expected value
++ * @flags: futex flags (FLAGS_SHARED, etc.)
++ * @q: the associated futex_q
++ * @hb: storage for hash_bucket pointer to be returned to caller
++ *
++ * Setup the futex_q and locate the hash_bucket. Get the futex value and
++ * compare it with the expected value. Handle atomic faults internally.
++ * Return with the hb lock held on success, and unlocked on failure.
++ *
++ * Return:
++ * - 0 - uaddr contains val and hb has been locked;
++ * - <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
++ */
++int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
++ struct futex_q *q, struct futex_hash_bucket **hb)
++{
++ u32 uval;
++ int ret;
++
++ /*
++ * Access the page AFTER the hash-bucket is locked.
++ * Order is important:
++ *
++ * Userspace waiter: val = var; if (cond(val)) futex_wait(&var, val);
++ * Userspace waker: if (cond(var)) { var = new; futex_wake(&var); }
++ *
++ * The basic logical guarantee of a futex is that it blocks ONLY
++ * if cond(var) is known to be true at the time of blocking, for
++ * any cond. If we locked the hash-bucket after testing *uaddr, that
++ * would open a race condition where we could block indefinitely with
++ * cond(var) false, which would violate the guarantee.
++ *
++ * On the other hand, we insert q and release the hash-bucket only
++ * after testing *uaddr. This guarantees that futex_wait() will NOT
++ * absorb a wakeup if *uaddr does not match the desired values
++ * while the syscall executes.
++ */
++retry:
++ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key, FUTEX_READ);
++ if (unlikely(ret != 0))
++ return ret;
++
++retry_private:
++ *hb = futex_q_lock(q);
++
++ ret = futex_get_value_locked(&uval, uaddr);
++
++ if (ret) {
++ futex_q_unlock(*hb);
++
++ ret = get_user(uval, uaddr);
++ if (ret)
++ return ret;
++
++ if (!(flags & FLAGS_SHARED))
++ goto retry_private;
++
++ goto retry;
++ }
++
++ if (uval != val) {
++ futex_q_unlock(*hb);
++ ret = -EWOULDBLOCK;
++ }
++
++ return ret;
++}
++
++int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val, ktime_t *abs_time, u32 bitset)
++{
++ struct hrtimer_sleeper timeout, *to;
++ struct restart_block *restart;
++ struct futex_hash_bucket *hb;
++ struct futex_q q = futex_q_init;
++ int ret;
++
++ if (!bitset)
++ return -EINVAL;
++ q.bitset = bitset;
++
++ to = futex_setup_timer(abs_time, &timeout, flags,
++ current->timer_slack_ns);
++retry:
++ /*
++ * Prepare to wait on uaddr. On success, it holds hb->lock and q
++ * is initialized.
++ */
++ ret = futex_wait_setup(uaddr, val, flags, &q, &hb);
++ if (ret)
++ goto out;
++
++ /* futex_queue and wait for wakeup, timeout, or a signal. */
++ futex_wait_queue(hb, &q, to);
++
++ /* If we were woken (and unqueued), we succeeded, whatever. */
++ ret = 0;
++ if (!futex_unqueue(&q))
++ goto out;
++ ret = -ETIMEDOUT;
++ if (to && !to->task)
++ goto out;
++
++ /*
++ * We expect signal_pending(current), but we might be the
++ * victim of a spurious wakeup as well.
++ */
++ if (!signal_pending(current))
++ goto retry;
++
++ ret = -ERESTARTSYS;
++ if (!abs_time)
++ goto out;
++
++ restart = &current->restart_block;
++ restart->futex.uaddr = uaddr;
++ restart->futex.val = val;
++ restart->futex.time = *abs_time;
++ restart->futex.bitset = bitset;
++ restart->futex.flags = flags | FLAGS_HAS_TIMEOUT;
++
++ ret = set_restart_fn(restart, futex_wait_restart);
++
++out:
++ if (to) {
++ hrtimer_cancel(&to->timer);
++ destroy_hrtimer_on_stack(&to->timer);
++ }
++ return ret;
++}
++
++static long futex_wait_restart(struct restart_block *restart)
++{
++ u32 __user *uaddr = restart->futex.uaddr;
++ ktime_t t, *tp = NULL;
++
++ if (restart->futex.flags & FLAGS_HAS_TIMEOUT) {
++ t = restart->futex.time;
++ tp = &t;
++ }
++ restart->fn = do_no_restart_syscall;
++
++ return (long)futex_wait(uaddr, restart->futex.flags,
++ restart->futex.val, tp, restart->futex.bitset);
++}
++
+diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
+index f43d89d92..d1944258c 100644
+--- a/kernel/sys_ni.c
++++ b/kernel/sys_ni.c
+@@ -143,13 +143,14 @@ COND_SYSCALL(capset);
+ /* __ARCH_WANT_SYS_CLONE3 */
+ COND_SYSCALL(clone3);
+
+-/* kernel/futex.c */
++/* kernel/futex/syscalls.c */
+ COND_SYSCALL(futex);
+ COND_SYSCALL(futex_time32);
+ COND_SYSCALL(set_robust_list);
+ COND_SYSCALL_COMPAT(set_robust_list);
+ COND_SYSCALL(get_robust_list);
+ COND_SYSCALL_COMPAT(get_robust_list);
++COND_SYSCALL(futex_waitv);
+
+ /* kernel/hrtimer.c */
+
+diff --git a/tools/testing/selftests/futex/functional/.gitignore b/tools/testing/selftests/futex/functional/.gitignore
+index 0e78b49d0..fbcbdb696 100644
+--- a/tools/testing/selftests/futex/functional/.gitignore
++++ b/tools/testing/selftests/futex/functional/.gitignore
+@@ -8,3 +8,4 @@ futex_wait_uninitialized_heap
+ futex_wait_wouldblock
+ futex_wait
+ futex_requeue
++futex_waitv
+diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile
+index bd1fec59e..5cc38de9d 100644
+--- a/tools/testing/selftests/futex/functional/Makefile
++++ b/tools/testing/selftests/futex/functional/Makefile
+@@ -17,7 +17,8 @@ TEST_GEN_FILES := \
+ futex_wait_uninitialized_heap \
+ futex_wait_private_mapped_file \
+ futex_wait \
+- futex_requeue
++ futex_requeue \
++ futex_waitv
+
+ TEST_PROGS := run.sh
+
+diff --git a/tools/testing/selftests/futex/functional/futex_wait_timeout.c b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
+index 1f8f6daaf..3651ce17b 100644
+--- a/tools/testing/selftests/futex/functional/futex_wait_timeout.c
++++ b/tools/testing/selftests/futex/functional/futex_wait_timeout.c
+@@ -17,6 +17,7 @@
+
+ #include <pthread.h>
+ #include "futextest.h"
++#include "futex2test.h"
+ #include "logging.h"
+
+ #define TEST_NAME "futex-wait-timeout"
+@@ -96,6 +97,12 @@ int main(int argc, char *argv[])
+ struct timespec to;
+ pthread_t thread;
+ int c;
++ struct futex_waitv waitv = {
++ .uaddr = (uintptr_t)&f1,
++ .val = f1,
++ .flags = FUTEX_32,
++ .__reserved = 0
++ };
+
+ while ((c = getopt(argc, argv, "cht:v:")) != -1) {
+ switch (c) {
+@@ -118,7 +125,7 @@ int main(int argc, char *argv[])
+ }
+
+ ksft_print_header();
+- ksft_set_plan(7);
++ ksft_set_plan(9);
+ ksft_print_msg("%s: Block on a futex and wait for timeout\n",
+ basename(argv[0]));
+ ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
+@@ -175,6 +182,18 @@ int main(int argc, char *argv[])
+ res = futex_lock_pi(&futex_pi, NULL, 0, FUTEX_CLOCK_REALTIME);
+ test_timeout(res, &ret, "futex_lock_pi invalid timeout flag", ENOSYS);
+
++ /* futex_waitv with CLOCK_MONOTONIC */
++ if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns))
++ return RET_FAIL;
++ res = futex_waitv(&waitv, 1, 0, &to, CLOCK_MONOTONIC);
++ test_timeout(res, &ret, "futex_waitv monotonic", ETIMEDOUT);
++
++ /* futex_waitv with CLOCK_REALTIME */
++ if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns))
++ return RET_FAIL;
++ res = futex_waitv(&waitv, 1, 0, &to, CLOCK_REALTIME);
++ test_timeout(res, &ret, "futex_waitv realtime", ETIMEDOUT);
++
+ ksft_print_cnts();
+ return ret;
+ }
+diff --git a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
+index 0ae390ff8..7d7a6a06c 100644
+--- a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
++++ b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
+@@ -22,6 +22,7 @@
+ #include <string.h>
+ #include <time.h>
+ #include "futextest.h"
++#include "futex2test.h"
+ #include "logging.h"
+
+ #define TEST_NAME "futex-wait-wouldblock"
+@@ -42,6 +43,12 @@ int main(int argc, char *argv[])
+ futex_t f1 = FUTEX_INITIALIZER;
+ int res, ret = RET_PASS;
+ int c;
++ struct futex_waitv waitv = {
++ .uaddr = (uintptr_t)&f1,
++ .val = f1+1,
++ .flags = FUTEX_32,
++ .__reserved = 0
++ };
+
+ while ((c = getopt(argc, argv, "cht:v:")) != -1) {
+ switch (c) {
+@@ -61,18 +68,44 @@ int main(int argc, char *argv[])
+ }
+
+ ksft_print_header();
+- ksft_set_plan(1);
++ ksft_set_plan(2);
+ ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n",
+ basename(argv[0]));
+
+ info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1);
+ res = futex_wait(&f1, f1+1, &to, FUTEX_PRIVATE_FLAG);
+ if (!res || errno != EWOULDBLOCK) {
+- fail("futex_wait returned: %d %s\n",
+- res ? errno : res, res ? strerror(errno) : "");
++ ksft_test_result_fail("futex_wait returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
+ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_wait\n");
+ }
+
+- print_result(TEST_NAME, ret);
++ if (clock_gettime(CLOCK_MONOTONIC, &to)) {
++ error("clock_gettime failed\n", errno);
++ return errno;
++ }
++
++ to.tv_nsec += timeout_ns;
++
++ if (to.tv_nsec >= 1000000000) {
++ to.tv_sec++;
++ to.tv_nsec -= 1000000000;
++ }
++
++ info("Calling futex_waitv on f1: %u @ %p with val=%u\n", f1, &f1, f1+1);
++ res = futex_waitv(&waitv, 1, 0, &to, CLOCK_MONOTONIC);
++ if (!res || errno != EWOULDBLOCK) {
++ ksft_test_result_pass("futex_waitv returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv\n");
++ }
++
++ ksft_print_cnts();
+ return ret;
+ }
+diff --git a/tools/testing/selftests/futex/functional/futex_waitv.c b/tools/testing/selftests/futex/functional/futex_waitv.c
+new file mode 100644
+index 000000000..a94337f67
+--- /dev/null
++++ b/tools/testing/selftests/futex/functional/futex_waitv.c
+@@ -0,0 +1,237 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * futex_waitv() test by André Almeida <andrealmeid@collabora.com>
++ *
++ * Copyright 2021 Collabora Ltd.
++ */
++
++#include <errno.h>
++#include <error.h>
++#include <getopt.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++#include <pthread.h>
++#include <stdint.h>
++#include <sys/shm.h>
++#include "futextest.h"
++#include "futex2test.h"
++#include "logging.h"
++
++#define TEST_NAME "futex-wait"
++#define WAKE_WAIT_US 10000
++#define NR_FUTEXES 30
++static struct futex_waitv waitv[NR_FUTEXES];
++u_int32_t futexes[NR_FUTEXES] = {0};
++
++void usage(char *prog)
++{
++ printf("Usage: %s\n", prog);
++ printf(" -c Use color\n");
++ printf(" -h Display this help message\n");
++ printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",
++ VQUIET, VCRITICAL, VINFO);
++}
++
++void *waiterfn(void *arg)
++{
++ struct timespec to;
++ int res;
++
++ /* setting absolute timeout for futex2 */
++ if (clock_gettime(CLOCK_MONOTONIC, &to))
++ error("gettime64 failed\n", errno);
++
++ to.tv_sec++;
++
++ res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
++ if (res < 0) {
++ ksft_test_result_fail("futex_waitv returned: %d %s\n",
++ errno, strerror(errno));
++ } else if (res != NR_FUTEXES - 1) {
++ ksft_test_result_fail("futex_waitv returned: %d, expecting %d\n",
++ res, NR_FUTEXES - 1);
++ }
++
++ return NULL;
++}
++
++int main(int argc, char *argv[])
++{
++ pthread_t waiter;
++ int res, ret = RET_PASS;
++ struct timespec to;
++ int c, i;
++
++ while ((c = getopt(argc, argv, "cht:v:")) != -1) {
++ switch (c) {
++ case 'c':
++ log_color(1);
++ break;
++ case 'h':
++ usage(basename(argv[0]));
++ exit(0);
++ case 'v':
++ log_verbosity(atoi(optarg));
++ break;
++ default:
++ usage(basename(argv[0]));
++ exit(1);
++ }
++ }
++
++ ksft_print_header();
++ ksft_set_plan(7);
++ ksft_print_msg("%s: Test FUTEX_WAITV\n",
++ basename(argv[0]));
++
++ for (i = 0; i < NR_FUTEXES; i++) {
++ waitv[i].uaddr = (uintptr_t)&futexes[i];
++ waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;
++ waitv[i].val = 0;
++ waitv[i].__reserved = 0;
++ }
++
++ /* Private waitv */
++ if (pthread_create(&waiter, NULL, waiterfn, NULL))
++ error("pthread_create failed\n", errno);
++
++ usleep(WAKE_WAIT_US);
++
++ res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, FUTEX_PRIVATE_FLAG);
++ if (res != 1) {
++ ksft_test_result_fail("futex_wake private returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv private\n");
++ }
++
++ /* Shared waitv */
++ for (i = 0; i < NR_FUTEXES; i++) {
++ int shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
++
++ if (shm_id < 0) {
++ perror("shmget");
++ exit(1);
++ }
++
++ unsigned int *shared_data = shmat(shm_id, NULL, 0);
++
++ *shared_data = 0;
++ waitv[i].uaddr = (uintptr_t)shared_data;
++ waitv[i].flags = FUTEX_32;
++ waitv[i].val = 0;
++ waitv[i].__reserved = 0;
++ }
++
++ if (pthread_create(&waiter, NULL, waiterfn, NULL))
++ error("pthread_create failed\n", errno);
++
++ usleep(WAKE_WAIT_US);
++
++ res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, 0);
++ if (res != 1) {
++ ksft_test_result_fail("futex_wake shared returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv shared\n");
++ }
++
++ for (i = 0; i < NR_FUTEXES; i++)
++ shmdt(u64_to_ptr(waitv[i].uaddr));
++
++ /* Testing a waiter without FUTEX_32 flag */
++ waitv[0].flags = FUTEX_PRIVATE_FLAG;
++
++ if (clock_gettime(CLOCK_MONOTONIC, &to))
++ error("gettime64 failed\n", errno);
++
++ to.tv_sec++;
++
++ res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
++ if (res == EINVAL) {
++ ksft_test_result_fail("futex_waitv private returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv without FUTEX_32\n");
++ }
++
++ /* Testing a waiter with an unaligned address */
++ waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32;
++ waitv[0].uaddr = 1;
++
++ if (clock_gettime(CLOCK_MONOTONIC, &to))
++ error("gettime64 failed\n", errno);
++
++ to.tv_sec++;
++
++ res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
++ if (res == EINVAL) {
++ ksft_test_result_fail("futex_wake private returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv with an unaligned address\n");
++ }
++
++ /* Testing a NULL address for waiters.uaddr */
++ waitv[0].uaddr = 0x00000000;
++
++ if (clock_gettime(CLOCK_MONOTONIC, &to))
++ error("gettime64 failed\n", errno);
++
++ to.tv_sec++;
++
++ res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
++ if (res == EINVAL) {
++ ksft_test_result_fail("futex_waitv private returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv NULL address in waitv.uaddr\n");
++ }
++
++ /* Testing a NULL address for *waiters */
++ if (clock_gettime(CLOCK_MONOTONIC, &to))
++ error("gettime64 failed\n", errno);
++
++ to.tv_sec++;
++
++ res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
++ if (res == EINVAL) {
++ ksft_test_result_fail("futex_waitv private returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv NULL address in *waiters\n");
++ }
++
++ /* Testing an invalid clockid */
++ if (clock_gettime(CLOCK_MONOTONIC, &to))
++ error("gettime64 failed\n", errno);
++
++ to.tv_sec++;
++
++ res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_TAI);
++ if (res == EINVAL) {
++ ksft_test_result_fail("futex_waitv private returned: %d %s\n",
++ res ? errno : res,
++ res ? strerror(errno) : "");
++ ret = RET_FAIL;
++ } else {
++ ksft_test_result_pass("futex_waitv invalid clockid\n");
++ }
++
++ ksft_print_cnts();
++ return ret;
++}
+diff --git a/tools/testing/selftests/futex/functional/run.sh b/tools/testing/selftests/futex/functional/run.sh
+index 11a9d6229..5ccd599da 100755
+--- a/tools/testing/selftests/futex/functional/run.sh
++++ b/tools/testing/selftests/futex/functional/run.sh
+@@ -79,3 +79,6 @@ echo
+
+ echo
+ ./futex_requeue $COLOR
++
++echo
++./futex_waitv $COLOR
+diff --git a/tools/testing/selftests/futex/include/futex2test.h b/tools/testing/selftests/futex/include/futex2test.h
+new file mode 100644
+index 000000000..9d305520e
+--- /dev/null
++++ b/tools/testing/selftests/futex/include/futex2test.h
+@@ -0,0 +1,22 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * Futex2 library addons for futex tests
++ *
++ * Copyright 2021 Collabora Ltd.
++ */
++#include <stdint.h>
++
++#define u64_to_ptr(x) ((void *)(uintptr_t)(x))
++
++/**
++ * futex_waitv - Wait at multiple futexes, wake on any
++ * @waiters: Array of waiters
++ * @nr_waiters: Length of waiters array
++ * @flags: Operation flags
++ * @timo: Optional timeout for operation
++ */
++static inline int futex_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters,
++ unsigned long flags, struct timespec *timo, clockid_t clockid)
++{
++ return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, timo, clockid);
++}
+--
+2.33.1.711.g9d530dc002
+
+
diff --git a/0104-revert-xhci-Add-support-for-Renesas-controller-with-memory.patch b/0104-revert-xhci-Add-support-for-Renesas-controller-with-memory.patch
new file mode 100644
index 000000000000..dafb17784fdb
--- /dev/null
+++ b/0104-revert-xhci-Add-support-for-Renesas-controller-with-memory.patch
@@ -0,0 +1,89 @@
+--- b/drivers/usb/host/xhci-pci.c
++++ a/drivers/usb/host/xhci-pci.c
+@@ -636,14 +636,7 @@
+ { /* end: all zeroes */ }
+ };
+ MODULE_DEVICE_TABLE(pci, pci_ids);
+-
+-/*
+- * Without CONFIG_USB_XHCI_PCI_RENESAS renesas_xhci_check_request_fw() won't
+- * load firmware, so don't encumber the xhci-pci driver with it.
+- */
+-#if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS)
+ MODULE_FIRMWARE("renesas_usb_fw.mem");
+-#endif
+
+ /* pci driver glue; this is a "new style" PCI driver module */
+ static struct pci_driver xhci_pci_driver = {
+--- b/drivers/usb/host/xhci-pci.c
++++ a/drivers/usb/host/xhci-pci.c
+@@ -16,7 +16,6 @@
+
+ #include "xhci.h"
+ #include "xhci-trace.h"
+-#include "xhci-pci.h"
+
+ #define SSIC_PORT_NUM 2
+ #define SSIC_PORT_CFG2 0x880c
+@@ -92,16 +91,7 @@ static int xhci_pci_reinit(struct xhci_h
+
+ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+ {
+- struct pci_dev *pdev = to_pci_dev(dev);
+- struct xhci_driver_data *driver_data;
+- const struct pci_device_id *id;
+-
+- id = pci_match_id(pdev->driver->id_table, pdev);
+-
+- if (id && id->driver_data) {
+- driver_data = (struct xhci_driver_data *)id->driver_data;
+- xhci->quirks |= driver_data->quirks;
+- }
++ struct pci_dev *pdev = to_pci_dev(dev);
+
+ /* Look for vendor-specific quirks */
+ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+@@ -346,16 +336,8 @@ static int xhci_pci_probe(struct pci_dev
+ int retval;
+ struct xhci_hcd *xhci;
+ struct usb_hcd *hcd;
+- struct xhci_driver_data *driver_data;
+ struct reset_control *reset;
+
+- driver_data = (struct xhci_driver_data *)id->driver_data;
+- if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) {
+- retval = renesas_xhci_check_request_fw(dev, id);
+- if (retval)
+- return retval;
+- }
+-
+ reset = devm_reset_control_get_optional_exclusive(&dev->dev, NULL);
+ if (IS_ERR(reset))
+ return PTR_ERR(reset);
+@@ -578,26 +557,14 @@ static void xhci_pci_shutdown(struct usb
+
+ /*-------------------------------------------------------------------------*/
+
+-static const struct xhci_driver_data reneses_data = {
+- .quirks = XHCI_RENESAS_FW_QUIRK,
+- .firmware = "renesas_usb_fw.mem",
+-};
+-
+ /* PCI driver selection metadata; PCI hotplugging uses this */
+ static const struct pci_device_id pci_ids[] = {
+- { PCI_DEVICE(0x1912, 0x0014),
+- .driver_data = (unsigned long)&reneses_data,
+- },
+- { PCI_DEVICE(0x1912, 0x0015),
+- .driver_data = (unsigned long)&reneses_data,
+- },
+ /* handle any USB 3.0 xHCI controller */
+ { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0),
+ },
+ { /* end: all zeroes */ }
+ };
+ MODULE_DEVICE_TABLE(pci, pci_ids);
+-MODULE_FIRMWARE("renesas_usb_fw.mem");
+
+ /* pci driver glue; this is a "new style" PCI driver module */
+ static struct pci_driver xhci_pci_driver = {
diff --git a/0105-quirk-kernel-org-bug-210681-firmware_rome_error.patch b/0105-quirk-kernel-org-bug-210681-firmware_rome_error.patch
new file mode 100644
index 000000000000..7f46da7672da
--- /dev/null
+++ b/0105-quirk-kernel-org-bug-210681-firmware_rome_error.patch
@@ -0,0 +1,12 @@
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 03b83aa91277..dfc6c7d1b0e7 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -4070,6 +4070,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
+ }
+ if (!info) {
+ bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
++ if (ver_rom & ~0xffffU) return 0;
+ return -ENODEV;
+ }
+
diff --git a/0201-lenovo-wmi2.patch b/0201-lenovo-wmi2.patch
new file mode 100644
index 000000000000..c6b1b0603651
--- /dev/null
+++ b/0201-lenovo-wmi2.patch
@@ -0,0 +1,15 @@
+diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
+index 791449a2370f..45d9010aafcf 100644
+--- a/drivers/platform/x86/wmi.c
++++ b/drivers/platform/x86/wmi.c
+@@ -1081,7 +1081,8 @@ static int wmi_create_device(struct device *wmi_bus_dev,
+ wblock->dev.dev.bus = &wmi_bus_type;
+ wblock->dev.dev.parent = wmi_bus_dev;
+
+- dev_set_name(&wblock->dev.dev, "%pUL", gblock->guid);
++ dev_set_name(&wblock->dev.dev, "%s-%pUL",
++ dev_name(&wblock->acpi_device->dev), gblock->guid);
+
+ device_initialize(&wblock->dev.dev);
+
+
diff --git a/0301-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch b/0301-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
new file mode 100644
index 000000000000..c12688800eab
--- /dev/null
+++ b/0301-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
@@ -0,0 +1,150 @@
+--- b/drivers/video/fbdev/core/bitblit.c
++++ a/drivers/video/fbdev/core/bitblit.c
+@@ -234,7 +234,7 @@
+ }
+
+ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg)
+- int fg, int bg)
+ {
+ struct fb_cursor cursor;
+ struct fbcon_ops *ops = info->fbcon_par;
+@@ -247,6 +247,15 @@
+
+ cursor.set = 0;
+
++ if (softback_lines) {
++ if (y + softback_lines >= vc->vc_rows) {
++ mode = CM_ERASE;
++ ops->cursor_flash = 0;
++ return;
++ } else
++ y += softback_lines;
++ }
++
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+ src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+--- b/drivers/video/fbdev/core/fbcon.c
++++ a/drivers/video/fbdev/core/fbcon.c
+@@ -394,7 +394,7 @@
+ c = scr_readw((u16 *) vc->vc_pos);
+ mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
+ CM_ERASE : CM_DRAW;
++ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
+- ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+ get_color(vc, info, c, 0));
+ console_unlock();
+ }
+@@ -1345,7 +1345,7 @@
+
+ ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
+
++ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
+- ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
+ get_color(vc, info, c, 0));
+ }
+
+--- b/drivers/video/fbdev/core/fbcon.h
++++ a/drivers/video/fbdev/core/fbcon.h
+@@ -62,7 +62,7 @@
+ void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
+ int color, int bottom_only);
+ void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg);
+- int fg, int bg);
+ int (*update_start)(struct fb_info *info);
+ int (*rotate_font)(struct fb_info *info, struct vc_data *vc);
+ struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */
+--- b/drivers/video/fbdev/core/fbcon_ccw.c
++++ a/drivers/video/fbdev/core/fbcon_ccw.c
+@@ -219,7 +219,7 @@
+ }
+
+ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg)
+- int fg, int bg)
+ {
+ struct fb_cursor cursor;
+ struct fbcon_ops *ops = info->fbcon_par;
+@@ -236,6 +236,15 @@
+
+ cursor.set = 0;
+
++ if (softback_lines) {
++ if (y + softback_lines >= vc->vc_rows) {
++ mode = CM_ERASE;
++ ops->cursor_flash = 0;
++ return;
++ } else
++ y += softback_lines;
++ }
++
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+ src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+--- b/drivers/video/fbdev/core/fbcon_cw.c
++++ a/drivers/video/fbdev/core/fbcon_cw.c
+@@ -202,7 +202,7 @@
+ }
+
+ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg)
+- int fg, int bg)
+ {
+ struct fb_cursor cursor;
+ struct fbcon_ops *ops = info->fbcon_par;
+@@ -219,6 +219,15 @@
+
+ cursor.set = 0;
+
++ if (softback_lines) {
++ if (y + softback_lines >= vc->vc_rows) {
++ mode = CM_ERASE;
++ ops->cursor_flash = 0;
++ return;
++ } else
++ y += softback_lines;
++ }
++
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+ src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+--- b/drivers/video/fbdev/core/fbcon_ud.c
++++ a/drivers/video/fbdev/core/fbcon_ud.c
+@@ -249,7 +249,7 @@
+ }
+
+ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg)
+- int fg, int bg)
+ {
+ struct fb_cursor cursor;
+ struct fbcon_ops *ops = info->fbcon_par;
+@@ -267,6 +267,15 @@
+
+ cursor.set = 0;
+
++ if (softback_lines) {
++ if (y + softback_lines >= vc->vc_rows) {
++ mode = CM_ERASE;
++ ops->cursor_flash = 0;
++ return;
++ } else
++ y += softback_lines;
++ }
++
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+ src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
+--- b/drivers/video/fbdev/core/tileblit.c
++++ a/drivers/video/fbdev/core/tileblit.c
+@@ -80,7 +80,7 @@
+ }
+
+ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg)
+- int fg, int bg)
+ {
+ struct fb_tilecursor cursor;
+ int use_sw = vc->vc_cursor_type & CUR_SW;
diff --git a/0302-revert-fbcon-remove-no-op-fbcon_set_origin.patch b/0302-revert-fbcon-remove-no-op-fbcon_set_origin.patch
new file mode 100644
index 000000000000..6491c541e883
--- /dev/null
+++ b/0302-revert-fbcon-remove-no-op-fbcon_set_origin.patch
@@ -0,0 +1,31 @@
+--- b/drivers/video/fbdev/core/fbcon.c
++++ a/drivers/video/fbdev/core/fbcon.c
+@@ -163,6 +163,8 @@
+
+ #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+
++static int fbcon_set_origin(struct vc_data *);
++
+ static int fbcon_cursor_noblink;
+
+ #define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1)
+@@ -2633,6 +2635,11 @@
+ }
+ }
+
++static int fbcon_set_origin(struct vc_data *vc)
++{
++ return 0;
++}
++
+ void fbcon_suspended(struct fb_info *info)
+ {
+ struct vc_data *vc = NULL;
+@@ -3103,6 +3110,7 @@
+ .con_font_default = fbcon_set_def_font,
+ .con_font_copy = fbcon_copy_font,
+ .con_set_palette = fbcon_set_palette,
++ .con_set_origin = fbcon_set_origin,
+ .con_invert_region = fbcon_invert_region,
+ .con_screen_pos = fbcon_screen_pos,
+ .con_getxy = fbcon_getxy,
diff --git a/0303-revert-fbcon-remove-soft-scrollback-code.patch b/0303-revert-fbcon-remove-soft-scrollback-code.patch
new file mode 100644
index 000000000000..4f9735447f37
--- /dev/null
+++ b/0303-revert-fbcon-remove-soft-scrollback-code.patch
@@ -0,0 +1,500 @@
+--- b/drivers/video/fbdev/core/fbcon.c
++++ a/drivers/video/fbdev/core/fbcon.c
+@@ -122,6 +122,12 @@
+ /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
+ enums. */
+ static int logo_shown = FBCON_LOGO_CANSHOW;
++/* Software scrollback */
++static int fbcon_softback_size = 32768;
++static unsigned long softback_buf, softback_curr;
++static unsigned long softback_in;
++static unsigned long softback_top, softback_end;
++static int softback_lines;
+ /* console mappings */
+ static int first_fb_vc;
+ static int last_fb_vc = MAX_NR_CONSOLES - 1;
+@@ -161,6 +167,8 @@
+
+ static const struct consw fb_con;
+
++#define CM_SOFTBACK (8)
++
+ #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+
+ static int fbcon_set_origin(struct vc_data *);
+@@ -365,6 +373,18 @@
+ return color;
+ }
+
++static void fbcon_update_softback(struct vc_data *vc)
++{
++ int l = fbcon_softback_size / vc->vc_size_row;
++
++ if (l > 5)
++ softback_end = softback_buf + l * vc->vc_size_row;
++ else
++ /* Smaller scrollback makes no sense, and 0 would screw
++ the operation totally */
++ softback_top = 0;
++}
++
+ static void fb_flashcursor(struct work_struct *work)
+ {
+ struct fb_info *info = container_of(work, struct fb_info, queue);
+@@ -394,7 +414,7 @@
+ c = scr_readw((u16 *) vc->vc_pos);
+ mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
+ CM_ERASE : CM_DRAW;
++ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
+- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
+ get_color(vc, info, c, 0));
+ console_unlock();
+ }
+@@ -451,7 +471,13 @@
+ }
+
+ if (!strncmp(options, "scrollback:", 11)) {
++ options += 11;
++ if (*options) {
++ fbcon_softback_size = simple_strtoul(options, &options, 0);
++ if (*options == 'k' || *options == 'K') {
++ fbcon_softback_size *= 1024;
++ }
++ }
+- pr_warn("Ignoring scrollback size option\n");
+ continue;
+ }
+
+@@ -996,6 +1022,31 @@
+
+ set_blitting_type(vc, info);
+
++ if (info->fix.type != FB_TYPE_TEXT) {
++ if (fbcon_softback_size) {
++ if (!softback_buf) {
++ softback_buf =
++ (unsigned long)
++ kvmalloc(fbcon_softback_size,
++ GFP_KERNEL);
++ if (!softback_buf) {
++ fbcon_softback_size = 0;
++ softback_top = 0;
++ }
++ }
++ } else {
++ if (softback_buf) {
++ kvfree((void *) softback_buf);
++ softback_buf = 0;
++ softback_top = 0;
++ }
++ }
++ if (softback_buf)
++ softback_in = softback_top = softback_curr =
++ softback_buf;
++ softback_lines = 0;
++ }
++
+ /* Setup default font */
+ if (!p->fontdata && !vc->vc_font.data) {
+ if (!fontname[0] || !(font = find_font(fontname)))
+@@ -1169,6 +1220,9 @@
+ if (logo)
+ fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
+
++ if (vc == svc && softback_buf)
++ fbcon_update_softback(vc);
++
+ if (ops->rotate_font && ops->rotate_font(info, vc)) {
+ ops->rotate = FB_ROTATE_UR;
+ set_blitting_type(vc, info);
+@@ -1331,6 +1385,7 @@
+ {
+ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+ struct fbcon_ops *ops = info->fbcon_par;
++ int y;
+ int c = scr_readw((u16 *) vc->vc_pos);
+
+ ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+@@ -1334,11 +1389,19 @@ static void fbcon_cursor(struct vc_data
+ fbcon_add_cursor_timer(info);
+
+ ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
++ if (mode & CM_SOFTBACK) {
++ mode &= ~CM_SOFTBACK;
++ y = softback_lines;
++ } else {
++ if (softback_lines)
++ fbcon_set_origin(vc);
++ y = 0;
++ }
+
+ if (!ops->cursor)
+ return;
+
+- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
++ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
+ get_color(vc, info, c, 0));
+ }
+
+@@ -1416,6 +1479,8 @@
+
+ if (con_is_visible(vc)) {
+ update_screen(vc);
++ if (softback_buf)
++ fbcon_update_softback(vc);
+ }
+ }
+
+@@ -1553,6 +1618,99 @@
+ scrollback_current = 0;
+ }
+
++static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
++ long delta)
++{
++ int count = vc->vc_rows;
++ unsigned short *d, *s;
++ unsigned long n;
++ int line = 0;
++
++ d = (u16 *) softback_curr;
++ if (d == (u16 *) softback_in)
++ d = (u16 *) vc->vc_origin;
++ n = softback_curr + delta * vc->vc_size_row;
++ softback_lines -= delta;
++ if (delta < 0) {
++ if (softback_curr < softback_top && n < softback_buf) {
++ n += softback_end - softback_buf;
++ if (n < softback_top) {
++ softback_lines -=
++ (softback_top - n) / vc->vc_size_row;
++ n = softback_top;
++ }
++ } else if (softback_curr >= softback_top
++ && n < softback_top) {
++ softback_lines -=
++ (softback_top - n) / vc->vc_size_row;
++ n = softback_top;
++ }
++ } else {
++ if (softback_curr > softback_in && n >= softback_end) {
++ n += softback_buf - softback_end;
++ if (n > softback_in) {
++ n = softback_in;
++ softback_lines = 0;
++ }
++ } else if (softback_curr <= softback_in && n > softback_in) {
++ n = softback_in;
++ softback_lines = 0;
++ }
++ }
++ if (n == softback_curr)
++ return;
++ softback_curr = n;
++ s = (u16 *) softback_curr;
++ if (s == (u16 *) softback_in)
++ s = (u16 *) vc->vc_origin;
++ while (count--) {
++ unsigned short *start;
++ unsigned short *le;
++ unsigned short c;
++ int x = 0;
++ unsigned short attr = 1;
++
++ start = s;
++ le = advance_row(s, 1);
++ do {
++ c = scr_readw(s);
++ if (attr != (c & 0xff00)) {
++ attr = c & 0xff00;
++ if (s > start) {
++ fbcon_putcs(vc, start, s - start,
++ line, x);
++ x += s - start;
++ start = s;
++ }
++ }
++ if (c == scr_readw(d)) {
++ if (s > start) {
++ fbcon_putcs(vc, start, s - start,
++ line, x);
++ x += s - start + 1;
++ start = s + 1;
++ } else {
++ x++;
++ start++;
++ }
++ }
++ s++;
++ d++;
++ } while (s < le);
++ if (s > start)
++ fbcon_putcs(vc, start, s - start, line, x);
++ line++;
++ if (d == (u16 *) softback_end)
++ d = (u16 *) softback_buf;
++ if (d == (u16 *) softback_in)
++ d = (u16 *) vc->vc_origin;
++ if (s == (u16 *) softback_end)
++ s = (u16 *) softback_buf;
++ if (s == (u16 *) softback_in)
++ s = (u16 *) vc->vc_origin;
++ }
++}
++
+ static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
+ int line, int count, int dy)
+ {
+@@ -1692,6 +1850,31 @@
+ }
+ }
+
++static inline void fbcon_softback_note(struct vc_data *vc, int t,
++ int count)
++{
++ unsigned short *p;
++
++ if (vc->vc_num != fg_console)
++ return;
++ p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
++
++ while (count) {
++ scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
++ count--;
++ p = advance_row(p, 1);
++ softback_in += vc->vc_size_row;
++ if (softback_in == softback_end)
++ softback_in = softback_buf;
++ if (softback_in == softback_top) {
++ softback_top += vc->vc_size_row;
++ if (softback_top == softback_end)
++ softback_top = softback_buf;
++ }
++ }
++ softback_curr = softback_in;
++}
++
+ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+ enum con_scroll dir, unsigned int count)
+ {
+@@ -1714,6 +1897,8 @@
+ case SM_UP:
+ if (count > vc->vc_rows) /* Maximum realistic size */
+ count = vc->vc_rows;
++ if (softback_top)
++ fbcon_softback_note(vc, t, count);
+ if (logo_shown >= 0)
+ goto redraw_up;
+ switch (p->scrollmode) {
+@@ -2084,6 +2269,14 @@
+ info = registered_fb[con2fb_map[vc->vc_num]];
+ ops = info->fbcon_par;
+
++ if (softback_top) {
++ if (softback_lines)
++ fbcon_set_origin(vc);
++ softback_top = softback_curr = softback_in = softback_buf;
++ softback_lines = 0;
++ fbcon_update_softback(vc);
++ }
++
+ if (logo_shown >= 0) {
+ struct vc_data *conp2 = vc_cons[logo_shown].d;
+
+@@ -2407,6 +2600,9 @@
+ int cnt;
+ char *old_data = NULL;
+
++ if (con_is_visible(vc) && softback_lines)
++ fbcon_set_origin(vc);
++
+ resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
+ if (p->userfont)
+ old_data = vc->vc_font.data;
+@@ -2432,6 +2628,8 @@
+ cols /= w;
+ rows /= h;
+ vc_resize(vc, cols, rows);
++ if (con_is_visible(vc) && softback_buf)
++ fbcon_update_softback(vc);
+ } else if (con_is_visible(vc)
+ && vc->vc_mode == KD_TEXT) {
+ fbcon_clear_margins(vc, 0);
+@@ -2590,7 +2788,19 @@
+
+ static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
+ {
++ unsigned long p;
++ int line;
++
++ if (vc->vc_num != fg_console || !softback_lines)
++ return (u16 *) (vc->vc_origin + offset);
++ line = offset / vc->vc_size_row;
++ if (line >= softback_lines)
++ return (u16 *) (vc->vc_origin + offset -
++ softback_lines * vc->vc_size_row);
++ p = softback_curr + offset;
++ if (p >= softback_end)
++ p += softback_buf - softback_end;
++ return (u16 *) p;
+- return (u16 *) (vc->vc_origin + offset);
+ }
+
+ static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
+@@ -2604,7 +2814,22 @@
+
+ x = offset % vc->vc_cols;
+ y = offset / vc->vc_cols;
++ if (vc->vc_num == fg_console)
++ y += softback_lines;
+ ret = pos + (vc->vc_cols - x) * 2;
++ } else if (vc->vc_num == fg_console && softback_lines) {
++ unsigned long offset = pos - softback_curr;
++
++ if (pos < softback_curr)
++ offset += softback_end - softback_buf;
++ offset /= 2;
++ x = offset % vc->vc_cols;
++ y = offset / vc->vc_cols;
++ ret = pos + (vc->vc_cols - x) * 2;
++ if (ret == softback_end)
++ ret = softback_buf;
++ if (ret == softback_in)
++ ret = vc->vc_origin;
+ } else {
+ /* Should not happen */
+ x = y = 0;
+@@ -2632,11 +2857,106 @@
+ a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
+ (((a) & 0x0700) << 4);
+ scr_writew(a, p++);
++ if (p == (u16 *) softback_end)
++ p = (u16 *) softback_buf;
++ if (p == (u16 *) softback_in)
++ p = (u16 *) vc->vc_origin;
++ }
++}
++
++static void fbcon_scrolldelta(struct vc_data *vc, int lines)
++{
++ struct fb_info *info = registered_fb[con2fb_map[fg_console]];
++ struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_display *disp = &fb_display[fg_console];
++ int offset, limit, scrollback_old;
++
++ if (softback_top) {
++ if (vc->vc_num != fg_console)
++ return;
++ if (vc->vc_mode != KD_TEXT || !lines)
++ return;
++ if (logo_shown >= 0) {
++ struct vc_data *conp2 = vc_cons[logo_shown].d;
++
++ if (conp2->vc_top == logo_lines
++ && conp2->vc_bottom == conp2->vc_rows)
++ conp2->vc_top = 0;
++ if (logo_shown == vc->vc_num) {
++ unsigned long p, q;
++ int i;
++
++ p = softback_in;
++ q = vc->vc_origin +
++ logo_lines * vc->vc_size_row;
++ for (i = 0; i < logo_lines; i++) {
++ if (p == softback_top)
++ break;
++ if (p == softback_buf)
++ p = softback_end;
++ p -= vc->vc_size_row;
++ q -= vc->vc_size_row;
++ scr_memcpyw((u16 *) q, (u16 *) p,
++ vc->vc_size_row);
++ }
++ softback_in = softback_curr = p;
++ update_region(vc, vc->vc_origin,
++ logo_lines * vc->vc_cols);
++ }
++ logo_shown = FBCON_LOGO_CANSHOW;
++ }
++ fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
++ fbcon_redraw_softback(vc, disp, lines);
++ fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
++ return;
+ }
++
++ if (!scrollback_phys_max)
++ return;
++
++ scrollback_old = scrollback_current;
++ scrollback_current -= lines;
++ if (scrollback_current < 0)
++ scrollback_current = 0;
++ else if (scrollback_current > scrollback_max)
++ scrollback_current = scrollback_max;
++ if (scrollback_current == scrollback_old)
++ return;
++
++ if (fbcon_is_inactive(vc, info))
++ return;
++
++ fbcon_cursor(vc, CM_ERASE);
++
++ offset = disp->yscroll - scrollback_current;
++ limit = disp->vrows;
++ switch (disp->scrollmode) {
++ case SCROLL_WRAP_MOVE:
++ info->var.vmode |= FB_VMODE_YWRAP;
++ break;
++ case SCROLL_PAN_MOVE:
++ case SCROLL_PAN_REDRAW:
++ limit -= vc->vc_rows;
++ info->var.vmode &= ~FB_VMODE_YWRAP;
++ break;
++ }
++ if (offset < 0)
++ offset += limit;
++ else if (offset >= limit)
++ offset -= limit;
++
++ ops->var.xoffset = 0;
++ ops->var.yoffset = offset * vc->vc_font.height;
++ ops->update_start(info);
++
++ if (!scrollback_current)
++ fbcon_cursor(vc, CM_DRAW);
+ }
+
+ static int fbcon_set_origin(struct vc_data *vc)
+ {
++ if (softback_lines)
++ fbcon_scrolldelta(vc, softback_lines);
+ return 0;
+ }
+
+@@ -2700,6 +3020,8 @@
+
+ fbcon_set_palette(vc, color_table);
+ update_screen(vc);
++ if (softback_buf)
++ fbcon_update_softback(vc);
+ }
+ }
+
+@@ -3110,6 +3432,7 @@
+ .con_font_default = fbcon_set_def_font,
+ .con_font_copy = fbcon_copy_font,
+ .con_set_palette = fbcon_set_palette,
++ .con_scrolldelta = fbcon_scrolldelta,
+ .con_set_origin = fbcon_set_origin,
+ .con_invert_region = fbcon_invert_region,
+ .con_screen_pos = fbcon_screen_pos,
+@@ -3344,6 +3667,9 @@
+ }
+ #endif
+
++ kvfree((void *)softback_buf);
++ softback_buf = 0UL;
++
+ for_each_registered_fb(i) {
+ int pending = 0;
+
diff --git a/0401-bootsplash.patch b/0401-bootsplash.patch
new file mode 100644
index 000000000000..d5835e5ca12b
--- /dev/null
+++ b/0401-bootsplash.patch
@@ -0,0 +1,746 @@
+diff --git a/MAINTAINERS b/MAINTAINERS
+index a74227ad082e..b5633b56391e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2705,6 +2705,14 @@ S: Supported
+ F: drivers/net/bonding/
+ F: include/uapi/linux/if_bonding.h
+
++BOOTSPLASH
++M: Max Staudt <mstaudt@suse.de>
++L: linux-fbdev@vger.kernel.org
++S: Maintained
++F: drivers/video/fbdev/core/bootsplash*.*
++F: drivers/video/fbdev/core/dummycon.c
++F: include/linux/bootsplash.h
++
+ BPF (Safe dynamic programs and tools)
+ M: Alexei Starovoitov <ast@kernel.org>
+ M: Daniel Borkmann <daniel@iogearbox.net>
+diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
+index 7f1f1fbcef9e..f3ff976266fe 100644
+--- a/drivers/video/console/Kconfig
++++ b/drivers/video/console/Kconfig
+@@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
+ such that other users of the framebuffer will remain normally
+ oriented.
+
++config BOOTSPLASH
++ bool "Bootup splash screen"
++ depends on FRAMEBUFFER_CONSOLE
++ help
++ This option enables the Linux bootsplash screen.
++
++ The bootsplash is a full-screen logo or animation indicating a
++ booting system. It replaces the classic scrolling text with a
++ graphical alternative, similar to other systems.
++
++ Since this is technically implemented as a hook on top of fbcon,
++ it can only work if the FRAMEBUFFER_CONSOLE is enabled and a
++ framebuffer driver is active. Thus, to get a text-free boot,
++ the system needs to boot with vesafb, efifb, or similar.
++
++ Once built into the kernel, the bootsplash needs to be enabled
++ with bootsplash.enabled=1 and a splash file needs to be supplied.
++
++ Further documentation can be found in:
++ Documentation/fb/bootsplash.txt
++
++ If unsure, say N.
++ This is typically used by distributors and system integrators.
++
+ config STI_CONSOLE
+ bool "STI text console"
+ depends on PARISC
+diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
+index 73493bbd7a15..66895321928e 100644
+--- a/drivers/video/fbdev/core/Makefile
++++ b/drivers/video/fbdev/core/Makefile
+@@ -29,3 +29,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
+ obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
+ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
+ obj-$(CONFIG_FB_DDC) += fb_ddc.o
++
++obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
++ dummyblit.o
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+new file mode 100644
+index 000000000000..e449755af268
+--- /dev/null
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -0,0 +1,294 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Main file: Glue code, workers, timer, PM, kernel and userland API)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#define pr_fmt(fmt) "bootsplash: " fmt
++
++
++#include <linux/atomic.h>
++#include <linux/bootsplash.h>
++#include <linux/console.h>
++#include <linux/device.h> /* dev_warn() */
++#include <linux/fb.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/jiffies.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/platform_device.h>
++#include <linux/printk.h>
++#include <linux/selection.h> /* console_blanked */
++#include <linux/stringify.h>
++#include <linux/types.h>
++#include <linux/vmalloc.h>
++#include <linux/vt_kern.h>
++#include <linux/workqueue.h>
++
++#include "bootsplash_internal.h"
++
++
++/*
++ * We only have one splash screen, so let's keep a single
++ * instance of the internal state.
++ */
++static struct splash_priv splash_state;
++
++
++static void splash_callback_redraw_vc(struct work_struct *ignored)
++{
++ if (console_blanked)
++ return;
++
++ console_lock();
++ if (vc_cons[fg_console].d)
++ update_screen(vc_cons[fg_console].d);
++ console_unlock();
++}
++
++
++static bool is_fb_compatible(const struct fb_info *info)
++{
++ if (!(info->flags & FBINFO_BE_MATH)
++ != !fb_be_math((struct fb_info *)info)) {
++ dev_warn(info->device,
++ "Can't draw on foreign endianness framebuffer.\n");
++
++ return false;
++ }
++
++ if (info->flags & FBINFO_MISC_TILEBLITTING) {
++ dev_warn(info->device,
++ "Can't draw splash on tiling framebuffer.\n");
++
++ return false;
++ }
++
++ if (info->fix.type != FB_TYPE_PACKED_PIXELS
++ || (info->fix.visual != FB_VISUAL_TRUECOLOR
++ && info->fix.visual != FB_VISUAL_DIRECTCOLOR)) {
++ dev_warn(info->device,
++ "Can't draw splash on non-packed or non-truecolor framebuffer.\n");
++
++ dev_warn(info->device,
++ " type: %u visual: %u\n",
++ info->fix.type, info->fix.visual);
++
++ return false;
++ }
++
++ if (info->var.bits_per_pixel != 16
++ && info->var.bits_per_pixel != 24
++ && info->var.bits_per_pixel != 32) {
++ dev_warn(info->device,
++ "We only support drawing on framebuffers with 16, 24, or 32 bpp, not %d.\n",
++ info->var.bits_per_pixel);
++
++ return false;
++ }
++
++ return true;
++}
++
++
++/*
++ * Called by fbcon_switch() when an instance is activated or refreshed.
++ */
++void bootsplash_render_full(struct fb_info *info)
++{
++ if (!is_fb_compatible(info))
++ return;
++
++ bootsplash_do_render_background(info);
++}
++
++
++/*
++ * External status enquiry and on/off switch
++ */
++bool bootsplash_would_render_now(void)
++{
++ return !oops_in_progress
++ && !console_blanked
++ && bootsplash_is_enabled();
++}
++
++bool bootsplash_is_enabled(void)
++{
++ bool was_enabled;
++
++ /* Make sure we have the newest state */
++ smp_rmb();
++
++ was_enabled = test_bit(0, &splash_state.enabled);
++
++ return was_enabled;
++}
++
++void bootsplash_disable(void)
++{
++ int was_enabled;
++
++ was_enabled = test_and_clear_bit(0, &splash_state.enabled);
++
++ if (was_enabled) {
++ if (oops_in_progress) {
++ /* Redraw screen now so we can see a panic */
++ if (vc_cons[fg_console].d)
++ update_screen(vc_cons[fg_console].d);
++ } else {
++ /* No urgency, redraw at next opportunity */
++ schedule_work(&splash_state.work_redraw_vc);
++ }
++ }
++}
++
++void bootsplash_enable(void)
++{
++ bool was_enabled;
++
++ if (oops_in_progress)
++ return;
++
++ was_enabled = test_and_set_bit(0, &splash_state.enabled);
++
++ if (!was_enabled)
++ schedule_work(&splash_state.work_redraw_vc);
++}
++
++
++/*
++ * Userland API via platform device in sysfs
++ */
++static ssize_t splash_show_enabled(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%d\n", bootsplash_is_enabled());
++}
++
++static ssize_t splash_store_enabled(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ bool enable;
++ int err;
++
++ if (!buf || !count)
++ return -EFAULT;
++
++ err = kstrtobool(buf, &enable);
++ if (err)
++ return err;
++
++ if (enable)
++ bootsplash_enable();
++ else
++ bootsplash_disable();
++
++ return count;
++}
++
++static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
++
++
++static struct attribute *splash_dev_attrs[] = {
++ &dev_attr_enabled.attr,
++ NULL
++};
++
++ATTRIBUTE_GROUPS(splash_dev);
++
++
++
++
++/*
++ * Power management fixup via platform device
++ *
++ * When the system is woken from sleep or restored after hibernating, we
++ * cannot expect the screen contents to still be present in video RAM.
++ * Thus, we have to redraw the splash if we're currently active.
++ */
++static int splash_resume(struct device *device)
++{
++ if (bootsplash_would_render_now())
++ schedule_work(&splash_state.work_redraw_vc);
++
++ return 0;
++}
++
++static int splash_suspend(struct device *device)
++{
++ cancel_work_sync(&splash_state.work_redraw_vc);
++
++ return 0;
++}
++
++
++static const struct dev_pm_ops splash_pm_ops = {
++ .thaw = splash_resume,
++ .restore = splash_resume,
++ .resume = splash_resume,
++ .suspend = splash_suspend,
++ .freeze = splash_suspend,
++};
++
++static struct platform_driver splash_driver = {
++ .driver = {
++ .name = "bootsplash",
++ .pm = &splash_pm_ops,
++ },
++};
++
++
++/*
++ * Main init
++ */
++void bootsplash_init(void)
++{
++ int ret;
++
++ /* Initialized already? */
++ if (splash_state.splash_device)
++ return;
++
++
++ /* Register platform device to export user API */
++ ret = platform_driver_register(&splash_driver);
++ if (ret) {
++ pr_err("platform_driver_register() failed: %d\n", ret);
++ goto err;
++ }
++
++ splash_state.splash_device
++ = platform_device_alloc("bootsplash", 0);
++
++ if (!splash_state.splash_device)
++ goto err_driver;
++
++ splash_state.splash_device->dev.groups = splash_dev_groups;
++
++ ret = platform_device_add(splash_state.splash_device);
++ if (ret) {
++ pr_err("platform_device_add() failed: %d\n", ret);
++ goto err_device;
++ }
++
++
++ INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
++
++ return;
++
++err_device:
++ platform_device_put(splash_state.splash_device);
++ splash_state.splash_device = NULL;
++err_driver:
++ platform_driver_unregister(&splash_driver);
++err:
++ pr_err("Failed to initialize.\n");
++}
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+new file mode 100644
+index 000000000000..b11da5cb90bf
+--- /dev/null
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -0,0 +1,55 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Internal data structures used at runtime)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#ifndef __BOOTSPLASH_INTERNAL_H
++#define __BOOTSPLASH_INTERNAL_H
++
++
++#include <linux/types.h>
++#include <linux/fb.h>
++#include <linux/kernel.h>
++#include <linux/mutex.h>
++#include <linux/spinlock.h>
++
++
++/*
++ * Runtime types
++ */
++struct splash_priv {
++ /*
++ * Enabled/disabled state, to be used with atomic bit operations.
++ * Bit 0: 0 = Splash hidden
++ * 1 = Splash shown
++ *
++ * Note: fbcon.c uses this twice, by calling
++ * bootsplash_would_render_now() in set_blitting_type() and
++ * in fbcon_switch().
++ * This is racy, but eventually consistent: Turning the
++ * splash on/off will cause a redraw, which calls
++ * fbcon_switch(), which calls set_blitting_type().
++ * So the last on/off toggle will make things consistent.
++ */
++ unsigned long enabled;
++
++ /* Our gateway to userland via sysfs */
++ struct platform_device *splash_device;
++
++ struct work_struct work_redraw_vc;
++};
++
++
++
++/*
++ * Rendering functions
++ */
++void bootsplash_do_render_background(struct fb_info *info);
++
++#endif
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+new file mode 100644
+index 000000000000..4d7e0117f653
+--- /dev/null
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -0,0 +1,93 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Rendering functions)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#define pr_fmt(fmt) "bootsplash: " fmt
++
++
++#include <linux/bootsplash.h>
++#include <linux/fb.h>
++#include <linux/kernel.h>
++#include <linux/printk.h>
++#include <linux/types.h>
++
++#include "bootsplash_internal.h"
++
++
++
++
++/*
++ * Rendering: Internal drawing routines
++ */
++
++
++/*
++ * Pack pixel into target format and do Big/Little Endian handling.
++ * This would be a good place to handle endianness conversion if necessary.
++ */
++static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
++ u8 red, u8 green, u8 blue)
++{
++ u32 dstpix;
++
++ /* Quantize pixel */
++ red = red >> (8 - dst_var->red.length);
++ green = green >> (8 - dst_var->green.length);
++ blue = blue >> (8 - dst_var->blue.length);
++
++ /* Pack pixel */
++ dstpix = red << (dst_var->red.offset)
++ | green << (dst_var->green.offset)
++ | blue << (dst_var->blue.offset);
++
++ /*
++ * Move packed pixel to the beginning of the memory cell,
++ * so we can memcpy() it out easily
++ */
++#ifdef __BIG_ENDIAN
++ switch (dst_var->bits_per_pixel) {
++ case 16:
++ dstpix <<= 16;
++ break;
++ case 24:
++ dstpix <<= 8;
++ break;
++ case 32:
++ break;
++ }
++#else
++ /* This is intrinsically unnecessary on Little Endian */
++#endif
++
++ return dstpix;
++}
++
++
++void bootsplash_do_render_background(struct fb_info *info)
++{
++ unsigned int x, y;
++ u32 dstpix;
++ u32 dst_octpp = info->var.bits_per_pixel / 8;
++
++ dstpix = pack_pixel(&info->var,
++ 0,
++ 0,
++ 0);
++
++ for (y = 0; y < info->var.yres_virtual; y++) {
++ u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
++
++ for (x = 0; x < info->var.xres_virtual; x++) {
++ memcpy(dstline, &dstpix, dst_octpp);
++
++ dstline += dst_octpp;
++ }
++ }
++}
+diff --git a/drivers/video/fbdev/core/dummyblit.c b/drivers/video/fbdev/core/dummyblit.c
+new file mode 100644
+index 000000000000..8c22ff92ce24
+--- /dev/null
++++ b/drivers/video/fbdev/core/dummyblit.c
+@@ -0,0 +1,89 @@
++/*
++ * linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * These functions are used in place of blitblit/tileblit to suppress
++ * fbcon's text output while a splash is shown.
++ *
++ * Only suppressing actual rendering keeps the text buffer in the VC layer
++ * intact and makes it easy to switch back from the bootsplash to a full
++ * text console with a simple redraw (with the original functions in place).
++ *
++ * Based on linux/drivers/video/fbdev/core/bitblit.c
++ * and linux/drivers/video/fbdev/core/tileblit.c
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#include <linux/module.h>
++#include <linux/fb.h>
++#include <linux/vt_kern.h>
++#include <linux/console.h>
++#include <asm/types.h>
++#include "fbcon.h"
++
++static void dummy_bmove(struct vc_data *vc, struct fb_info *info, int sy,
++ int sx, int dy, int dx, int height, int width)
++{
++ ;
++}
++
++static void dummy_clear(struct vc_data *vc, struct fb_info *info, int sy,
++ int sx, int height, int width)
++{
++ ;
++}
++
++static void dummy_putcs(struct vc_data *vc, struct fb_info *info,
++ const unsigned short *s, int count, int yy, int xx,
++ int fg, int bg)
++{
++ ;
++}
++
++static void dummy_clear_margins(struct vc_data *vc, struct fb_info *info,
++ int color, int bottom_only)
++{
++ ;
++}
++
++static void dummy_cursor(struct vc_data *vc, struct fb_info *info, int mode,
++ int softback_lines, int fg, int bg)
++{
++ ;
++}
++
++static int dummy_update_start(struct fb_info *info)
++{
++ /*
++ * Copied from bitblit.c and tileblit.c
++ *
++ * As of Linux 4.12, nobody seems to care about our return value.
++ */
++ struct fbcon_ops *ops = info->fbcon_par;
++ int err;
++
++ err = fb_pan_display(info, &ops->var);
++ ops->var.xoffset = info->var.xoffset;
++ ops->var.yoffset = info->var.yoffset;
++ ops->var.vmode = info->var.vmode;
++ return err;
++}
++
++void fbcon_set_dummyops(struct fbcon_ops *ops)
++{
++ ops->bmove = dummy_bmove;
++ ops->clear = dummy_clear;
++ ops->putcs = dummy_putcs;
++ ops->clear_margins = dummy_clear_margins;
++ ops->cursor = dummy_cursor;
++ ops->update_start = dummy_update_start;
++ ops->rotate_font = NULL;
++}
++EXPORT_SYMBOL_GPL(fbcon_set_dummyops);
++
++MODULE_AUTHOR("Max Staudt <mstaudt@suse.de>");
++MODULE_DESCRIPTION("Dummy Blitting Operation");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 04612f938bab..9a39a6fcfe98 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -80,6 +80,7 @@
+ #include <asm/irq.h>
+
+ #include "fbcon.h"
++#include <linux/bootsplash.h>
+
+ #ifdef FBCONDEBUG
+ # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+@@ -542,6 +543,8 @@ static int do_fbcon_takeover(int show_logo)
+ for (i = first_fb_vc; i <= last_fb_vc; i++)
+ con2fb_map[i] = info_idx;
+
++ bootsplash_init();
++
+ err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
+ fbcon_is_default);
+
+@@ -661,6 +664,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
+ else {
+ fbcon_set_rotation(info);
+ fbcon_set_bitops(ops);
++
++ if (bootsplash_would_render_now())
++ fbcon_set_dummyops(ops);
+ }
+ }
+
+@@ -683,6 +689,19 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
+ ops->p = &fb_display[vc->vc_num];
+ fbcon_set_rotation(info);
+ fbcon_set_bitops(ops);
++
++ /*
++ * Note:
++ * This is *eventually correct*.
++ * Setting the fbcon operations and drawing the splash happen at
++ * different points in time. If the splash is enabled/disabled
++ * in between, then bootsplash_{en,dis}able will schedule a
++ * redraw, which will again render the splash (or not) and set
++ * the correct fbcon ops.
++ * The last run will then be the right one.
++ */
++ if (bootsplash_would_render_now())
++ fbcon_set_dummyops(ops);
+ }
+
+ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+@@ -2184,6 +2203,9 @@ static int fbcon_switch(struct vc_data *vc)
+ info = registered_fb[con2fb_map[vc->vc_num]];
+ ops = info->fbcon_par;
+
++ if (bootsplash_would_render_now())
++ bootsplash_render_full(info);
++
+ if (softback_top) {
+ if (softback_lines)
+ fbcon_set_origin(vc);
+diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
+index 18f3ac144237..45f94347fe5e 100644
+--- a/drivers/video/fbdev/core/fbcon.h
++++ b/drivers/video/fbdev/core/fbcon.h
+@@ -214,6 +214,11 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
+ #define SCROLL_REDRAW 0x004
+ #define SCROLL_PAN_REDRAW 0x005
+
++#ifdef CONFIG_BOOTSPLASH
++extern void fbcon_set_dummyops(struct fbcon_ops *ops);
++#else /* CONFIG_BOOTSPLASH */
++#define fbcon_set_dummyops(x)
++#endif /* CONFIG_BOOTSPLASH */
+ #ifdef CONFIG_FB_TILEBLITTING
+ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
+ #endif
+diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
+new file mode 100644
+index 000000000000..c6dd0b43180d
+--- /dev/null
++++ b/include/linux/bootsplash.h
+@@ -0,0 +1,43 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#ifndef __LINUX_BOOTSPLASH_H
++#define __LINUX_BOOTSPLASH_H
++
++#include <linux/fb.h>
++
++
++#ifdef CONFIG_BOOTSPLASH
++
++extern void bootsplash_render_full(struct fb_info *info);
++
++extern bool bootsplash_would_render_now(void);
++
++extern bool bootsplash_is_enabled(void);
++extern void bootsplash_disable(void);
++extern void bootsplash_enable(void);
++
++extern void bootsplash_init(void);
++
++#else /* CONFIG_BOOTSPLASH */
++
++#define bootsplash_render_full(x)
++
++#define bootsplash_would_render_now() (false)
++
++#define bootsplash_is_enabled() (false)
++#define bootsplash_disable()
++#define bootsplash_enable()
++
++#define bootsplash_init()
++
++#endif /* CONFIG_BOOTSPLASH */
++
++
++#endif
diff --git a/0402-bootsplash.patch b/0402-bootsplash.patch
new file mode 100644
index 000000000000..92d62caa7031
--- /dev/null
+++ b/0402-bootsplash.patch
@@ -0,0 +1,669 @@
+diff --git a/MAINTAINERS b/MAINTAINERS
+index b5633b56391e..5c237445761e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2712,6 +2712,7 @@ S: Maintained
+ F: drivers/video/fbdev/core/bootsplash*.*
+ F: drivers/video/fbdev/core/dummycon.c
+ F: include/linux/bootsplash.h
++F: include/uapi/linux/bootsplash_file.h
+
+ BPF (Safe dynamic programs and tools)
+ M: Alexei Starovoitov <ast@kernel.org>
+diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
+index 66895321928e..6a8d1bab8a01 100644
+--- a/drivers/video/fbdev/core/Makefile
++++ b/drivers/video/fbdev/core/Makefile
+@@ -31,4 +31,4 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
+ obj-$(CONFIG_FB_DDC) += fb_ddc.o
+
+ obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
+- dummyblit.o
++ bootsplash_load.o dummyblit.o
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index e449755af268..843c5400fefc 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -32,6 +32,7 @@
+ #include <linux/workqueue.h>
+
+ #include "bootsplash_internal.h"
++#include "uapi/linux/bootsplash_file.h"
+
+
+ /*
+@@ -102,10 +103,17 @@ static bool is_fb_compatible(const struct fb_info *info)
+ */
+ void bootsplash_render_full(struct fb_info *info)
+ {
++ mutex_lock(&splash_state.data_lock);
++
+ if (!is_fb_compatible(info))
+- return;
++ goto out;
++
++ bootsplash_do_render_background(info, splash_state.file);
++
++ bootsplash_do_render_pictures(info, splash_state.file);
+
+- bootsplash_do_render_background(info);
++out:
++ mutex_unlock(&splash_state.data_lock);
+ }
+
+
+@@ -116,6 +124,7 @@ bool bootsplash_would_render_now(void)
+ {
+ return !oops_in_progress
+ && !console_blanked
++ && splash_state.file
+ && bootsplash_is_enabled();
+ }
+
+@@ -252,6 +261,7 @@ static struct platform_driver splash_driver = {
+ void bootsplash_init(void)
+ {
+ int ret;
++ struct splash_file_priv *fp;
+
+ /* Initialized already? */
+ if (splash_state.splash_device)
+@@ -280,8 +290,26 @@ void bootsplash_init(void)
+ }
+
+
++ mutex_init(&splash_state.data_lock);
++ set_bit(0, &splash_state.enabled);
++
+ INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
+
++
++ if (!splash_state.bootfile || !strlen(splash_state.bootfile))
++ return;
++
++ fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
++ splash_state.bootfile);
++
++ if (!fp)
++ goto err;
++
++ mutex_lock(&splash_state.data_lock);
++ splash_state.splash_fb = NULL;
++ splash_state.file = fp;
++ mutex_unlock(&splash_state.data_lock);
++
+ return;
+
+ err_device:
+@@ -292,3 +320,7 @@ void bootsplash_init(void)
+ err:
+ pr_err("Failed to initialize.\n");
+ }
++
++
++module_param_named(bootfile, splash_state.bootfile, charp, 0444);
++MODULE_PARM_DESC(bootfile, "Bootsplash file to load on boot");
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+index b11da5cb90bf..71e2a27ac0b8 100644
+--- a/drivers/video/fbdev/core/bootsplash_internal.h
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -15,15 +15,43 @@
+
+ #include <linux/types.h>
+ #include <linux/fb.h>
++#include <linux/firmware.h>
+ #include <linux/kernel.h>
+ #include <linux/mutex.h>
+ #include <linux/spinlock.h>
+
++#include "uapi/linux/bootsplash_file.h"
++
+
+ /*
+ * Runtime types
+ */
++struct splash_blob_priv {
++ struct splash_blob_header *blob_header;
++ const void *data;
++};
++
++
++struct splash_pic_priv {
++ const struct splash_pic_header *pic_header;
++
++ struct splash_blob_priv *blobs;
++ u16 blobs_loaded;
++};
++
++
++struct splash_file_priv {
++ const struct firmware *fw;
++ const struct splash_file_header *header;
++
++ struct splash_pic_priv *pics;
++};
++
++
+ struct splash_priv {
++ /* Bootup and runtime state */
++ char *bootfile;
++
+ /*
+ * Enabled/disabled state, to be used with atomic bit operations.
+ * Bit 0: 0 = Splash hidden
+@@ -43,6 +71,13 @@ struct splash_priv {
+ struct platform_device *splash_device;
+
+ struct work_struct work_redraw_vc;
++
++ /* Splash data structures including lock for everything below */
++ struct mutex data_lock;
++
++ struct fb_info *splash_fb;
++
++ struct splash_file_priv *file;
+ };
+
+
+@@ -50,6 +85,14 @@ struct splash_priv {
+ /*
+ * Rendering functions
+ */
+-void bootsplash_do_render_background(struct fb_info *info);
++void bootsplash_do_render_background(struct fb_info *info,
++ const struct splash_file_priv *fp);
++void bootsplash_do_render_pictures(struct fb_info *info,
++ const struct splash_file_priv *fp);
++
++
++void bootsplash_free_file(struct splash_file_priv *fp);
++struct splash_file_priv *bootsplash_load_firmware(struct device *device,
++ const char *path);
+
+ #endif
+diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
+new file mode 100644
+index 000000000000..fd807571ab7d
+--- /dev/null
++++ b/drivers/video/fbdev/core/bootsplash_load.c
+@@ -0,0 +1,225 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Loading and freeing functions)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#define pr_fmt(fmt) "bootsplash: " fmt
++
++
++#include <linux/bootsplash.h>
++#include <linux/fb.h>
++#include <linux/firmware.h>
++#include <linux/kernel.h>
++#include <linux/mutex.h>
++#include <linux/printk.h>
++#include <linux/types.h>
++#include <linux/vmalloc.h>
++
++#include "bootsplash_internal.h"
++#include "uapi/linux/bootsplash_file.h"
++
++
++
++
++/*
++ * Free all vmalloc()'d resources describing a splash file.
++ */
++void bootsplash_free_file(struct splash_file_priv *fp)
++{
++ if (!fp)
++ return;
++
++ if (fp->pics) {
++ unsigned int i;
++
++ for (i = 0; i < fp->header->num_pics; i++) {
++ struct splash_pic_priv *pp = &fp->pics[i];
++
++ if (pp->blobs)
++ vfree(pp->blobs);
++ }
++
++ vfree(fp->pics);
++ }
++
++ release_firmware(fp->fw);
++ vfree(fp);
++}
++
++
++
++
++/*
++ * Load a splash screen from a "firmware" file.
++ *
++ * Parsing, and sanity checks.
++ */
++#ifdef __BIG_ENDIAN
++ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_BE
++#else
++ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_LE
++#endif
++
++struct splash_file_priv *bootsplash_load_firmware(struct device *device,
++ const char *path)
++{
++ const struct firmware *fw;
++ struct splash_file_priv *fp;
++ unsigned int i;
++ const u8 *walker;
++
++ if (request_firmware(&fw, path, device))
++ return NULL;
++
++ if (fw->size < sizeof(struct splash_file_header)
++ || memcmp(fw->data, BOOTSPLASH_MAGIC, sizeof(fp->header->id))) {
++ pr_err("Not a bootsplash file.\n");
++
++ release_firmware(fw);
++ return NULL;
++ }
++
++ fp = vzalloc(sizeof(struct splash_file_priv));
++ if (!fp) {
++ release_firmware(fw);
++ return NULL;
++ }
++
++ pr_info("Loading splash file (%li bytes)\n", fw->size);
++
++ fp->fw = fw;
++ fp->header = (struct splash_file_header *)fw->data;
++
++ /* Sanity checks */
++ if (fp->header->version != BOOTSPLASH_VERSION) {
++ pr_err("Loaded v%d file, but we only support version %d\n",
++ fp->header->version,
++ BOOTSPLASH_VERSION);
++
++ goto err;
++ }
++
++ if (fw->size < sizeof(struct splash_file_header)
++ + fp->header->num_pics
++ * sizeof(struct splash_pic_header)
++ + fp->header->num_blobs
++ * sizeof(struct splash_blob_header)) {
++ pr_err("File incomplete.\n");
++
++ goto err;
++ }
++
++ /* Read picture headers */
++ if (fp->header->num_pics) {
++ fp->pics = vzalloc(fp->header->num_pics
++ * sizeof(struct splash_pic_priv));
++ if (!fp->pics)
++ goto err;
++ }
++
++ walker = fw->data + sizeof(struct splash_file_header);
++ for (i = 0; i < fp->header->num_pics; i++) {
++ struct splash_pic_priv *pp = &fp->pics[i];
++ struct splash_pic_header *ph = (void *)walker;
++
++ pr_debug("Picture %u: Size %ux%u\n", i, ph->width, ph->height);
++
++ if (ph->num_blobs < 1) {
++ pr_err("Picture %u: Zero blobs? Aborting load.\n", i);
++ goto err;
++ }
++
++ pp->pic_header = ph;
++ pp->blobs = vzalloc(ph->num_blobs
++ * sizeof(struct splash_blob_priv));
++ if (!pp->blobs)
++ goto err;
++
++ walker += sizeof(struct splash_pic_header);
++ }
++
++ /* Read blob headers */
++ for (i = 0; i < fp->header->num_blobs; i++) {
++ struct splash_blob_header *bh = (void *)walker;
++ struct splash_pic_priv *pp;
++
++ if (walker + sizeof(struct splash_blob_header)
++ > fw->data + fw->size)
++ goto err;
++
++ walker += sizeof(struct splash_blob_header);
++
++ if (walker + bh->length > fw->data + fw->size)
++ goto err;
++
++ if (bh->picture_id >= fp->header->num_pics)
++ goto nextblob;
++
++ pp = &fp->pics[bh->picture_id];
++
++ pr_debug("Blob %u, pic %u, blobs_loaded %u, num_blobs %u.\n",
++ i, bh->picture_id,
++ pp->blobs_loaded, pp->pic_header->num_blobs);
++
++ if (pp->blobs_loaded >= pp->pic_header->num_blobs)
++ goto nextblob;
++
++ switch (bh->type) {
++ case 0:
++ /* Raw 24-bit packed pixels */
++ if (bh->length != pp->pic_header->width
++ * pp->pic_header->height * 3) {
++ pr_err("Blob %u, type 1: Length doesn't match picture.\n",
++ i);
++
++ goto err;
++ }
++ break;
++ default:
++ pr_warn("Blob %u, unknown type %u.\n", i, bh->type);
++ goto nextblob;
++ }
++
++ pp->blobs[pp->blobs_loaded].blob_header = bh;
++ pp->blobs[pp->blobs_loaded].data = walker;
++ pp->blobs_loaded++;
++
++nextblob:
++ walker += bh->length;
++ if (bh->length % 16)
++ walker += 16 - (bh->length % 16);
++ }
++
++ if (walker != fw->data + fw->size)
++ pr_warn("Trailing data in splash file.\n");
++
++ /* Walk over pictures and ensure all blob slots are filled */
++ for (i = 0; i < fp->header->num_pics; i++) {
++ struct splash_pic_priv *pp = &fp->pics[i];
++
++ if (pp->blobs_loaded != pp->pic_header->num_blobs) {
++ pr_err("Picture %u doesn't have all blob slots filled.\n",
++ i);
++
++ goto err;
++ }
++ }
++
++ pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
++ fw->size,
++ fp->header->num_pics,
++ fp->header->num_blobs);
++
++ return fp;
++
++
++err:
++ bootsplash_free_file(fp);
++ return NULL;
++}
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 4d7e0117f653..2ae36949d0e3 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -19,6 +19,7 @@
+ #include <linux/types.h>
+
+ #include "bootsplash_internal.h"
++#include "uapi/linux/bootsplash_file.h"
+
+
+
+@@ -70,16 +71,69 @@ static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
+ }
+
+
+-void bootsplash_do_render_background(struct fb_info *info)
++/*
++ * Copy from source and blend into the destination picture.
++ * Currently assumes that the source picture is 24bpp.
++ * Currently assumes that the destination is <= 32bpp.
++ */
++static int splash_convert_to_fb(u8 *dst,
++ const struct fb_var_screeninfo *dst_var,
++ unsigned int dst_stride,
++ unsigned int dst_xoff,
++ unsigned int dst_yoff,
++ const u8 *src,
++ unsigned int src_width,
++ unsigned int src_height)
++{
++ unsigned int x, y;
++ unsigned int src_stride = 3 * src_width; /* Assume 24bpp packed */
++ u32 dst_octpp = dst_var->bits_per_pixel / 8;
++
++ dst_xoff += dst_var->xoffset;
++ dst_yoff += dst_var->yoffset;
++
++ /* Copy with stride and pixel size adjustment */
++ for (y = 0;
++ y < src_height && y + dst_yoff < dst_var->yres_virtual;
++ y++) {
++ const u8 *srcline = src + (y * src_stride);
++ u8 *dstline = dst + ((y + dst_yoff) * dst_stride)
++ + (dst_xoff * dst_octpp);
++
++ for (x = 0;
++ x < src_width && x + dst_xoff < dst_var->xres_virtual;
++ x++) {
++ u8 red, green, blue;
++ u32 dstpix;
++
++ /* Read pixel */
++ red = *srcline++;
++ green = *srcline++;
++ blue = *srcline++;
++
++ /* Write pixel */
++ dstpix = pack_pixel(dst_var, red, green, blue);
++ memcpy(dstline, &dstpix, dst_octpp);
++
++ dstline += dst_octpp;
++ }
++ }
++
++ return 0;
++}
++
++
++void bootsplash_do_render_background(struct fb_info *info,
++ const struct splash_file_priv *fp)
+ {
+ unsigned int x, y;
+ u32 dstpix;
+ u32 dst_octpp = info->var.bits_per_pixel / 8;
+
+ dstpix = pack_pixel(&info->var,
+- 0,
+- 0,
+- 0);
++ fp->header->bg_red,
++ fp->header->bg_green,
++ fp->header->bg_blue);
+
+ for (y = 0; y < info->var.yres_virtual; y++) {
+ u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
+@@ -91,3 +145,44 @@ void bootsplash_do_render_background(struct fb_info *info)
+ }
+ }
+ }
++
++
++void bootsplash_do_render_pictures(struct fb_info *info,
++ const struct splash_file_priv *fp)
++{
++ unsigned int i;
++
++ for (i = 0; i < fp->header->num_pics; i++) {
++ struct splash_blob_priv *bp;
++ struct splash_pic_priv *pp = &fp->pics[i];
++ long dst_xoff, dst_yoff;
++
++ if (pp->blobs_loaded < 1)
++ continue;
++
++ bp = &pp->blobs[0];
++
++ if (!bp || bp->blob_header->type != 0)
++ continue;
++
++ dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
++ dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
++
++ if (dst_xoff < 0
++ || dst_yoff < 0
++ || dst_xoff + pp->pic_header->width > info->var.xres
++ || dst_yoff + pp->pic_header->height > info->var.yres) {
++ pr_info_once("Picture %u is out of bounds at current resolution: %dx%d\n"
++ "(this will only be printed once every reboot)\n",
++ i, info->var.xres, info->var.yres);
++
++ continue;
++ }
++
++ /* Draw next splash frame */
++ splash_convert_to_fb(info->screen_buffer, &info->var,
++ info->fix.line_length, dst_xoff, dst_yoff,
++ bp->data,
++ pp->pic_header->width, pp->pic_header->height);
++ }
++}
+diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
+new file mode 100644
+index 000000000000..89dc9cca8f0c
+--- /dev/null
++++ b/include/uapi/linux/bootsplash_file.h
+@@ -0,0 +1,118 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (File format)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
++ */
++
++#ifndef __BOOTSPLASH_FILE_H
++#define __BOOTSPLASH_FILE_H
++
++
++#define BOOTSPLASH_VERSION 55561
++
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++
++/*
++ * On-disk types
++ *
++ * A splash file consists of:
++ * - One single 'struct splash_file_header'
++ * - An array of 'struct splash_pic_header'
++ * - An array of raw data blocks, each padded to 16 bytes and
++ * preceded by a 'struct splash_blob_header'
++ *
++ * A single-frame splash may look like this:
++ *
++ * +--------------------+
++ * | |
++ * | splash_file_header |
++ * | -> num_blobs = 1 |
++ * | -> num_pics = 1 |
++ * | |
++ * +--------------------+
++ * | |
++ * | splash_pic_header |
++ * | |
++ * +--------------------+
++ * | |
++ * | splash_blob_header |
++ * | -> type = 0 |
++ * | -> picture_id = 0 |
++ * | |
++ * | (raw RGB data) |
++ * | (pad to 16 bytes) |
++ * | |
++ * +--------------------+
++ *
++ * All multi-byte values are stored on disk in the native format
++ * expected by the system the file will be used on.
++ */
++#define BOOTSPLASH_MAGIC_BE "Linux bootsplash"
++#define BOOTSPLASH_MAGIC_LE "hsalpstoob xuniL"
++
++struct splash_file_header {
++ uint8_t id[16]; /* "Linux bootsplash" (no trailing NUL) */
++
++ /* Splash file format version to avoid clashes */
++ uint16_t version;
++
++ /* The background color */
++ uint8_t bg_red;
++ uint8_t bg_green;
++ uint8_t bg_blue;
++ uint8_t bg_reserved;
++
++ /*
++ * Number of pic/blobs so we can allocate memory for internal
++ * structures ahead of time when reading the file
++ */
++ uint16_t num_blobs;
++ uint8_t num_pics;
++
++ uint8_t padding[103];
++} __attribute__((__packed__));
++
++
++struct splash_pic_header {
++ uint16_t width;
++ uint16_t height;
++
++ /*
++ * Number of data packages associated with this picture.
++ * Currently, the only use for more than 1 is for animations.
++ */
++ uint8_t num_blobs;
++
++ uint8_t padding[27];
++} __attribute__((__packed__));
++
++
++struct splash_blob_header {
++ /* Length of the data block in bytes. */
++ uint32_t length;
++
++ /*
++ * Type of the contents.
++ * 0 - Raw RGB data.
++ */
++ uint16_t type;
++
++ /*
++ * Picture this blob is associated with.
++ * Blobs will be added to a picture in the order they are
++ * found in the file.
++ */
++ uint8_t picture_id;
++
++ uint8_t padding[9];
++} __attribute__((__packed__));
++
++#endif
diff --git a/0403-bootsplash.patch b/0403-bootsplash.patch
new file mode 100644
index 000000000000..216953762e2e
--- /dev/null
+++ b/0403-bootsplash.patch
@@ -0,0 +1,66 @@
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index 843c5400fefc..815b007f81ca 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -112,6 +112,8 @@ void bootsplash_render_full(struct fb_info *info)
+
+ bootsplash_do_render_pictures(info, splash_state.file);
+
++ bootsplash_do_render_flush(info);
++
+ out:
+ mutex_unlock(&splash_state.data_lock);
+ }
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+index 71e2a27ac0b8..0acb383aa4e3 100644
+--- a/drivers/video/fbdev/core/bootsplash_internal.h
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -89,6 +89,7 @@ void bootsplash_do_render_background(struct fb_info *info,
+ const struct splash_file_priv *fp);
+ void bootsplash_do_render_pictures(struct fb_info *info,
+ const struct splash_file_priv *fp);
++void bootsplash_do_render_flush(struct fb_info *info);
+
+
+ void bootsplash_free_file(struct splash_file_priv *fp);
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 2ae36949d0e3..8c09c306ff67 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -186,3 +186,36 @@ void bootsplash_do_render_pictures(struct fb_info *info,
+ pp->pic_header->width, pp->pic_header->height);
+ }
+ }
++
++
++void bootsplash_do_render_flush(struct fb_info *info)
++{
++ /*
++ * FB drivers using deferred_io (such as Xen) need to sync the
++ * screen after modifying its contents. When the FB is mmap()ed
++ * from userspace, this happens via a dirty pages callback, but
++ * when modifying the FB from the kernel, there is no such thing.
++ *
++ * So let's issue a fake fb_copyarea (copying the FB onto itself)
++ * to trick the FB driver into syncing the screen.
++ *
++ * A few DRM drivers' FB implementations are broken by not using
++ * deferred_io when they really should - we match on the known
++ * bad ones manually for now.
++ */
++ if (info->fbdefio
++ || !strcmp(info->fix.id, "astdrmfb")
++ || !strcmp(info->fix.id, "cirrusdrmfb")
++ || !strcmp(info->fix.id, "mgadrmfb")) {
++ struct fb_copyarea area;
++
++ area.dx = 0;
++ area.dy = 0;
++ area.width = info->var.xres;
++ area.height = info->var.yres;
++ area.sx = 0;
++ area.sy = 0;
++
++ info->fbops->fb_copyarea(info, &area);
++ }
++}
diff --git a/0404-bootsplash.patch b/0404-bootsplash.patch
new file mode 100644
index 000000000000..7eb54aff7e00
--- /dev/null
+++ b/0404-bootsplash.patch
@@ -0,0 +1,215 @@
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 8c09c306ff67..07e3a4eab811 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -155,6 +155,7 @@ void bootsplash_do_render_pictures(struct fb_info *info,
+ for (i = 0; i < fp->header->num_pics; i++) {
+ struct splash_blob_priv *bp;
+ struct splash_pic_priv *pp = &fp->pics[i];
++ const struct splash_pic_header *ph = pp->pic_header;
+ long dst_xoff, dst_yoff;
+
+ if (pp->blobs_loaded < 1)
+@@ -165,8 +166,139 @@ void bootsplash_do_render_pictures(struct fb_info *info,
+ if (!bp || bp->blob_header->type != 0)
+ continue;
+
+- dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
+- dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
++ switch (ph->position) {
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_LEFT:
++ dst_xoff = 0;
++ dst_yoff = 0;
++
++ dst_xoff += ph->position_offset;
++ dst_yoff += ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = 0;
++
++ dst_yoff += ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_RIGHT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_yoff = 0;
++
++ dst_xoff -= ph->position_offset;
++ dst_yoff += ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_RIGHT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff -= ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_RIGHT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++
++ dst_xoff -= ph->position_offset;
++ dst_yoff -= ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++
++ dst_yoff -= ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_LEFT:
++ dst_xoff = 0 + ph->position_offset;
++ dst_yoff = info->var.yres - pp->pic_header->height
++ - ph->position_offset;
++ break;
++ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_LEFT:
++ dst_xoff = 0;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff += ph->position_offset;
++ break;
++
++ case SPLASH_CORNER_TOP_LEFT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff -= ph->position_offset;
++ dst_yoff -= ph->position_offset;
++ break;
++ case SPLASH_CORNER_TOP:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_yoff -= ph->position_offset;
++ break;
++ case SPLASH_CORNER_TOP_RIGHT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff += ph->position_offset;
++ dst_yoff -= ph->position_offset;
++ break;
++ case SPLASH_CORNER_RIGHT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff += ph->position_offset;
++ break;
++ case SPLASH_CORNER_BOTTOM_RIGHT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff += ph->position_offset;
++ dst_yoff += ph->position_offset;
++ break;
++ case SPLASH_CORNER_BOTTOM:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_yoff += ph->position_offset;
++ break;
++ case SPLASH_CORNER_BOTTOM_LEFT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff -= ph->position_offset;
++ dst_yoff += ph->position_offset;
++ break;
++ case SPLASH_CORNER_LEFT:
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++
++ dst_xoff -= ph->position_offset;
++ break;
++
++ default:
++ /* As a fallback, center the picture. */
++ dst_xoff = info->var.xres - pp->pic_header->width;
++ dst_xoff /= 2;
++ dst_yoff = info->var.yres - pp->pic_header->height;
++ dst_yoff /= 2;
++ break;
++ }
+
+ if (dst_xoff < 0
+ || dst_yoff < 0
+diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
+index 89dc9cca8f0c..71cedcc68933 100644
+--- a/include/uapi/linux/bootsplash_file.h
++++ b/include/uapi/linux/bootsplash_file.h
+@@ -91,7 +91,32 @@ struct splash_pic_header {
+ */
+ uint8_t num_blobs;
+
+- uint8_t padding[27];
++ /*
++ * Corner to move the picture to / from.
++ * 0x00 - Top left
++ * 0x01 - Top
++ * 0x02 - Top right
++ * 0x03 - Right
++ * 0x04 - Bottom right
++ * 0x05 - Bottom
++ * 0x06 - Bottom left
++ * 0x07 - Left
++ *
++ * Flags:
++ * 0x10 - Calculate offset from the corner towards the center,
++ * rather than from the center towards the corner
++ */
++ uint8_t position;
++
++ /*
++ * Pixel offset from the selected position.
++ * Example: If the picture is in the top right corner, it will
++ * be placed position_offset pixels from the top and
++ * position_offset pixels from the right margin.
++ */
++ uint16_t position_offset;
++
++ uint8_t padding[24];
+ } __attribute__((__packed__));
+
+
+@@ -115,4 +140,22 @@ struct splash_blob_header {
+ uint8_t padding[9];
+ } __attribute__((__packed__));
+
++
++
++
++/*
++ * Enums for on-disk types
++ */
++enum splash_position {
++ SPLASH_CORNER_TOP_LEFT = 0,
++ SPLASH_CORNER_TOP = 1,
++ SPLASH_CORNER_TOP_RIGHT = 2,
++ SPLASH_CORNER_RIGHT = 3,
++ SPLASH_CORNER_BOTTOM_RIGHT = 4,
++ SPLASH_CORNER_BOTTOM = 5,
++ SPLASH_CORNER_BOTTOM_LEFT = 6,
++ SPLASH_CORNER_LEFT = 7,
++ SPLASH_POS_FLAG_CORNER = 0x10,
++};
++
+ #endif
diff --git a/0405-bootsplash.patch b/0405-bootsplash.patch
new file mode 100644
index 000000000000..2785c5e65277
--- /dev/null
+++ b/0405-bootsplash.patch
@@ -0,0 +1,327 @@
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index 815b007f81ca..c8642142cfea 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -53,6 +53,14 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)
+ console_unlock();
+ }
+
++static void splash_callback_animation(struct work_struct *ignored)
++{
++ if (bootsplash_would_render_now()) {
++ /* This will also re-schedule this delayed worker */
++ splash_callback_redraw_vc(ignored);
++ }
++}
++
+
+ static bool is_fb_compatible(const struct fb_info *info)
+ {
+@@ -103,17 +111,44 @@ static bool is_fb_compatible(const struct fb_info *info)
+ */
+ void bootsplash_render_full(struct fb_info *info)
+ {
++ bool is_update = false;
++
+ mutex_lock(&splash_state.data_lock);
+
+- if (!is_fb_compatible(info))
+- goto out;
++ /*
++ * If we've painted on this FB recently, we don't have to do
++ * the sanity checks and background drawing again.
++ */
++ if (splash_state.splash_fb == info)
++ is_update = true;
++
++
++ if (!is_update) {
++ /* Check whether we actually support this FB. */
++ splash_state.splash_fb = NULL;
++
++ if (!is_fb_compatible(info))
++ goto out;
++
++ /* Draw the background only once */
++ bootsplash_do_render_background(info, splash_state.file);
+
+- bootsplash_do_render_background(info, splash_state.file);
++ /* Mark this FB as last seen */
++ splash_state.splash_fb = info;
++ }
+
+- bootsplash_do_render_pictures(info, splash_state.file);
++ bootsplash_do_render_pictures(info, splash_state.file, is_update);
+
+ bootsplash_do_render_flush(info);
+
++ bootsplash_do_step_animations(splash_state.file);
++
++ /* Schedule update for animated splash screens */
++ if (splash_state.file->frame_ms > 0)
++ schedule_delayed_work(&splash_state.dwork_animation,
++ msecs_to_jiffies(
++ splash_state.file->frame_ms));
++
+ out:
+ mutex_unlock(&splash_state.data_lock);
+ }
+@@ -169,8 +204,14 @@ void bootsplash_enable(void)
+
+ was_enabled = test_and_set_bit(0, &splash_state.enabled);
+
+- if (!was_enabled)
++ if (!was_enabled) {
++ /* Force a full redraw when the splash is re-activated */
++ mutex_lock(&splash_state.data_lock);
++ splash_state.splash_fb = NULL;
++ mutex_unlock(&splash_state.data_lock);
++
+ schedule_work(&splash_state.work_redraw_vc);
++ }
+ }
+
+
+@@ -227,6 +268,14 @@ ATTRIBUTE_GROUPS(splash_dev);
+ */
+ static int splash_resume(struct device *device)
+ {
++ /*
++ * Force full redraw on resume since we've probably lost the
++ * framebuffer's contents meanwhile
++ */
++ mutex_lock(&splash_state.data_lock);
++ splash_state.splash_fb = NULL;
++ mutex_unlock(&splash_state.data_lock);
++
+ if (bootsplash_would_render_now())
+ schedule_work(&splash_state.work_redraw_vc);
+
+@@ -235,6 +284,7 @@ static int splash_resume(struct device *device)
+
+ static int splash_suspend(struct device *device)
+ {
++ cancel_delayed_work_sync(&splash_state.dwork_animation);
+ cancel_work_sync(&splash_state.work_redraw_vc);
+
+ return 0;
+@@ -296,6 +346,8 @@ void bootsplash_init(void)
+ set_bit(0, &splash_state.enabled);
+
+ INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
++ INIT_DELAYED_WORK(&splash_state.dwork_animation,
++ splash_callback_animation);
+
+
+ if (!splash_state.bootfile || !strlen(splash_state.bootfile))
+diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
+index 0acb383aa4e3..b3a74835d90f 100644
+--- a/drivers/video/fbdev/core/bootsplash_internal.h
++++ b/drivers/video/fbdev/core/bootsplash_internal.h
+@@ -37,6 +37,8 @@ struct splash_pic_priv {
+
+ struct splash_blob_priv *blobs;
+ u16 blobs_loaded;
++
++ u16 anim_nextframe;
+ };
+
+
+@@ -45,6 +47,12 @@ struct splash_file_priv {
+ const struct splash_file_header *header;
+
+ struct splash_pic_priv *pics;
++
++ /*
++ * A local copy of the frame delay in the header.
++ * We modify it to keep the code simple.
++ */
++ u16 frame_ms;
+ };
+
+
+@@ -71,6 +79,7 @@ struct splash_priv {
+ struct platform_device *splash_device;
+
+ struct work_struct work_redraw_vc;
++ struct delayed_work dwork_animation;
+
+ /* Splash data structures including lock for everything below */
+ struct mutex data_lock;
+@@ -88,8 +97,10 @@ struct splash_priv {
+ void bootsplash_do_render_background(struct fb_info *info,
+ const struct splash_file_priv *fp);
+ void bootsplash_do_render_pictures(struct fb_info *info,
+- const struct splash_file_priv *fp);
++ const struct splash_file_priv *fp,
++ bool is_update);
+ void bootsplash_do_render_flush(struct fb_info *info);
++void bootsplash_do_step_animations(struct splash_file_priv *fp);
+
+
+ void bootsplash_free_file(struct splash_file_priv *fp);
+diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
+index fd807571ab7d..1f661b2d4cc9 100644
+--- a/drivers/video/fbdev/core/bootsplash_load.c
++++ b/drivers/video/fbdev/core/bootsplash_load.c
+@@ -71,6 +71,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ {
+ const struct firmware *fw;
+ struct splash_file_priv *fp;
++ bool have_anim = false;
+ unsigned int i;
+ const u8 *walker;
+
+@@ -135,6 +136,13 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ goto err;
+ }
+
++ if (ph->anim_type > SPLASH_ANIM_LOOP_FORWARD) {
++ pr_warn("Picture %u: Unsupported animation type %u.\n",
++ i, ph->anim_type);
++
++ ph->anim_type = SPLASH_ANIM_NONE;
++ }
++
+ pp->pic_header = ph;
+ pp->blobs = vzalloc(ph->num_blobs
+ * sizeof(struct splash_blob_priv));
+@@ -202,6 +210,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+ /* Walk over pictures and ensure all blob slots are filled */
+ for (i = 0; i < fp->header->num_pics; i++) {
+ struct splash_pic_priv *pp = &fp->pics[i];
++ const struct splash_pic_header *ph = pp->pic_header;
+
+ if (pp->blobs_loaded != pp->pic_header->num_blobs) {
+ pr_err("Picture %u doesn't have all blob slots filled.\n",
+@@ -209,8 +218,20 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
+
+ goto err;
+ }
++
++ if (ph->anim_type
++ && ph->num_blobs > 1
++ && ph->anim_loop < pp->blobs_loaded)
++ have_anim = true;
+ }
+
++ if (!have_anim)
++ /* Disable animation timer if there is nothing to animate */
++ fp->frame_ms = 0;
++ else
++ /* Enforce minimum delay between frames */
++ fp->frame_ms = max((u16)20, fp->header->frame_ms);
++
+ pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
+ fw->size,
+ fp->header->num_pics,
+diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
+index 07e3a4eab811..76033606ca8a 100644
+--- a/drivers/video/fbdev/core/bootsplash_render.c
++++ b/drivers/video/fbdev/core/bootsplash_render.c
+@@ -148,7 +148,8 @@ void bootsplash_do_render_background(struct fb_info *info,
+
+
+ void bootsplash_do_render_pictures(struct fb_info *info,
+- const struct splash_file_priv *fp)
++ const struct splash_file_priv *fp,
++ bool is_update)
+ {
+ unsigned int i;
+
+@@ -161,7 +162,11 @@ void bootsplash_do_render_pictures(struct fb_info *info,
+ if (pp->blobs_loaded < 1)
+ continue;
+
+- bp = &pp->blobs[0];
++ /* Skip static pictures when refreshing animations */
++ if (ph->anim_type == SPLASH_ANIM_NONE && is_update)
++ continue;
++
++ bp = &pp->blobs[pp->anim_nextframe];
+
+ if (!bp || bp->blob_header->type != 0)
+ continue;
+@@ -351,3 +356,24 @@ void bootsplash_do_render_flush(struct fb_info *info)
+ info->fbops->fb_copyarea(info, &area);
+ }
+ }
++
++
++void bootsplash_do_step_animations(struct splash_file_priv *fp)
++{
++ unsigned int i;
++
++ /* Step every animation once */
++ for (i = 0; i < fp->header->num_pics; i++) {
++ struct splash_pic_priv *pp = &fp->pics[i];
++
++ if (pp->blobs_loaded < 2
++ || pp->pic_header->anim_loop > pp->blobs_loaded)
++ continue;
++
++ if (pp->pic_header->anim_type == SPLASH_ANIM_LOOP_FORWARD) {
++ pp->anim_nextframe++;
++ if (pp->anim_nextframe >= pp->pic_header->num_blobs)
++ pp->anim_nextframe = pp->pic_header->anim_loop;
++ }
++ }
++}
+diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
+index 71cedcc68933..b3af0a3c6487 100644
+--- a/include/uapi/linux/bootsplash_file.h
++++ b/include/uapi/linux/bootsplash_file.h
+@@ -77,7 +77,17 @@ struct splash_file_header {
+ uint16_t num_blobs;
+ uint8_t num_pics;
+
+- uint8_t padding[103];
++ uint8_t unused_1;
++
++ /*
++ * Milliseconds to wait before painting the next frame in
++ * an animation.
++ * This is actually a minimum, as the system is allowed to
++ * stall for longer between frames.
++ */
++ uint16_t frame_ms;
++
++ uint8_t padding[100];
+ } __attribute__((__packed__));
+
+
+@@ -116,7 +126,23 @@ struct splash_pic_header {
+ */
+ uint16_t position_offset;
+
+- uint8_t padding[24];
++ /*
++ * Animation type.
++ * 0 - off
++ * 1 - forward loop
++ */
++ uint8_t anim_type;
++
++ /*
++ * Animation loop point.
++ * Actual meaning depends on animation type:
++ * Type 0 - Unused
++ * 1 - Frame at which to restart the forward loop
++ * (allowing for "intro" frames)
++ */
++ uint8_t anim_loop;
++
++ uint8_t padding[22];
+ } __attribute__((__packed__));
+
+
+@@ -158,4 +184,9 @@ enum splash_position {
+ SPLASH_POS_FLAG_CORNER = 0x10,
+ };
+
++enum splash_anim_type {
++ SPLASH_ANIM_NONE = 0,
++ SPLASH_ANIM_LOOP_FORWARD = 1,
++};
++
+ #endif
diff --git a/0406-bootsplash.patch b/0406-bootsplash.patch
new file mode 100644
index 000000000000..d6c6db659c56
--- /dev/null
+++ b/0406-bootsplash.patch
@@ -0,0 +1,82 @@
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index 2ebaba16f785..416735ab6dc1 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -105,6 +105,7 @@
+ #include <linux/ctype.h>
+ #include <linux/bsearch.h>
+ #include <linux/gcd.h>
++#include <linux/bootsplash.h>
+
+ #define MAX_NR_CON_DRIVER 16
+
+@@ -4235,6 +4236,7 @@ void do_unblank_screen(int leaving_gfx)
+ }
+
+ console_blanked = 0;
++ bootsplash_mark_dirty();
+ if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
+ /* Low-level driver cannot restore -> do it ourselves */
+ update_screen(vc);
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index c8642142cfea..13fcaabbc2ca 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -165,6 +165,13 @@ bool bootsplash_would_render_now(void)
+ && bootsplash_is_enabled();
+ }
+
++void bootsplash_mark_dirty(void)
++{
++ mutex_lock(&splash_state.data_lock);
++ splash_state.splash_fb = NULL;
++ mutex_unlock(&splash_state.data_lock);
++}
++
+ bool bootsplash_is_enabled(void)
+ {
+ bool was_enabled;
+@@ -206,9 +213,7 @@ void bootsplash_enable(void)
+
+ if (!was_enabled) {
+ /* Force a full redraw when the splash is re-activated */
+- mutex_lock(&splash_state.data_lock);
+- splash_state.splash_fb = NULL;
+- mutex_unlock(&splash_state.data_lock);
++ bootsplash_mark_dirty();
+
+ schedule_work(&splash_state.work_redraw_vc);
+ }
+@@ -272,9 +277,7 @@ static int splash_resume(struct device *device)
+ * Force full redraw on resume since we've probably lost the
+ * framebuffer's contents meanwhile
+ */
+- mutex_lock(&splash_state.data_lock);
+- splash_state.splash_fb = NULL;
+- mutex_unlock(&splash_state.data_lock);
++ bootsplash_mark_dirty();
+
+ if (bootsplash_would_render_now())
+ schedule_work(&splash_state.work_redraw_vc);
+diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
+index c6dd0b43180d..4075098aaadd 100644
+--- a/include/linux/bootsplash.h
++++ b/include/linux/bootsplash.h
+@@ -19,6 +19,8 @@ extern void bootsplash_render_full(struct fb_info *info);
+
+ extern bool bootsplash_would_render_now(void);
+
++extern void bootsplash_mark_dirty(void);
++
+ extern bool bootsplash_is_enabled(void);
+ extern void bootsplash_disable(void);
+ extern void bootsplash_enable(void);
+@@ -31,6 +33,8 @@ extern void bootsplash_init(void);
+
+ #define bootsplash_would_render_now() (false)
+
++#define bootsplash_mark_dirty()
++
+ #define bootsplash_is_enabled() (false)
+ #define bootsplash_disable()
+ #define bootsplash_enable()
diff --git a/0407-bootsplash.patch b/0407-bootsplash.patch
new file mode 100644
index 000000000000..3f82eb0b9296
--- /dev/null
+++ b/0407-bootsplash.patch
@@ -0,0 +1,42 @@
+diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
+index f4166263bb3a..a248429194bb 100644
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -49,6 +49,8 @@
+
+ #include <asm/irq_regs.h>
+
++#include <linux/bootsplash.h>
++
+ /*
+ * Exported functions/variables
+ */
+@@ -1413,6 +1415,28 @@ static void kbd_keycode(unsigned int key
+ }
+ #endif
+
++ /* Trap keys when bootsplash is shown */
++ if (bootsplash_would_render_now()) {
++ /* Deactivate bootsplash on ESC or Alt+Fxx VT switch */
++ if (keycode >= KEY_F1 && keycode <= KEY_F12) {
++ bootsplash_disable();
++
++ /*
++ * No return here since we want to actually
++ * perform the VT switch.
++ */
++ } else {
++ if (keycode == KEY_ESC)
++ bootsplash_disable();
++
++ /*
++ * Just drop any other keys.
++ * Their effect would be hidden by the splash.
++ */
++ return;
++ }
++ }
++
+ if (kbd->kbdmode == VC_MEDIUMRAW) {
+ /*
+ * This is extended medium raw mode, with keys above 127
diff --git a/0408-bootsplash.patch b/0408-bootsplash.patch
new file mode 100644
index 000000000000..8a3b715ce46a
--- /dev/null
+++ b/0408-bootsplash.patch
@@ -0,0 +1,21 @@
+diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
+index 3ffc1ce29023..bc6a24c9dfa8 100644
+--- a/drivers/tty/sysrq.c
++++ b/drivers/tty/sysrq.c
+@@ -49,6 +49,7 @@
+ #include <linux/syscalls.h>
+ #include <linux/of.h>
+ #include <linux/rcupdate.h>
++#include <linux/bootsplash.h>
+
+ #include <asm/ptrace.h>
+ #include <asm/irq_regs.h>
+@@ -104,6 +105,8 @@ static void sysrq_handle_SAK(int key)
+ {
+ struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
+ schedule_work(SAK_work);
++
++ bootsplash_disable();
+ }
+ static struct sysrq_key_op sysrq_SAK_op = {
+ .handler = sysrq_handle_SAK,
diff --git a/0409-bootsplash.patch b/0409-bootsplash.patch
new file mode 100644
index 000000000000..add68e7b275c
--- /dev/null
+++ b/0409-bootsplash.patch
@@ -0,0 +1,21 @@
+diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
+index 9a39a6fcfe98..8a9c67e1c5d8 100644
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -1343,6 +1343,16 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
+ int y;
+ int c = scr_readw((u16 *) vc->vc_pos);
+
++ /*
++ * Disable the splash here so we don't have to hook into
++ * vt_console_print() in drivers/tty/vt/vt.c
++ *
++ * We'd disable the splash just before the call to
++ * hide_cursor() anyway, so this spot is just fine.
++ */
++ if (oops_in_progress)
++ bootsplash_disable();
++
+ ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+
+ if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
diff --git a/0410-bootsplash.patch b/0410-bootsplash.patch
new file mode 100644
index 000000000000..e5c1fd0c8604
--- /dev/null
+++ b/0410-bootsplash.patch
@@ -0,0 +1,321 @@
+diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
+new file mode 100644
+index 000000000000..742c7b035ded
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
+@@ -0,0 +1,11 @@
++What: /sys/devices/platform/bootsplash.0/enabled
++Date: Oct 2017
++KernelVersion: 4.14
++Contact: Max Staudt <mstaudt@suse.de>
++Description:
++ Can be set and read.
++
++ 0: Splash is disabled.
++ 1: Splash is shown whenever fbcon would show a text console
++ (i.e. no graphical application is running), and a splash
++ file is loaded.
+diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
+new file mode 100644
+index 000000000000..611f0c558925
+--- /dev/null
++++ b/Documentation/bootsplash.rst
+@@ -0,0 +1,285 @@
++====================
++The Linux bootsplash
++====================
++
++:Date: November, 2017
++:Author: Max Staudt <mstaudt@suse.de>
++
++
++The Linux bootsplash is a graphical replacement for the '``quiet``' boot
++option, typically showing a logo and a spinner animation as the system starts.
++
++Currently, it is a part of the Framebuffer Console support, and can be found
++as ``CONFIG_BOOTSPLASH`` in the kernel configuration. This means that as long
++as it is enabled, it hijacks fbcon's output and draws a splash screen instead.
++
++Purely compiling in the bootsplash will not render it functional - to actually
++render a splash, you will also need a splash theme file. See the example
++utility and script in ``tools/bootsplash`` for a live demo.
++
++
++
++Motivation
++==========
++
++- The '``quiet``' boot option only suppresses most messages during boot, but
++ errors are still shown.
++
++- A user space implementation can only show a logo once user space has been
++ initialized far enough to allow this. A kernel splash can display a splash
++ immediately as soon as fbcon can be displayed.
++
++- Implementing a splash screen in user space (e.g. Plymouth) is problematic
++ due to resource conflicts.
++
++ For example, if Plymouth is keeping ``/dev/fb0`` (provided via vesafb/efifb)
++ open, then most DRM drivers can't replace it because the address space is
++ still busy - thus leading to a VRAM reservation error.
++
++ See: https://bugzilla.opensuse.org/show_bug.cgi?id=980750
++
++
++
++Command line arguments
++======================
++
++``bootsplash.bootfile``
++ Which file in the initramfs to load.
++
++ The splash theme is loaded via request_firmware(), thus to load
++ ``/lib/firmware/bootsplash/mytheme`` pass the command line:
++
++ ``bootsplash.bootfile=bootsplash/mytheme``
++
++ Note: The splash file *has to be* in the initramfs, as it needs to be
++ available when the splash is initialized early on.
++
++ Default: none, i.e. a non-functional splash, falling back to showing text.
++
++
++
++sysfs run-time configuration
++============================
++
++``/sys/devices/platform/bootsplash.0/enabled``
++ Enable/disable the bootsplash.
++ The system boots with this set to 1, but will not show a splash unless
++ a splash theme file is also loaded.
++
++
++
++Kconfig
++=======
++
++``BOOTSPLASH``
++ Whether to compile in bootsplash support
++ (depends on fbcon compiled in, i.e. ``FRAMEBUFFER_CONSOLE=y``)
++
++
++
++Bootsplash file format
++======================
++
++A file specified in the kernel configuration as ``CONFIG_BOOTSPLASH_FILE``
++or specified on the command line as ``bootsplash.bootfile`` will be loaded
++and displayed as soon as fbcon is initialized.
++
++
++Main blocks
++-----------
++
++There are 3 main blocks in each file:
++
++ - one File header
++ - n Picture headers
++ - m (Blob header + payload) blocks
++
++
++Structures
++----------
++
++The on-disk structures are defined in
++``drivers/video/fbdev/core/bootsplash_file.h`` and represent these blocks:
++
++ - ``struct splash_file_header``
++
++ Represents the file header, with splash-wide information including:
++
++ - The magic string "``Linux bootsplash``" on big-endian platforms
++ (the reverse on little endian)
++ - The file format version (for incompatible updates, hopefully never)
++ - The background color
++ - Number of picture and blob blocks
++ - Animation speed (we only allow one delay for all animations)
++
++ The file header is followed by the first picture header.
++
++
++ - ``struct splash_picture_header``
++
++ Represents an object (picture) drawn on screen, including its immutable
++ properties:
++ - Width, height
++ - Positioning relative to screen corners or in the center
++ - Animation, if any
++ - Animation type
++ - Number of blobs
++
++ The picture header is followed by another picture header, up until n
++ picture headers (as defined in the file header) have been read. Then,
++ the (blob header, payload) pairs follow.
++
++
++ - ``struct splash_blob_header``
++ (followed by payload)
++
++ Represents one raw data stream. So far, only picture data is defined.
++
++ The blob header is followed by a payload, then padding to n*16 bytes,
++ then (if further blobs are defined in the file header) a further blob
++ header.
++
++
++Alignment
++---------
++
++The bootsplash file is designed to be loaded into memory as-is.
++
++All structures are a multiple of 16 bytes long, all elements therein are
++aligned to multiples of their length, and the payloads are always padded
++up to multiples of 16 bytes. This is to allow aligned accesses in all
++cases while still simply mapping the structures over an in-memory copy of
++the bootsplash file.
++
++
++Further information
++-------------------
++
++Please see ``drivers/video/fbdev/core/bootsplash_file.h`` for further
++details and possible values in the file.
++
++
++
++Hooks - how the bootsplash is integrated
++========================================
++
++``drivers/video/fbdev/core/fbcon.c``
++ ``fbcon_init()`` calls ``bootsplash_init()``, which loads the default
++ bootsplash file or the one specified on the kernel command line.
++
++ ``fbcon_switch()`` draws the bootsplash when it's active, and is also
++ one of the callers of ``set_blitting_type()``.
++
++ ``set_blitting_type()`` calls ``fbcon_set_dummyops()`` when the
++ bootsplash is active, overriding the text rendering functions.
++
++ ``fbcon_cursor()`` will call ``bootsplash_disable()`` when an oops is
++ being printed in order to make a kernel panic visible.
++
++``drivers/video/fbdev/core/dummyblit.c``
++ This contains the dummy text rendering functions used to suppress text
++ output while the bootsplash is shown.
++
++``drivers/tty/vt/keyboard.c``
++ ``kbd_keycode()`` can call ``bootsplash_disable()`` when the user
++ presses ESC or F1-F12 (changing VT). This is to provide a built-in way
++ of disabling the splash manually at any time.
++
++
++
++FAQ: Frequently Asked Questions
++===============================
++
++I want to see the log! How do I show the log?
++---------------------------------------------
++
++Press ESC while the splash is shown, or remove the ``bootsplash.bootfile``
++parameter from the kernel cmdline. Without that parameter, the bootsplash
++will boot disabled.
++
++
++Why use FB instead of modern DRM/KMS?
++-------------------------------------
++
++This is a semantic problem:
++ - What memory to draw the splash to?
++ - And what mode will the screen be set to?
++
++Using the fbdev emulation solves these issues.
++
++Let's start from a bare KMS system, without fbcon, and without fbdev
++emulation. In this case, as long as userspace doesn't open the KMS
++device, the state of the screen is undefined. No framebuffer is
++allocated in video RAM, and no particular mode is set.
++
++In this case, we'd have to allocate a framebuffer to show the splash,
++and set our mode ourselves. This either wastes a screenful of video RAM
++if the splash is to co-exist with the userspace program's own allocated
++framebuffer, or there is a flicker as we deactivate and delete the
++bootsplash's framebuffer and hand control over to userspace. Since we
++may set a different mode than userspace, we'd also have flicker due
++to mode switching.
++
++This logic is already contained in every KMS driver that performs fbdev
++emulation. So we might as well use that. And the correct API to do so is
++fbdev. Plus, we get compatibility with old, pure fbdev drivers for free.
++With the fbdev emulation, there is *always* a well-defined framebuffer
++to draw on. And the selection of mode has already been done by the
++graphics driver, so we don't need to reinvent that wheel, either.
++Finally, if userspace decides to use /dev/fbX, we don't have to worry
++about wasting video RAM, either.
++
++
++Why is the bootsplash integrated in fbcon?
++------------------------------------------
++
++Right now, the bootsplash is drawn from within fbcon, as this allows us
++to easily know *when* to draw - i.e. when we're safe from fbcon and
++userspace drawing all over our beautiful splash logo.
++
++Separating them is not easy - see the to-do list below.
++
++
++
++TO DO list for future development
++=================================
++
++Second enable/disable switch for the system
++-------------------------------------------
++
++It may be helpful to differentiate between the system and the user
++switching off the bootsplash. Thus, the system may make it disappear and
++reappear e.g. for a password prompt, yet once the user has pressed ESC,
++it could stay gone.
++
++
++Fix buggy DRM/KMS drivers
++-------------------------
++
++Currently, the splash code manually checks for fbdev emulation provided by
++the ast, cirrus, and mgag200 DRM/KMS drivers.
++These drivers use a manual mechanism similar to deferred I/O for their FB
++emulation, and thus need to be manually flushed onto the screen in the same
++way.
++
++This may be improved upon in several ways:
++
++1. Changing these drivers to expose the fbdev BO's memory directly, like
++ bochsdrmfb does.
++2. Creating a new fb_ops->fb_flush() API to allow the kernel to flush the
++ framebuffer once the bootsplash has been drawn into it.
++
++
++Separating from fbcon
++---------------------
++
++Separating these two components would yield independence from fbcon being
++compiled into the kernel, and thus lowering code size in embedded
++applications.
++
++To do this cleanly will involve a clean separation of users of an FB device
++within the kernel, i.e. fbcon, bootsplash, and userspace. Right now, the
++legacy fbcon code and VT code co-operate to switch between fbcon and
++userspace (by setting the VT into KD_GRAPHICS mode). Installing a muxer
++between these components ensues refactoring of old code and checking for
++correct locking.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 5c237445761e..7ffac272434e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2709,6 +2709,8 @@ BOOTSPLASH
+ M: Max Staudt <mstaudt@suse.de>
+ L: linux-fbdev@vger.kernel.org
+ S: Maintained
++F: Documentation/ABI/testing/sysfs-platform-bootsplash
++F: Documentation/bootsplash.rst
+ F: drivers/video/fbdev/core/bootsplash*.*
+ F: drivers/video/fbdev/core/dummycon.c
+ F: include/linux/bootsplash.h
diff --git a/0411-bootsplash.patch b/0411-bootsplash.patch
new file mode 100644
index 000000000000..8e87eb463187
--- /dev/null
+++ b/0411-bootsplash.patch
@@ -0,0 +1,129 @@
+diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
+index 742c7b035ded..f8f4b259220e 100644
+--- a/Documentation/ABI/testing/sysfs-platform-bootsplash
++++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
+@@ -9,3 +9,35 @@ Description:
+ 1: Splash is shown whenever fbcon would show a text console
+ (i.e. no graphical application is running), and a splash
+ file is loaded.
++
++What: /sys/devices/platform/bootsplash.0/drop_splash
++Date: Oct 2017
++KernelVersion: 4.14
++Contact: Max Staudt <mstaudt@suse.de>
++Description:
++ Can only be set.
++
++ Any value written will cause the current splash theme file
++ to be unloaded and the text console to be redrawn.
++
++What: /sys/devices/platform/bootsplash.0/load_file
++Date: Oct 2017
++KernelVersion: 4.14
++Contact: Max Staudt <mstaudt@suse.de>
++Description:
++ Can only be set.
++
++ Any value written will cause the splash to be disabled and
++ internal memory structures to be freed.
++
++ A firmware path written will cause a new theme file to be
++ loaded and the current bootsplash to be replaced.
++ The current enabled/disabled status is not touched.
++ If the splash is already active, it will be redrawn.
++
++ The path has to be a path in /lib/firmware since
++ request_firmware() is used to fetch the data.
++
++ When setting the splash from the shell, echo -n has to be
++ used as any trailing '\n' newline will be interpreted as
++ part of the path.
+diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
+index 611f0c558925..b35aba5093e8 100644
+--- a/Documentation/bootsplash.rst
++++ b/Documentation/bootsplash.rst
+@@ -67,6 +67,14 @@ sysfs run-time configuration
+ a splash theme file is also loaded.
+
+
++``/sys/devices/platform/bootsplash.0/drop_splash``
++ Unload splash data and free memory.
++
++``/sys/devices/platform/bootsplash.0/load_file``
++ Load a splash file from ``/lib/firmware/``.
++ Note that trailing newlines will be interpreted as part of the file name.
++
++
+
+ Kconfig
+ =======
+diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
+index 13fcaabbc2ca..16cb0493629d 100644
+--- a/drivers/video/fbdev/core/bootsplash.c
++++ b/drivers/video/fbdev/core/bootsplash.c
+@@ -251,11 +251,65 @@ static ssize_t splash_store_enabled(struct device *device,
+ return count;
+ }
+
++static ssize_t splash_store_drop_splash(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct splash_file_priv *fp;
++
++ if (!buf || !count || !splash_state.file)
++ return count;
++
++ mutex_lock(&splash_state.data_lock);
++ fp = splash_state.file;
++ splash_state.file = NULL;
++ mutex_unlock(&splash_state.data_lock);
++
++ /* Redraw the text console */
++ schedule_work(&splash_state.work_redraw_vc);
++
++ bootsplash_free_file(fp);
++
++ return count;
++}
++
++static ssize_t splash_store_load_file(struct device *device,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct splash_file_priv *fp, *fp_old;
++
++ if (!count)
++ return 0;
++
++ fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
++ buf);
++
++ if (!fp)
++ return -ENXIO;
++
++ mutex_lock(&splash_state.data_lock);
++ fp_old = splash_state.file;
++ splash_state.splash_fb = NULL;
++ splash_state.file = fp;
++ mutex_unlock(&splash_state.data_lock);
++
++ /* Update the splash or text console */
++ schedule_work(&splash_state.work_redraw_vc);
++
++ bootsplash_free_file(fp_old);
++ return count;
++}
++
+ static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
++static DEVICE_ATTR(drop_splash, 0200, NULL, splash_store_drop_splash);
++static DEVICE_ATTR(load_file, 0200, NULL, splash_store_load_file);
+
+
+ static struct attribute *splash_dev_attrs[] = {
+ &dev_attr_enabled.attr,
++ &dev_attr_drop_splash.attr,
++ &dev_attr_load_file.attr,
+ NULL
+ };
+
diff --git a/0412-bootsplash.patch b/0412-bootsplash.patch
new file mode 100644
index 000000000000..5d8ea1fe295c
--- /dev/null
+++ b/0412-bootsplash.patch
@@ -0,0 +1,511 @@
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 7ffac272434e..ddff07cd794c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2715,6 +2715,7 @@ F: drivers/video/fbdev/core/bootsplash*.*
+ F: drivers/video/fbdev/core/dummycon.c
+ F: include/linux/bootsplash.h
+ F: include/uapi/linux/bootsplash_file.h
++F: tools/bootsplash/*
+
+ BPF (Safe dynamic programs and tools)
+ M: Alexei Starovoitov <ast@kernel.org>
+diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
+new file mode 100644
+index 000000000000..091b99a17567
+--- /dev/null
++++ b/tools/bootsplash/.gitignore
+@@ -0,0 +1 @@
++bootsplash-packer
+diff --git a/tools/bootsplash/Makefile b/tools/bootsplash/Makefile
+new file mode 100644
+index 000000000000..0ad8e8a84942
+--- /dev/null
++++ b/tools/bootsplash/Makefile
+@@ -0,0 +1,9 @@
++CC := $(CROSS_COMPILE)gcc
++CFLAGS := -I../../usr/include
++
++PROGS := bootsplash-packer
++
++all: $(PROGS)
++
++clean:
++ rm -fr $(PROGS)
+diff --git a/tools/bootsplash/bootsplash-packer.c b/tools/bootsplash/bootsplash-packer.c
+new file mode 100644
+index 000000000000..ffb6a8b69885
+--- /dev/null
++++ b/tools/bootsplash/bootsplash-packer.c
+@@ -0,0 +1,471 @@
++/*
++ * Kernel based bootsplash.
++ *
++ * (Splash file packer tool)
++ *
++ * Authors:
++ * Max Staudt <mstaudt@suse.de>
++ *
++ * SPDX-License-Identifier: GPL-2.0
++ */
++
++#include <endian.h>
++#include <getopt.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <linux/bootsplash_file.h>
++
++
++static void print_help(char *progname)
++{
++ printf("Usage: %s [OPTIONS] outfile\n", progname);
++ printf("\n"
++ "Options, executed in order given:\n"
++ " -h, --help Print this help message\n"
++ "\n"
++ " --bg_red <u8> Background color (red part)\n"
++ " --bg_green <u8> Background color (green part)\n"
++ " --bg_blue <u8> Background color (blue part)\n"
++ " --bg_reserved <u8> (do not use)\n"
++ " --frame_ms <u16> Minimum milliseconds between animation steps\n"
++ "\n"
++ " --picture Start describing the next picture\n"
++ " --pic_width <u16> Picture width in pixels\n"
++ " --pic_height <u16> Picture height in pixels\n"
++ " --pic_position <u8> Coarse picture placement:\n"
++ " 0x00 - Top left\n"
++ " 0x01 - Top\n"
++ " 0x02 - Top right\n"
++ " 0x03 - Right\n"
++ " 0x04 - Bottom right\n"
++ " 0x05 - Bottom\n"
++ " 0x06 - Bottom left\n"
++ " 0x07 - Left\n"
++ "\n"
++ " Flags:\n"
++ " 0x10 - Calculate offset from corner towards center,\n"
++ " rather than from center towards corner\n"
++ " --pic_position_offset <u16> Distance from base position in pixels\n"
++ " --pic_anim_type <u8> Animation type:\n"
++ " 0 - None\n"
++ " 1 - Forward loop\n"
++ " --pic_anim_loop <u8> Loop point for animation\n"
++ "\n"
++ " --blob <filename> Include next data stream\n"
++ " --blob_type <u16> Type of data\n"
++ " --blob_picture_id <u8> Picture to associate this blob with, starting at 0\n"
++ " (default: number of last --picture)\n"
++ "\n");
++ printf("This tool will write %s files.\n\n",
++#if __BYTE_ORDER == __BIG_ENDIAN
++ "Big Endian (BE)");
++#elif __BYTE_ORDER == __LITTLE_ENDIAN
++ "Little Endian (LE)");
++#else
++#error
++#endif
++}
++
++
++struct blob_entry {
++ struct blob_entry *next;
++
++ char *fn;
++
++ struct splash_blob_header header;
++};
++
++
++static void dump_file_header(struct splash_file_header *h)
++{
++ printf(" --- File header ---\n");
++ printf("\n");
++ printf(" version: %5u\n", h->version);
++ printf("\n");
++ printf(" bg_red: %5u\n", h->bg_red);
++ printf(" bg_green: %5u\n", h->bg_green);
++ printf(" bg_blue: %5u\n", h->bg_blue);
++ printf(" bg_reserved: %5u\n", h->bg_reserved);
++ printf("\n");
++ printf(" num_blobs: %5u\n", h->num_blobs);
++ printf(" num_pics: %5u\n", h->num_pics);
++ printf("\n");
++ printf(" frame_ms: %5u\n", h->frame_ms);
++ printf("\n");
++}
++
++static void dump_pic_header(struct splash_pic_header *ph)
++{
++ printf(" --- Picture header ---\n");
++ printf("\n");
++ printf(" width: %5u\n", ph->width);
++ printf(" height: %5u\n", ph->height);
++ printf("\n");
++ printf(" num_blobs: %5u\n", ph->num_blobs);
++ printf("\n");
++ printf(" position: %0x3x\n", ph->position);
++ printf(" position_offset: %5u\n", ph->position_offset);
++ printf("\n");
++ printf(" anim_type: %5u\n", ph->anim_type);
++ printf(" anim_loop: %5u\n", ph->anim_loop);
++ printf("\n");
++}
++
++static void dump_blob(struct blob_entry *b)
++{
++ printf(" --- Blob header ---\n");
++ printf("\n");
++ printf(" length: %7u\n", b->header.length);
++ printf(" type: %7u\n", b->header.type);
++ printf("\n");
++ printf(" picture_id: %7u\n", b->header.picture_id);
++ printf("\n");
++}
++
++
++#define OPT_MAX(var, max) \
++ do { \
++ if ((var) > max) { \
++ fprintf(stderr, "--%s: Invalid value\n", \
++ long_options[option_index].name); \
++ break; \
++ } \
++ } while (0)
++
++static struct option long_options[] = {
++ {"help", 0, 0, 'h'},
++ {"bg_red", 1, 0, 10001},
++ {"bg_green", 1, 0, 10002},
++ {"bg_blue", 1, 0, 10003},
++ {"bg_reserved", 1, 0, 10004},
++ {"frame_ms", 1, 0, 10005},
++ {"picture", 0, 0, 20000},
++ {"pic_width", 1, 0, 20001},
++ {"pic_height", 1, 0, 20002},
++ {"pic_position", 1, 0, 20003},
++ {"pic_position_offset", 1, 0, 20004},
++ {"pic_anim_type", 1, 0, 20005},
++ {"pic_anim_loop", 1, 0, 20006},
++ {"blob", 1, 0, 30000},
++ {"blob_type", 1, 0, 30001},
++ {"blob_picture_id", 1, 0, 30002},
++ {NULL, 0, NULL, 0}
++};
++
++
++int main(int argc, char **argv)
++{
++ FILE *of;
++ char *ofn;
++ int c;
++ int option_index = 0;
++
++ unsigned long ul;
++ struct splash_file_header fh = {};
++ struct splash_pic_header ph[255];
++ struct blob_entry *blob_first = NULL;
++ struct blob_entry *blob_last = NULL;
++ struct blob_entry *blob_cur = NULL;
++
++ if (argc < 2) {
++ print_help(argv[0]);
++ return EXIT_FAILURE;
++ }
++
++
++ /* Parse and and execute user commands */
++ while ((c = getopt_long(argc, argv, "h",
++ long_options, &option_index)) != -1) {
++ switch (c) {
++ case 10001: /* bg_red */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ fh.bg_red = ul;
++ break;
++ case 10002: /* bg_green */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ fh.bg_green = ul;
++ break;
++ case 10003: /* bg_blue */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ fh.bg_blue = ul;
++ break;
++ case 10004: /* bg_reserved */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ fh.bg_reserved = ul;
++ break;
++ case 10005: /* frame_ms */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 65535);
++ fh.frame_ms = ul;
++ break;
++
++
++ case 20000: /* picture */
++ if (fh.num_pics >= 255) {
++ fprintf(stderr, "--%s: Picture array full\n",
++ long_options[option_index].name);
++ break;
++ }
++
++ fh.num_pics++;
++ break;
++
++ case 20001: /* pic_width */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 65535);
++ ph[fh.num_pics - 1].width = ul;
++ break;
++
++ case 20002: /* pic_height */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 65535);
++ ph[fh.num_pics - 1].height = ul;
++ break;
++
++ case 20003: /* pic_position */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ ph[fh.num_pics - 1].position = ul;
++ break;
++
++ case 20004: /* pic_position_offset */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ ph[fh.num_pics - 1].position_offset = ul;
++ break;
++
++ case 20005: /* pic_anim_type */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ ph[fh.num_pics - 1].anim_type = ul;
++ break;
++
++ case 20006: /* pic_anim_loop */
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ ph[fh.num_pics - 1].anim_loop = ul;
++ break;
++
++
++ case 30000: /* blob */
++ if (fh.num_blobs >= 65535) {
++ fprintf(stderr, "--%s: Blob array full\n",
++ long_options[option_index].name);
++ break;
++ }
++
++ blob_cur = calloc(1, sizeof(struct blob_entry));
++ if (!blob_cur) {
++ fprintf(stderr, "--%s: Out of memory\n",
++ long_options[option_index].name);
++ break;
++ }
++
++ blob_cur->fn = optarg;
++ if (fh.num_pics)
++ blob_cur->header.picture_id = fh.num_pics - 1;
++
++ if (!blob_first)
++ blob_first = blob_cur;
++ if (blob_last)
++ blob_last->next = blob_cur;
++ blob_last = blob_cur;
++ fh.num_blobs++;
++ break;
++
++ case 30001: /* blob_type */
++ if (!blob_cur) {
++ fprintf(stderr, "--%s: No blob selected\n",
++ long_options[option_index].name);
++ break;
++ }
++
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ blob_cur->header.type = ul;
++ break;
++
++ case 30002: /* blob_picture_id */
++ if (!blob_cur) {
++ fprintf(stderr, "--%s: No blob selected\n",
++ long_options[option_index].name);
++ break;
++ }
++
++ ul = strtoul(optarg, NULL, 0);
++ OPT_MAX(ul, 255);
++ blob_cur->header.picture_id = ul;
++ break;
++
++
++
++ case 'h':
++ case '?':
++ default:
++ print_help(argv[0]);
++ goto EXIT;
++ } /* switch (c) */
++ } /* while ((c = getopt_long(...)) != -1) */
++
++ /* Consume and drop lone arguments */
++ while (optind < argc) {
++ ofn = argv[optind];
++ optind++;
++ }
++
++
++ /* Read file lengths */
++ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
++ FILE *f;
++ long pos;
++ int i;
++
++ if (!blob_cur->fn)
++ continue;
++
++ f = fopen(blob_cur->fn, "rb");
++ if (!f)
++ goto ERR_FILE_LEN;
++
++ if (fseek(f, 0, SEEK_END))
++ goto ERR_FILE_LEN;
++
++ pos = ftell(f);
++ if (pos < 0 || pos > (1 << 30))
++ goto ERR_FILE_LEN;
++
++ blob_cur->header.length = pos;
++
++ fclose(f);
++ continue;
++
++ERR_FILE_LEN:
++ fprintf(stderr, "Error getting file length (or too long): %s\n",
++ blob_cur->fn);
++ if (f)
++ fclose(f);
++ continue;
++ }
++
++
++ /* Set magic headers */
++#if __BYTE_ORDER == __BIG_ENDIAN
++ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_BE, 16);
++#elif __BYTE_ORDER == __LITTLE_ENDIAN
++ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_LE, 16);
++#else
++#error
++#endif
++ fh.version = BOOTSPLASH_VERSION;
++
++ /* Set blob counts */
++ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
++ if (blob_cur->header.picture_id < fh.num_pics)
++ ph[blob_cur->header.picture_id].num_blobs++;
++ }
++
++
++ /* Dump structs */
++ dump_file_header(&fh);
++
++ for (ul = 0; ul < fh.num_pics; ul++)
++ dump_pic_header(&ph[ul]);
++
++ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next)
++ dump_blob(blob_cur);
++
++
++ /* Write to file */
++ printf("Writing splash to file: %s\n", ofn);
++ of = fopen(ofn, "wb");
++ if (!of)
++ goto ERR_WRITING;
++
++ if (fwrite(&fh, sizeof(struct splash_file_header), 1, of) != 1)
++ goto ERR_WRITING;
++
++ for (ul = 0; ul < fh.num_pics; ul++) {
++ if (fwrite(&ph[ul], sizeof(struct splash_pic_header), 1, of)
++ != 1)
++ goto ERR_WRITING;
++ }
++
++ blob_cur = blob_first;
++ while (blob_cur) {
++ struct blob_entry *blob_old = blob_cur;
++ FILE *f;
++ char *buf[256];
++ uint32_t left;
++
++ if (fwrite(&blob_cur->header,
++ sizeof(struct splash_blob_header), 1, of) != 1)
++ goto ERR_WRITING;
++
++ if (!blob_cur->header.length || !blob_cur->fn)
++ continue;
++
++ f = fopen(blob_cur->fn, "rb");
++ if (!f)
++ goto ERR_FILE_COPY;
++
++ left = blob_cur->header.length;
++ while (left >= sizeof(buf)) {
++ if (fread(buf, sizeof(buf), 1, f) != 1)
++ goto ERR_FILE_COPY;
++ if (fwrite(buf, sizeof(buf), 1, of) != 1)
++ goto ERR_FILE_COPY;
++ left -= sizeof(buf);
++ }
++ if (left) {
++ if (fread(buf, left, 1, f) != 1)
++ goto ERR_FILE_COPY;
++ if (fwrite(buf, left, 1, of) != 1)
++ goto ERR_FILE_COPY;
++ }
++
++ /* Pad data stream to 16 bytes */
++ if (left % 16) {
++ if (fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
++ 16 - (left % 16), 1, of) != 1)
++ goto ERR_FILE_COPY;
++ }
++
++ fclose(f);
++ blob_cur = blob_cur->next;
++ free(blob_old);
++ continue;
++
++ERR_FILE_COPY:
++ if (f)
++ fclose(f);
++ goto ERR_WRITING;
++ }
++
++ fclose(of);
++
++EXIT:
++ return EXIT_SUCCESS;
++
++
++ERR_WRITING:
++ fprintf(stderr, "Error writing splash.\n");
++ fprintf(stderr, "The output file is probably corrupt.\n");
++ if (of)
++ fclose(of);
++
++ while (blob_cur) {
++ struct blob_entry *blob_old = blob_cur;
++
++ blob_cur = blob_cur->next;
++ free(blob_old);
++ }
++
++ return EXIT_FAILURE;
++}
diff --git a/0413-bootsplash.gitpatch b/0413-bootsplash.gitpatch
new file mode 100644
index 000000000000..124ad077fbc3
--- /dev/null
+++ b/0413-bootsplash.gitpatch
@@ -0,0 +1,162 @@
+diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
+index b35aba5093e8..d4f132eca615 100644
+--- a/Documentation/bootsplash.rst
++++ b/Documentation/bootsplash.rst
+@@ -195,6 +195,16 @@ Hooks - how the bootsplash is integrated
+
+
+
++Crating a bootsplash theme file
++===============================
++
++A simple tool for theme file creation is included in ``tools/bootsplash``.
++
++There is also an example shell script, as an example on how to use the tool
++and in order to generate a reference bootsplash file.
++
++
++
+ FAQ: Frequently Asked Questions
+ ===============================
+
+diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
+index 091b99a17567..5dfced41ba82 100644
+--- a/tools/bootsplash/.gitignore
++++ b/tools/bootsplash/.gitignore
+@@ -1 +1,4 @@
+ bootsplash-packer
++bootsplash
++logo.rgb
++throbber*.rgb
+diff --git a/tools/bootsplash/ajax-loader.gif b/tools/bootsplash/ajax-loader.gif
+new file mode 100644
+index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29
+GIT binary patch
+literal 3208
+zcmc(iX;4#H9>pJdFE7h`I{IF)0|5<6L}(j=N}5%L009EB2nYfyF)E0PvIqo$u!IC;
+z4PgyY5|S9AEh38G)(9eq4TbH7_UHg@yWrlIJ$6smIADL7s^P;_O;ykRc<bJ}b<Y2s
+zU)AOL`#QVCGXW;>9soXl`UC*LwQJXkii*0rx|*7rI2=x7WaRkx_~XZqFJ8R3c=2Kg
+zf@aSAv8+BJ8+^hyay>(QR@t*blbKzsf0}bscEqRc5Hd3o(-N5RyW=zWB*zQw6Zh>*
+z2CROCDAbu#D`)S|J_<lj7Yz9)#_Og>o(lL9Yn3l*+8RdiRD_>iNz$#_IAzCna&Wl5
+zSF_(rRCDD!wi#i8oAm&jYtn2_@VB%2-H*G%bN#|(6R6N?wM)3u`PiGzwuX7qmTgyF
+zpE)h0kuoxQ9?=kW7Y!=R@DmhU9)vwT<ZMc0Y;&y4jY1%TT3z!|H=R-GXDHPiKcVWh
+zY+!etO=DI2rIs8{iFWtPv(Lu|O3u|$F3Sbq;+xF{gTX$#T%m?MUUZy&ug3$=zXgXj
+zrxrf}reg*D3HB~8JyLgl$UCyV?EQ`@OKjW@tGrvh6ZqPD#+m=rK0T{FT01>*EZWzJ
+zrt+=2tqFts72yIp?|gvdLhs8Hfku^Z(){gmN%Y=K#<L1VKWYjwV^JDyeS;Y$p1xw*
+z#3VzfAV>P|%fkvg<hUP3U1Q=Hdgg~ik+2zyAc79kpuA<f*-~l+ZBH3*S2jBrEOF0w
+zrxe9#Vx$SxnL0JE4WeeXY1)ppOIy3@Vvexu&oeIa&QvoD`jBE#Gd7rT{j&OMLz1Wu
+zOEj;)PR^=mxjCG0NOUJb&U;ui6*-`3&wmcQ>Uj~HfIp3CuXqCtYGtJ#me+n+-LmP(
+z*XNuk%!aH8bIE@_Bj46>M*dSro|7<6vZ7WUHh5YQzN$>IJFqCb|CT!wj~R2C2%=q{
+zpt8rzY$aw?W?=Ustv{jo?Ow@<k6~~d?F>ZRkLe<)NItY>Cyhle*wR59dTdF6(@{5^
+zAQBOB*hNtc3bkY-8{Cm$nFS@elbTtSqrt7MB{h_4y+~`!mVa}?c&N>&?P}GqdMuhQ
+z&@TD5Czd((DcG_Su~dKKV)Pj$-qi1WHM8_vc^O4?^!oY|tmK~i!{fjd&@_1E(T~r7
+z_REZy&hMT^ySJB3W7l<L=l9ZMvC<Gz>$4YhR`M(J7S5S~+4Q&3HPa)z%zPpisOp$^
+zTEe99ig2$5_qFr!$;<oK+H}=wcaT3=%Nm!;Kw7MHnU5paWS{tI1+DOU?!7xefZ57L
+ze_iPrUrRQct0FSCtTFLtg*<#jo}Z3{E?T{skj>7A6CJ}PJmRhli>w?LC}Y`#HLGy6
+zMU4<C6_PR!wGq`HQyoWJb;nj8>EhL~dKCN5Ut;U2jd*83ShB<kA1Y@1U)Ar;N|HhS
+znIkwkT(&i5XhkI;xwmC%DvPhGNIi?aY<|8rajSt<ap(2E-#qSPQxAp@jIY@-@>Niu
+zcJB0l9>1Modc?-oM<<M{t-|U0{*W+=Ct2ZY_02y-De{7vW<f^HJQhd1l&4)Gw2oOS
+zm46KASlsKI@J$sA#$$|7D5QMbewIaFv4fXyNbL5Ac~kS&g^#5XHaYBvNxbF3Y2L*6
+ztrn?JmgOFAo1lh99BEb^pp>R<Z&2wFwWd*z2wF6&nmW9}nyMfWMO`hc&zkr2AeBP3
+zj75NZQ8-VthLviI^j@e=FN6wxR@1uCRv<b;Y<3t(dr<e}N%b}FQtKxHi9xU2C!#0Z
+zO2<#(;s&964KtWfkQVi``vIFT7kbT~d;ITb0T9+U1AwIgET*ciil)~4gl;xgoy5M!
+z-UJHerGNh_`lO!vA)%ly=~<}ykhlnQnoP$oqido+`qK(cOpmt^pbhf`n-FQaIK5ix
+zq@=#Sl2Y&s<pe8B!1!YA78W7dA?2Xu9v7QHc?}NN)sx(o6iZ#|kHX64nijZG(yB1J
+zfMQm;1rb5O!-+1Pov;csFu7z>4?<d6>}3g}UJ%@K);kriq>)e*rh%hdqM)5Q)*+O8
+zXm;SEbs@koiYS!9YXIclSg+5m_s~yrW#kKMdiRszg(gCP5HPmP7L)vCf8@fxUh6qY
+z@Z#TmkjzAZX{rwE+q|K~F2v5{_@vt%>yT_a#fF03SFt{0RX<yi^Bg0BS3UHmG;U4d
+z`2QlHs<l7ezUo)s<V^9ZccYv>vDAiaY~K9CgS1O>frXgAjBCS}mEd4mIWZ$=ovd5|
+zR?GRdU}d6+Q`+JRW)|=v7$)X<at#L3(d9WVd8CstDNPh>Nkn3yE`!nAiSCvOB1jKT
+zG<1aK3s<0b0m==egTD#8i(<nFTpHvxfx|aIng5yR81z6E<naz8-Ow^p@sCs8mz=%h
+zO$v$X0NS?ofjnp~62AE}^z%gY8Nsqj=NwUqyj+o6s$@kK@d+U4Vp-^_G32vzv@8nI
+z01{`FL$DXQL%WB*9R<xn7$ya31flsbiVh+-0m=YeB_ocaW;YRxI51d(jP?N!ane91
+z9~^yzJ;S;OWRKC8PrrXYkZCaruNYE>Of=1pGDTOCho0XpIOMQ&P87cVKY1W=C6kIg
+z9cH=@a&zbm2+`|{(_?YC9fdm?1TY~-pwlBn?>=(~1pDKbco6jloP;0-cqRiwV1A_S
+zEyV0Dj8Pwy!nekzaN>{)7rgZ&_QLxK{~1yRe865^<m)Ax^m58MY|zev&92(G7#vQU
+zn~8r)5oUrwM9`}05|I<Nx*n}jlvg&C9_310Dd4OT2txd91Z*_U8bRtrNaq+nGd{E#
+zVGckZFpr^;mv}%%T{jHtz<a=^%;mPXVY7SR`@6_Uw@(0*>yx>}+a!ECd>#MMwddow
+z@CU{l+Rt$xuXuf}?ga{3IAr?Raql^c@a%sI0U5m}HvJ5O1#I%_MMPt#BH>OqUZ{-k
+zt>4Xzz=%jT*FVW(uYkWyx}9Gw$HdN*qU?Bit#ji(Wi7p-u|_8?h^%szIS^s^fNM}b
+zgGy>|=cbEufpguY5_6w~&ZLv=Bo06UF9EYIY;Er-1VK)SyF&!|J{axiE1z^(hXwVq
+zsFS=K-#zC}CcOs^8W{KAt+kK)jYDgDYbCXv{{<mZ_TMxh0{w%6lzzG*pm+Dj4XaZ5
+zoJwkk5)~fyUmzYbwMERR3j)XePHj^2P!5GK`~^RXuEz>rwsgqtIU3<910$CJi)s??
+z_t8k{>7*0~4l~LLF7$WXT5OSq5QCTbP_l!SN|{R}3D&eWA8~0ltWh1IL+ZBX4rRSt
+zWF6Om3WDMu4xK^1(BF`2cL}rUCzhHAB`@j5&R-yk_l*t;mPGY|u2^o|myvcOdrg0W
+z%=lX;f^Vkqfp?u7*4qQq%A3Mpf!xspWBSKS@O%r*TSM}?dl(@*%{0Jm_8;(h{R__M
+Bt<?Yk
+
+literal 0
+HcmV?d00001
+
+diff --git a/tools/bootsplash/bootsplash-tux.sh b/tools/bootsplash/bootsplash-tux.sh
+new file mode 100755
+index 000000000000..1078f87644b9
+--- /dev/null
++++ b/tools/bootsplash/bootsplash-tux.sh
+@@ -0,0 +1,66 @@
++#!/bin/bash
++#
++# A simple script to show how to create a bootsplash.
++# Do with it whatever you wish.
++#
++# This needs ImageMagick for the 'convert' and 'identify' tools.
++#
++
++LOGO=../../Documentation/logo.gif
++LOGO_WIDTH=$(identify $LOGO | cut -d " " -f 3 | cut -d x -f 1)
++LOGO_HEIGHT=$(identify $LOGO | cut -d " " -f 3 | cut -d x -f 2)
++
++THROBBER=ajax-loader.gif
++THROBBER_WIDTH=$(identify $THROBBER | head -1 | cut -d " " -f 3 | \
++ cut -d x -f 1)
++THROBBER_HEIGHT=$(identify $THROBBER | head -1 | cut -d " " -f 3 | \
++ cut -d x -f 2)
++
++convert -alpha remove \
++ -background "#ff3a40" \
++ $LOGO \
++ logo.rgb
++
++convert -alpha remove \
++ -background "#ff3a40" \
++ $THROBBER \
++ throbber%02d.rgb
++
++
++make clean
++make bootsplash-packer
++
++
++# Let's put Tux in the center of an orange background.
++./bootsplash-packer \
++ --bg_red 0xff \
++ --bg_green 0x3a \
++ --bg_blue 0x40 \
++ --frame_ms 48 \
++ --picture \
++ --pic_width $LOGO_WIDTH \
++ --pic_height $LOGO_HEIGHT \
++ --pic_position 0 \
++ --blob logo.rgb \
++ --picture \
++ --pic_width $THROBBER_WIDTH \
++ --pic_height $THROBBER_HEIGHT \
++ --pic_position 0x14 \
++ --pic_position_offset 20 \
++ --pic_anim_type 1 \
++ --pic_anim_loop 0 \
++ --blob throbber00.rgb \
++ --blob throbber01.rgb \
++ --blob throbber02.rgb \
++ --blob throbber03.rgb \
++ --blob throbber04.rgb \
++ --blob throbber05.rgb \
++ --blob throbber06.rgb \
++ --blob throbber07.rgb \
++ --blob throbber08.rgb \
++ --blob throbber09.rgb \
++ --blob throbber10.rgb \
++ --blob throbber11.rgb \
++ bootsplash
++
++rm *.rgb
diff --git a/0999-acs.patch b/0999-acs.patch
new file mode 100644
index 000000000000..9a5fa4865004
--- /dev/null
+++ b/0999-acs.patch
@@ -0,0 +1,127 @@
+--- a/Documentation/admin-guide/kernel-parameters.txt.orig 2021-12-20 11:49:22.121459738 +0300
++++ b/Documentation/admin-guide/kernel-parameters.txt 2021-12-20 11:51:19.127255042 +0300
+@@ -3892,6 +3892,15 @@
+ nomsi [MSI] If the PCI_MSI kernel config parameter is
+ enabled, this kernel boot option can be used to
+ disable the use of MSI interrupts system-wide.
++ pcie_acs_override=
++ [PCIE] Override missing PCIe ACS support for:
++ downstream
++ All downstream ports - full ACS capabilities
++ multfunction
++ All multifunction devices - multifunction ACS subset
++ id:nnnn:nnnn
++ Specfic device - full ACS capabilities
++ Specified as vid:did (vendor/device ID) in hex
+ noioapicquirk [APIC] Disable all boot interrupt quirks.
+ Safety option to keep boot IRQs enabled. This
+ should never be necessary.
+--- a/drivers/pci/quirks.c.ori 2021-12-20 11:49:22.378124432 +0300
++++ b/drivers/pci/quirks.c 2021-12-20 11:54:23.312583171 +0300
+@@ -3588,6 +3588,106 @@
+ dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET;
+ }
+
++static bool acs_on_downstream;
++static bool acs_on_multifunction;
++
++#define NUM_ACS_IDS 16
++struct acs_on_id {
++ unsigned short vendor;
++ unsigned short device;
++};
++static struct acs_on_id acs_on_ids[NUM_ACS_IDS];
++static u8 max_acs_id;
++
++static __init int pcie_acs_override_setup(char *p)
++{
++ if (!p)
++ return -EINVAL;
++
++ while (*p) {
++ if (!strncmp(p, "downstream", 10))
++ acs_on_downstream = true;
++ if (!strncmp(p, "multifunction", 13))
++ acs_on_multifunction = true;
++ if (!strncmp(p, "id:", 3)) {
++ char opt[5];
++ int ret;
++ long val;
++
++ if (max_acs_id >= NUM_ACS_IDS - 1) {
++ pr_warn("Out of PCIe ACS override slots (%d)\n",
++ NUM_ACS_IDS);
++ goto next;
++ }
++
++ p += 3;
++ snprintf(opt, 5, "%s", p);
++ ret = kstrtol(opt, 16, &val);
++ if (ret) {
++ pr_warn("PCIe ACS ID parse error %d\n", ret);
++ goto next;
++ }
++ acs_on_ids[max_acs_id].vendor = val;
++
++ p += strcspn(p, ":");
++ if (*p != ':') {
++ pr_warn("PCIe ACS invalid ID\n");
++ goto next;
++ }
++
++ p++;
++ snprintf(opt, 5, "%s", p);
++ ret = kstrtol(opt, 16, &val);
++ if (ret) {
++ pr_warn("PCIe ACS ID parse error %d\n", ret);
++ goto next;
++ }
++ acs_on_ids[max_acs_id].device = val;
++ max_acs_id++;
++ }
++next:
++ p += strcspn(p, ",");
++ if (*p == ',')
++ p++;
++ }
++
++ if (acs_on_downstream || acs_on_multifunction || max_acs_id)
++ pr_warn("Warning: PCIe ACS overrides enabled; This may allow non-IOMMU protected peer-to-peer DMA\n");
++
++ return 0;
++}
++early_param("pcie_acs_override", pcie_acs_override_setup);
++
++static int pcie_acs_overrides(struct pci_dev *dev, u16 acs_flags)
++{
++ int i;
++
++ /* Never override ACS for legacy devices or devices with ACS caps */
++ if (!pci_is_pcie(dev) ||
++ pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS))
++ return -ENOTTY;
++
++ for (i = 0; i < max_acs_id; i++)
++ if (acs_on_ids[i].vendor == dev->vendor &&
++ acs_on_ids[i].device == dev->device)
++ return 1;
++
++ switch (pci_pcie_type(dev)) {
++ case PCI_EXP_TYPE_DOWNSTREAM:
++ case PCI_EXP_TYPE_ROOT_PORT:
++ if (acs_on_downstream)
++ return 1;
++ break;
++ case PCI_EXP_TYPE_ENDPOINT:
++ case PCI_EXP_TYPE_UPSTREAM:
++ case PCI_EXP_TYPE_LEG_END:
++ case PCI_EXP_TYPE_RC_END:
++ if (acs_on_multifunction && dev->multifunction)
++ return 1;
++ }
++
++ return -ENOTTY;
++}
+ /*
+ * Some NVIDIA GPU devices do not work with bus reset, SBR needs to be
+ * prevented for those affected devices.
diff --git a/1ac8f753e4249e6864c1c42070ba957ceef1f82a.patch b/1ac8f753e4249e6864c1c42070ba957ceef1f82a.patch
new file mode 100644
index 000000000000..01b324a03a17
--- /dev/null
+++ b/1ac8f753e4249e6864c1c42070ba957ceef1f82a.patch
@@ -0,0 +1,21 @@
+From 1ac8f753e4249e6864c1c42070ba957ceef1f82a Mon Sep 17 00:00:00 2001
+From: "Jan Alexander Steffens (heftig)" <heftig@archlinux.org>
+Date: Thu, 18 Nov 2021 22:53:31 +0100
+Subject: [PATCH] PCI: Add more NVIDIA controllers to the MSI masking quirk
+
+For: https://bugs.archlinux.org/task/72734
+For: https://bugs.archlinux.org/task/72777
+---
+ drivers/pci/quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 208fa03acdda00..7fdb7e9c2e12c4 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -5802,3 +5802,5 @@ static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
+ pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
+ }
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab9, nvidia_ion_ahci_fixup);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0d88, nvidia_ion_ahci_fixup);
diff --git a/62f1f7606485d450b23f86bc18dab101e7a2443d.patch b/62f1f7606485d450b23f86bc18dab101e7a2443d.patch
new file mode 100644
index 000000000000..1f7922e34722
--- /dev/null
+++ b/62f1f7606485d450b23f86bc18dab101e7a2443d.patch
@@ -0,0 +1,51 @@
+From 62f1f7606485d450b23f86bc18dab101e7a2443d Mon Sep 17 00:00:00 2001
+From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Date: Thu, 18 Nov 2021 21:18:01 -0800
+Subject: [PATCH] cpufreq: intel_pstate: ITMT support for overclocked system
+
+On systems with overclocking enabled, CPPC Highest Performance can be
+hard coded to 0xff. In this case even if we have cores with different
+highest performance, ITMT can't be enabled as the current implementation
+depends on CPPC Highest Performance.
+
+On such systems we can use MSR_HWP_CAPABILITIES maximum performance field
+when CPPC.Highest Performance is 0xff.
+
+Due to legacy reasons, we can't solely depend on MSR_HWP_CAPABILITIES as
+in some older systems CPPC Highest Performance is the only way to identify
+different performing cores.
+
+Reported-by: Michael Larabel <Michael@MichaelLarabel.com>
+Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+---
+ drivers/cpufreq/intel_pstate.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
+index e15c3bc17a55ce..8a2c6b58b6524f 100644
+--- a/drivers/cpufreq/intel_pstate.c
++++ b/drivers/cpufreq/intel_pstate.c
+@@ -335,6 +335,8 @@ static void intel_pstste_sched_itmt_work_fn(struct work_struct *work)
+
+ static DECLARE_WORK(sched_itmt_work, intel_pstste_sched_itmt_work_fn);
+
++#define CPPC_MAX_PERF U8_MAX
++
+ static void intel_pstate_set_itmt_prio(int cpu)
+ {
+ struct cppc_perf_caps cppc_perf;
+@@ -345,6 +347,14 @@ static void intel_pstate_set_itmt_prio(int cpu)
+ if (ret)
+ return;
+
++ /*
++ * On some systems with overclocking enabled, CPPC.highest_perf is hardcoded to 0xff.
++ * In this case we can't use CPPC.highest_perf to enable ITMT.
++ * In this case we can look at MSR_HWP_CAPABILITIES bits [8:0] to decide.
++ */
++ if (cppc_perf.highest_perf == CPPC_MAX_PERF)
++ cppc_perf.highest_perf = HWP_HIGHEST_PERF(READ_ONCE(all_cpu_data[cpu]->hwp_cap_cached));
++
+ /*
+ * The priorities can be set regardless of whether or not
+ * sched_set_itmt_support(true) has been called and it is valid to
diff --git a/675d4b66de78eec370cf5053eecdf00b26780af3.patch b/675d4b66de78eec370cf5053eecdf00b26780af3.patch
new file mode 100644
index 000000000000..8fbd217c36a2
--- /dev/null
+++ b/675d4b66de78eec370cf5053eecdf00b26780af3.patch
@@ -0,0 +1,36 @@
+From 675d4b66de78eec370cf5053eecdf00b26780af3 Mon Sep 17 00:00:00 2001
+From: Matan Ziv-Av <matan@svgalib.org>
+Date: Tue, 23 Nov 2021 22:14:55 +0200
+Subject: [PATCH] lg-laptop: Recognize more models
+
+LG uses 5 instead of 0 in the third digit (second digit after 2019) of the year string to indicate newer models in the same year. Handle this case as well.
+
+Signed-off-by: Matan Ziv-Av <matan@svgalib.org>
+For: https://bugs.archlinux.org/task/71772
+---
+ drivers/platform/x86/lg-laptop.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c
+index 88b551caeaaf41..d6f74d3a7605e2 100644
+--- a/drivers/platform/x86/lg-laptop.c
++++ b/drivers/platform/x86/lg-laptop.c
+@@ -658,6 +658,18 @@ static int acpi_add(struct acpi_device *device)
+ if (product && strlen(product) > 4)
+ switch (product[4]) {
+ case '5':
++ if (strlen(product) > 5)
++ switch (product[5]) {
++ case 'N':
++ year = 2021;
++ break;
++ case '0':
++ year = 2016;
++ break;
++ default:
++ year = 2022;
++ }
++ break;
+ case '6':
+ year = 2016;
+ break;
diff --git a/74db74ec6ce112c6137d51610429e7ac9ea5b6c1.patch b/74db74ec6ce112c6137d51610429e7ac9ea5b6c1.patch
new file mode 100644
index 000000000000..bc9dc1857912
--- /dev/null
+++ b/74db74ec6ce112c6137d51610429e7ac9ea5b6c1.patch
@@ -0,0 +1,85 @@
+From 74db74ec6ce112c6137d51610429e7ac9ea5b6c1 Mon Sep 17 00:00:00 2001
+From: Ajay Garg <ajaygargnsit@gmail.com>
+Date: Tue, 12 Oct 2021 19:26:53 +0530
+Subject: [PATCH] iommu: intel: do deep dma-unmapping, to avoid
+ kernel-flooding.
+
+Origins at :
+https://lists.linuxfoundation.org/pipermail/iommu/2021-October/thread.html
+
+=== Changes from v1 => v2 ===
+
+a)
+Improved patch-description.
+
+b)
+A more root-level fix, as suggested by
+
+ 1.
+ Alex Williamson <alex.williamson@redhat.com>
+
+ 2.
+ Lu Baolu <baolu.lu@linux.intel.com>
+
+=== Issue ===
+
+Kernel-flooding is seen, when an x86_64 L1 guest (Ubuntu-21) is booted in qemu/kvm
+on a x86_64 host (Ubuntu-21), with a host-pci-device attached.
+
+Following kind of logs, along with the stacktraces, cause the flood :
+
+......
+ DMAR: ERROR: DMA PTE for vPFN 0x428ec already set (to 3f6ec003 not 3f6ec003)
+ DMAR: ERROR: DMA PTE for vPFN 0x428ed already set (to 3f6ed003 not 3f6ed003)
+ DMAR: ERROR: DMA PTE for vPFN 0x428ee already set (to 3f6ee003 not 3f6ee003)
+ DMAR: ERROR: DMA PTE for vPFN 0x428ef already set (to 3f6ef003 not 3f6ef003)
+ DMAR: ERROR: DMA PTE for vPFN 0x428f0 already set (to 3f6f0003 not 3f6f0003)
+......
+
+=== Current Behaviour, leading to the issue ===
+
+Currently, when we do a dma-unmapping, we unmap/unlink the mappings, but
+the pte-entries are not cleared.
+
+Thus, following sequencing would flood the kernel-logs :
+
+i)
+A dma-unmapping makes the real/leaf-level pte-slot invalid, but the
+pte-content itself is not cleared.
+
+ii)
+Now, during some later dma-mapping procedure, as the pte-slot is about
+to hold a new pte-value, the intel-iommu checks if a prior
+pte-entry exists in the pte-slot. If it exists, it logs a kernel-error,
+along with a corresponding stacktrace.
+
+iii)
+Step ii) runs in abundance, and the kernel-logs run insane.
+
+=== Fix ===
+
+We ensure that as part of a dma-unmapping, each (unmapped) pte-slot
+is also cleared of its value/content (at the leaf-level, where the
+real mapping from a iova => pfn mapping is stored).
+
+This completes a "deep" dma-unmapping.
+
+Signed-off-by: Ajay Garg <ajaygargnsit@gmail.com>
+Link: https://lore.kernel.org/linux-iommu/20211012135653.3852-1-ajaygargnsit@gmail.com/
+---
+ drivers/iommu/intel/iommu.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 78f8c8e6803e97..d8da48a91ba3b2 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -5092,6 +5092,8 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
+ gather->freelist = domain_unmap(dmar_domain, start_pfn,
+ last_pfn, gather->freelist);
+
++ dma_pte_clear_range(dmar_domain, start_pfn, last_pfn);
++
+ if (dmar_domain->max_addr == iova + size)
+ dmar_domain->max_addr = iova;
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..fe5fdb54a9f0
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,266 @@
+# Maintainer: Evgeny Myandin <evgeny.myandin[at]gmail[dot]com>
+#
+# This is original kernel of Manjaro Linux + ACS patch
+
+pkgbase=linux515
+pkgname=('linux515' 'linux515-headers')
+_kernelname=-MANJARO-VFIO
+_basekernel=5.15
+_basever=515
+pkgver=5.15.10
+pkgrel=1
+arch=('x86_64')
+url="https://www.kernel.org/"
+license=('GPL2')
+makedepends=('bc'
+ 'docbook-xsl'
+ 'libelf'
+ 'pahole'
+ 'git'
+ 'inetutils'
+ 'kmod'
+ 'xmlto'
+ 'cpio'
+ 'perl'
+ 'tar'
+ 'xz')
+options=('!strip')
+source=("https://www.kernel.org/pub/linux/kernel/v5.x/linux-${_basekernel}.tar.xz"
+ "https://www.kernel.org/pub/linux/kernel/v5.x/patch-${pkgver}.xz"
+ 'config'
+ # ARCH Patches
+ '0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-CLONE_NEWUSER.patch'
+ '0002-HID-quirks-Add-Apple-Magic-Trackpad-2-to-hid_have_special_driver-list.patch'
+ # Temp Fixes
+ # MANJARO Patches
+ '0101-i2c-nuvoton-nc677x-hwmon-driver.patch'
+# '0102-iomap-iomap_bmap-should-accept-unwritten-maps.patch'
+ '0103-futex.patch' # https://github.com/sirlucjan/kernel-patches
+ '0104-revert-xhci-Add-support-for-Renesas-controller-with-memory.patch'
+ '0105-quirk-kernel-org-bug-210681-firmware_rome_error.patch'
+ '0108-drm_i915_Add_workaround_numbers_to_GEN7_COMMON_SLICE_CHICKEN1_whitelisting.patch::https://patchwork.freedesktop.org/patch/463650/raw/'
+ # Arch Patches
+ '1ac8f753e4249e6864c1c42070ba957ceef1f82a.patch'
+ '74db74ec6ce112c6137d51610429e7ac9ea5b6c1.patch'
+ '62f1f7606485d450b23f86bc18dab101e7a2443d.patch'
+ 'ae3386d67597db29ad2ba2685815e224a39897bc.patch'
+ '675d4b66de78eec370cf5053eecdf00b26780af3.patch'
+ # Lenovo + AMD
+ '0201-lenovo-wmi2.patch'
+ # other patches
+ # Bootsplash
+ '0301-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch'
+ '0302-revert-fbcon-remove-no-op-fbcon_set_origin.patch'
+ '0303-revert-fbcon-remove-soft-scrollback-code.patch'
+ '0401-bootsplash.patch'
+ '0402-bootsplash.patch'
+ '0403-bootsplash.patch'
+ '0404-bootsplash.patch'
+ '0405-bootsplash.patch'
+ '0406-bootsplash.patch'
+ '0407-bootsplash.patch'
+ '0408-bootsplash.patch'
+ '0409-bootsplash.patch'
+ '0410-bootsplash.patch'
+ '0411-bootsplash.patch'
+ '0412-bootsplash.patch'
+ '0413-bootsplash.gitpatch'
+ '0999-acs.patch')
+sha256sums=('57b2cf6991910e3b67a1b3490022e8a0674b6965c74c12da1e99d138d1991ee8'
+ 'bdb35ece2dd0f6d8225947b63539e70c8fc16bd28f03395d590515d8187f03c4'
+ 'ccbfb721030426bbd148602f99c88aaf226b7a6641a9c8c56973dd25a3f1df94'
+ '986f8d802f37b72a54256f0ab84da83cb229388d58c0b6750f7c770818a18421'
+ 'df5843818f1571841e1a8bdbe38d7f853d841f38de46d6a6a5765de089495578'
+ '7823d7488f42bc4ed7dfae6d1014dbde679d8b862c9a3697a39ba0dae5918978'
+ '844e66a95d7df754c55ac2f1ce7e215b1e56e20ca095462d926a993d557b20e0'
+ 'd9330ea593829a6ef3b824db9570253280cbff7da2b4beb47cbc037824d1a29b'
+ '5e804e1f241ce542f3f0e83d274ede6aa4b0539e510fb9376f8106e8732ce69b'
+ 'e8e6120035977903a7117ba215809b9b162b64a789848107513f219180baaada'
+ 'e2823eff3355b7c88a3fa327ea2f84f23cbd36569e0a5f0f76599023f63a52ca'
+ 'ce53090a4572cd6162d22225113082f7e4df5028a1230529d170460e26dcf849'
+ 'ab0360eac59329eb84f028c2f402ee4a17e4b3dfacb7957355e6178d35af87b9'
+ '6846fbd7d8e05adc0b25179bc5bbd6320929d155fafd4443eff206d6b8b580ac'
+ 'a2a0a0542055a6a921542fbb05cedb6eb6f3d3fb0c038bfb2304bfd3931a0f71'
+ '1d58ef2991c625f6f0eb33b4cb8303932f53f1c4694e42bae24c9cd36d2ad013'
+ '2b11905b63b05b25807dd64757c779da74dd4c37e36d3f7a46485b1ee5a9d326'
+ '94a8538251ad148f1025cc3de446ce64f73dc32b01815426fb159c722e8fa5bc'
+ '1f18c5c10a3c63e41ecd05ad34cd9f6653ba96e9f1049ce2b7bb6da2578ae710'
+ '59202940d4f12bad23c194a530edc900e066866c9945e39748484a6545af96de'
+ 'e096b127a5208f56d368d2cb938933454d7200d70c86b763aa22c38e0ddb8717'
+ '8c1c880f2caa9c7ae43281a35410203887ea8eae750fe8d360d0c8bf80fcc6e0'
+ '1144d51e5eb980fceeec16004f3645ed04a60fac9e0c7cf88a15c5c1e7a4b89e'
+ 'dd4b69def2efacf4a6c442202ad5cb93d492c03886d7c61de87696e5a83e2846'
+ '028b07f0c954f70ca37237b62e04103e81f7c658bb8bd65d7d3c2ace301297dc'
+ 'a0c548c5703d25ae34b57931f1162de8b18937e676e5791a0f039922090881e7'
+ '8dbb5ab3cb99e48d97d4e2f2e3df5d0de66f3721b4f7fd94a708089f53245c77'
+ 'a7aefeacf22c600fafd9e040a985a913643095db7272c296b77a0a651c6a140a'
+ 'e9f22cbb542591087d2d66dc6dc912b1434330ba3cd13d2df741d869a2c31e89'
+ '27471eee564ca3149dd271b0817719b5565a9594dc4d884fe3dc51a5f03832bc'
+ '60e295601e4fb33d9bf65f198c54c7eb07c0d1e91e2ad1e0dd6cd6e142cb266d'
+ '035ea4b2a7621054f4560471f45336b981538a40172d8f17285910d4e0e0b3ef'
+ 'b00dcd459248e57e1f1799e07d4c6aba9f147bb67b86b9f386e16e2268d89214')
+
+prepare() {
+ cd "linux-${_basekernel}"
+
+ # add upstream patch
+ msg "add upstream patch"
+ patch -p1 -i "../patch-${pkgver}"
+
+ local src
+ for src in "${source[@]}"; do
+ src="${src%%::*}"
+ src="${src##*/}"
+ [[ $src = *.patch ]] || continue
+ msg2 "Applying patch: $src..."
+ patch -Np1 < "../$src"
+ done
+
+ msg2 "0513-bootsplash"
+ git apply -p1 < "../0413-bootsplash.gitpatch"
+
+ msg2 "add config"
+ cat "../config" > ./.config
+
+ if [ "${_kernelname}" != "" ]; then
+ sed -i "s|CONFIG_LOCALVERSION=.*|CONFIG_LOCALVERSION=\"${_kernelname}\"|g" ./.config
+ sed -i "s|CONFIG_LOCALVERSION_AUTO=.*|CONFIG_LOCALVERSION_AUTO=n|" ./.config
+ fi
+
+ msg "set extraversion to pkgrel"
+ sed -ri "s|^(EXTRAVERSION =).*|\1 -${pkgrel}|" Makefile
+
+ # set patchlevel to 14
+ #sed -ri "s|^(PATCHLEVEL =).*|\1 14|" Makefile
+
+ msg "don't run depmod on 'make install'"
+ # We'll do this ourselves in packaging
+ sed -i '2iexit 0' scripts/depmod.sh
+
+ msg "get kernel version"
+ make prepare
+
+ msg "rewrite configuration"
+ yes "" | make config >/dev/null
+}
+
+build() {
+ cd "linux-${_basekernel}"
+
+ msg "build"
+ make ${MAKEFLAGS} LOCALVERSION= bzImage modules
+}
+
+package_linux515() {
+ pkgdesc="The ${pkgbase/linux/Linux} kernel and modules"
+ depends=('coreutils' 'linux-firmware' 'kmod' 'mkinitcpio>=27')
+ optdepends=('crda: to set the correct wireless channels of your country')
+ provides=("linux=${pkgver}" VIRTUALBOX-GUEST-MODULES WIREGUARD-MODULE)
+
+ cd "linux-${_basekernel}"
+
+ # get kernel version
+ _kernver="$(make LOCALVERSION= kernelrelease)"
+
+ mkdir -p "${pkgdir}"/{boot,usr/lib/modules}
+ make LOCALVERSION= INSTALL_MOD_PATH="${pkgdir}/usr" INSTALL_MOD_STRIP=1 modules_install
+
+ # systemd expects to find the kernel here to allow hibernation
+ # https://github.com/systemd/systemd/commit/edda44605f06a41fb86b7ab8128dcf99161d2344
+ cp arch/x86/boot/bzImage "${pkgdir}/usr/lib/modules/${_kernver}/vmlinuz"
+
+ # Used by mkinitcpio to name the kernel
+ echo "${pkgbase}" | install -Dm644 /dev/stdin "${pkgdir}/usr/lib/modules/${_kernver}/pkgbase"
+ echo "${_basekernel}-${CARCH}" | install -Dm644 /dev/stdin "${pkgdir}/usr/lib/modules/${_kernver}/kernelbase"
+
+ # add kernel version
+ echo "${pkgver}-${pkgrel}-MANJARO x64" > "${pkgdir}/boot/${pkgbase}-${CARCH}.kver"
+
+ # make room for external modules
+ local _extramodules="extramodules-${_basekernel}${_kernelname:--MANJARO}"
+ ln -s "../${_extramodules}" "${pkgdir}/usr/lib/modules/${_kernver}/extramodules"
+
+ # add real version for building modules and running depmod from hook
+ echo "${_kernver}" |
+ install -Dm644 /dev/stdin "${pkgdir}/usr/lib/modules/${_extramodules}/version"
+
+ # remove build and source links
+ rm "${pkgdir}"/usr/lib/modules/${_kernver}/{source,build}
+
+ # now we call depmod...
+ depmod -b "${pkgdir}/usr" -F System.map "${_kernver}"
+}
+
+package_linux515-headers() {
+ pkgdesc="Header files and scripts for building modules for ${pkgbase/linux/Linux} kernel"
+ depends=('gawk' 'python' 'libelf' 'pahole')
+ provides=("linux-headers=$pkgver")
+
+ cd "linux-${_basekernel}"
+ local _builddir="${pkgdir}/usr/lib/modules/${_kernver}/build"
+
+ install -Dt "${_builddir}" -m644 Makefile .config Module.symvers
+ install -Dt "${_builddir}/kernel" -m644 kernel/Makefile
+ install -Dt "${_builddir}" -m644 vmlinux
+
+ mkdir "${_builddir}/.tmp_versions"
+
+ cp -t "${_builddir}" -a include scripts
+
+ install -Dt "${_builddir}/arch/x86" -m644 "arch/x86/Makefile"
+ install -Dt "${_builddir}/arch/x86/kernel" -m644 "arch/x86/kernel/asm-offsets.s"
+
+ cp -t "${_builddir}/arch/x86" -a "arch/x86/include"
+
+ install -Dt "${_builddir}/drivers/md" -m644 drivers/md/*.h
+ install -Dt "${_builddir}/net/mac80211" -m644 net/mac80211/*.h
+
+ # https://bugs.archlinux.org/task/13146
+ install -Dt "${_builddir}/drivers/media/i2c" -m644 drivers/media/i2c/msp3400-driver.h
+
+ # https://bugs.archlinux.org/task/20402
+ install -Dt "${_builddir}/drivers/media/usb/dvb-usb" -m644 drivers/media/usb/dvb-usb/*.h
+ install -Dt "${_builddir}/drivers/media/dvb-frontends" -m644 drivers/media/dvb-frontends/*.h
+ install -Dt "${_builddir}/drivers/media/tuners" -m644 drivers/media/tuners/*.h
+
+ # https://bugs.archlinux.org/task/71392
+ install -Dt "${_builddir}/drivers/iio/common/hid-sensors" -m644 drivers/iio/common/hid-sensors/*.h
+
+ # add xfs and shmem for aufs building
+ mkdir -p "${_builddir}"/{fs/xfs,mm}
+
+ # copy in Kconfig files
+ find . -name Kconfig\* -exec install -Dm644 {} "${_builddir}/{}" \;
+
+ # add objtool for external module building and enabled VALIDATION_STACK option
+ install -Dt "${_builddir}/tools/objtool" tools/objtool/objtool
+
+ # remove unneeded architectures
+ local _arch
+ for _arch in "${_builddir}"/arch/*/; do
+ [[ ${_arch} == */x86/ ]] && continue
+ rm -r "${_arch}"
+ done
+
+ # remove documentation files
+ rm -r "${_builddir}/Documentation"
+
+ # strip scripts directory
+ local file
+ while read -rd '' file; do
+ case "$(file -bi "$file")" in
+ application/x-sharedlib\;*) # Libraries (.so)
+ strip $STRIP_SHARED "$file" ;;
+ application/x-archive\;*) # Libraries (.a)
+ strip $STRIP_STATIC "$file" ;;
+ application/x-executable\;*) # Binaries
+ strip $STRIP_BINARIES "$file" ;;
+ application/x-pie-executable\;*) # Relocatable binaries
+ strip $STRIP_SHARED "$file" ;;
+ esac
+ done < <(find "${_builddir}" -type f -perm -u+x ! -name vmlinux -print0 2>/dev/null)
+ strip $STRIP_STATIC "${_builddir}/vmlinux"
+
+ # remove unwanted files
+ find ${_builddir} -name '*.orig' -delete
+}
diff --git a/ae3386d67597db29ad2ba2685815e224a39897bc.patch b/ae3386d67597db29ad2ba2685815e224a39897bc.patch
new file mode 100644
index 000000000000..e22b5cca4c74
--- /dev/null
+++ b/ae3386d67597db29ad2ba2685815e224a39897bc.patch
@@ -0,0 +1,57 @@
+From ae3386d67597db29ad2ba2685815e224a39897bc Mon Sep 17 00:00:00 2001
+From: Kiran K <kiran.k@intel.com>
+Date: Wed, 13 Oct 2021 13:35:11 +0530
+Subject: [PATCH] Bluetooth: btintel: Fix bdaddress comparison with garbage
+ value
+
+Intel Read Verision(TLV) data is parsed into a local structure variable
+and it contains a field for bd address. Bd address is returned only in
+bootloader mode and hence bd address in TLV structure needs to be validated
+only if controller is present in boot loader mode.
+
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Reviewed-by: Tedd Ho-Jeong An <tedd.an@intel.com>
+---
+ drivers/bluetooth/btintel.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
+index f1705b46fc8898..b9055a3e61ed76 100644
+--- a/drivers/bluetooth/btintel.c
++++ b/drivers/bluetooth/btintel.c
+@@ -2006,14 +2006,16 @@ static int btintel_prepare_fw_download_tlv(struct hci_dev *hdev,
+ if (ver->img_type == 0x03) {
+ btintel_clear_flag(hdev, INTEL_BOOTLOADER);
+ btintel_check_bdaddr(hdev);
+- }
+-
+- /* If the OTP has no valid Bluetooth device address, then there will
+- * also be no valid address for the operational firmware.
+- */
+- if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) {
+- bt_dev_info(hdev, "No device address configured");
+- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
++ } else {
++ /*
++ * Check for valid bd address in boot loader mode. Device
++ * will be marked as unconfigured if empty bd address is
++ * found.
++ */
++ if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) {
++ bt_dev_info(hdev, "No device address configured");
++ set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
++ }
+ }
+
+ btintel_get_fw_name_tlv(ver, fwname, sizeof(fwname), "sfi");
+@@ -2303,6 +2305,10 @@ static int btintel_setup_combined(struct hci_dev *hdev)
+ goto exit_error;
+ }
+
++ /* memset ver_tlv to start with clean state as few fields are exclusive
++ * to bootloader mode and are not populated in operational mode
++ */
++ memset(&ver_tlv, 0, sizeof(ver_tlv));
+ /* For TLV type device, parse the tlv data */
+ err = btintel_parse_version_tlv(hdev, &ver_tlv, skb);
+ if (err) {
diff --git a/config b/config
new file mode 100644
index 000000000000..c92606e06c25
--- /dev/null
+++ b/config
@@ -0,0 +1,10680 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 5.15.5-2 Kernel Configuration
+#
+CONFIG_CC_VERSION_TEXT="gcc (GCC) 11.1.0"
+CONFIG_CC_IS_GCC=y
+CONFIG_GCC_VERSION=110100
+CONFIG_CLANG_VERSION=0
+CONFIG_AS_IS_GNU=y
+CONFIG_AS_VERSION=23601
+CONFIG_LD_IS_BFD=y
+CONFIG_LD_VERSION=23601
+CONFIG_LLD_VERSION=0
+CONFIG_CC_CAN_LINK=y
+CONFIG_CC_CAN_LINK_STATIC=y
+CONFIG_CC_HAS_ASM_GOTO=y
+CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
+CONFIG_CC_HAS_ASM_INLINE=y
+CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_TABLE_SORT=y
+CONFIG_THREAD_INFO_IN_TASK=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+# CONFIG_COMPILE_TEST is not set
+# CONFIG_WERROR is not set
+CONFIG_LOCALVERSION="-MANJARO"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_BUILD_SALT=""
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_HAVE_KERNEL_ZSTD=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_KERNEL_ZSTD=y
+CONFIG_DEFAULT_INIT=""
+CONFIG_DEFAULT_HOSTNAME="manjaro"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_WATCH_QUEUE=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_USELIB is not set
+CONFIG_AUDIT=y
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
+CONFIG_GENERIC_IRQ_INJECTION=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_SIM=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_IRQ_MSI_IOMMU=y
+CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
+CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_GENERIC_IRQ_DEBUGFS is not set
+# end of IRQ subsystem
+
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+# CONFIG_NO_HZ_FULL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+# end of Timers subsystem
+
+CONFIG_BPF=y
+CONFIG_HAVE_EBPF_JIT=y
+CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
+
+#
+# BPF subsystem
+#
+CONFIG_BPF_SYSCALL=y
+CONFIG_BPF_JIT=y
+CONFIG_BPF_JIT_ALWAYS_ON=y
+CONFIG_BPF_JIT_DEFAULT_ON=y
+# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
+# CONFIG_BPF_PRELOAD is not set
+CONFIG_BPF_LSM=y
+# end of BPF subsystem
+
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_PREEMPTION=y
+CONFIG_PREEMPT_DYNAMIC=y
+CONFIG_SCHED_CORE=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_SCHED_AVG_IRQ=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_PSI=y
+# CONFIG_PSI_DEFAULT_DISABLED is not set
+# end of CPU/Task time and stats accounting
+
+CONFIG_CPU_ISOLATION=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_EXPERT=y
+CONFIG_SRCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_TASKS_RCU_GENERIC=y
+CONFIG_TASKS_RCU=y
+CONFIG_TASKS_RUDE_RCU=y
+CONFIG_TASKS_TRACE_RCU=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+CONFIG_RCU_FANOUT=64
+CONFIG_RCU_FANOUT_LEAF=16
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_DELAY=500
+# CONFIG_RCU_NOCB_CPU is not set
+# CONFIG_TASKS_TRACE_RCU_READ_MB is not set
+# end of RCU Subsystem
+
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_IKHEADERS=m
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
+CONFIG_PRINTK_INDEX=y
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+
+#
+# Scheduler features
+#
+CONFIG_UCLAMP_TASK=y
+CONFIG_UCLAMP_BUCKETS_COUNT=5
+# end of Scheduler features
+
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
+CONFIG_CC_HAS_INT128=y
+CONFIG_ARCH_SUPPORTS_INT128=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
+CONFIG_CGROUPS=y
+CONFIG_PAGE_COUNTER=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_WRITEBACK=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_UCLAMP_TASK_GROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_MISC=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_SOCK_CGROUP_DATA=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_TIME_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_USER_NS_UNPRIVILEGED=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+CONFIG_RD_ZSTD=y
+CONFIG_BOOT_CONFIG=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_LD_ORPHAN_WARN=y
+CONFIG_SYSCTL=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+CONFIG_SGETMASK_SYSCALL=y
+CONFIG_SYSFS_SYSCALL=y
+CONFIG_FHANDLE=y
+CONFIG_POSIX_TIMERS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_FUTEX_PI=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_IO_URING=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_HAVE_ARCH_USERFAULTFD_WP=y
+CONFIG_HAVE_ARCH_USERFAULTFD_MINOR=y
+CONFIG_MEMBARRIER=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_USERFAULTFD=y
+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
+CONFIG_KCMP=y
+CONFIG_RSEQ=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# end of Kernel Performance Events And Counters
+
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLAB_MERGE_DEFAULT=y
+CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
+CONFIG_SHUFFLE_PAGE_ALLOCATOR=y
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SYSTEM_DATA_VERIFICATION=y
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# end of General setup
+
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=28
+CONFIG_ARCH_MMAP_RND_BITS_MAX=32
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_FILTER_PGPROT=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_NR_GPIO=1024
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_HAVE_INTEL_TXT=y
+CONFIG_X86_64_SMP=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_DYNAMIC_PHYSICAL_MASK=y
+CONFIG_PGTABLE_LEVELS=5
+CONFIG_CC_HAS_SANE_STACKPROTECTOR=y
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+CONFIG_X86_FEATURE_NAMES=y
+CONFIG_X86_X2APIC=y
+CONFIG_X86_MPPARSE=y
+# CONFIG_GOLDFISH is not set
+CONFIG_RETPOLINE=y
+CONFIG_X86_CPU_RESCTRL=y
+# CONFIG_X86_EXTENDED_PLATFORM is not set
+CONFIG_X86_INTEL_LPSS=y
+CONFIG_X86_AMD_PLATFORM_DEVICE=y
+CONFIG_IOSF_MBI=y
+# CONFIG_IOSF_MBI_DEBUG is not set
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_HYPERVISOR_GUEST=y
+CONFIG_PARAVIRT=y
+CONFIG_PARAVIRT_XXL=y
+# CONFIG_PARAVIRT_DEBUG is not set
+CONFIG_PARAVIRT_SPINLOCKS=y
+CONFIG_X86_HV_CALLBACK_VECTOR=y
+CONFIG_XEN=y
+CONFIG_XEN_PV=y
+CONFIG_XEN_512GB=y
+CONFIG_XEN_PV_SMP=y
+CONFIG_XEN_PV_DOM0=y
+CONFIG_XEN_PVHVM=y
+CONFIG_XEN_PVHVM_SMP=y
+CONFIG_XEN_PVHVM_GUEST=y
+CONFIG_XEN_SAVE_RESTORE=y
+# CONFIG_XEN_DEBUG_FS is not set
+CONFIG_XEN_PVH=y
+CONFIG_XEN_DOM0=y
+CONFIG_KVM_GUEST=y
+CONFIG_ARCH_CPUIDLE_HALTPOLL=y
+CONFIG_PVH=y
+CONFIG_PARAVIRT_TIME_ACCOUNTING=y
+CONFIG_PARAVIRT_CLOCK=y
+CONFIG_JAILHOUSE_GUEST=y
+CONFIG_ACRN_GUEST=y
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_IA32_FEAT_CTL=y
+CONFIG_X86_VMX_FEATURE_NAMES=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_HYGON=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_ZHAOXIN=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+# CONFIG_GART_IOMMU is not set
+# CONFIG_MAXSMP is not set
+CONFIG_NR_CPUS_RANGE_BEGIN=2
+CONFIG_NR_CPUS_RANGE_END=512
+CONFIG_NR_CPUS_DEFAULT=64
+CONFIG_NR_CPUS=320
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_MC_PRIO=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCELOG_LEGACY is not set
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_AMD=y
+CONFIG_X86_MCE_THRESHOLD=y
+CONFIG_X86_MCE_INJECT=m
+
+#
+# Performance monitoring
+#
+CONFIG_PERF_EVENTS_INTEL_UNCORE=m
+CONFIG_PERF_EVENTS_INTEL_RAPL=m
+CONFIG_PERF_EVENTS_INTEL_CSTATE=m
+CONFIG_PERF_EVENTS_AMD_POWER=m
+CONFIG_PERF_EVENTS_AMD_UNCORE=m
+# end of Performance monitoring
+
+CONFIG_X86_16BIT=y
+CONFIG_X86_ESPFIX64=y
+CONFIG_X86_VSYSCALL_EMULATION=y
+CONFIG_X86_IOPL_IOPERM=y
+CONFIG_I8K=m
+CONFIG_MICROCODE=y
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+# CONFIG_MICROCODE_OLD_INTERFACE is not set
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_5LEVEL=y
+CONFIG_X86_DIRECT_GBPAGES=y
+CONFIG_X86_CPA_STATISTICS=y
+CONFIG_AMD_MEM_ENCRYPT=y
+# CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT is not set
+CONFIG_NUMA=y
+CONFIG_AMD_NUMA=y
+CONFIG_X86_64_ACPI_NUMA=y
+# CONFIG_NUMA_EMU is not set
+CONFIG_NODES_SHIFT=5
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+# CONFIG_ARCH_MEMORY_PROBE is not set
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_X86_PMEM_LEGACY_DEVICE=y
+CONFIG_X86_PMEM_LEGACY=m
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=0
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_RANDOM=y
+CONFIG_X86_SMAP=y
+CONFIG_X86_UMIP=y
+CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y
+# CONFIG_X86_INTEL_TSX_MODE_OFF is not set
+# CONFIG_X86_INTEL_TSX_MODE_ON is not set
+CONFIG_X86_INTEL_TSX_MODE_AUTO=y
+CONFIG_X86_SGX=y
+CONFIG_EFI=y
+CONFIG_EFI_STUB=y
+CONFIG_EFI_MIXED=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
+CONFIG_ARCH_HAS_KEXEC_PURGATORY=y
+# CONFIG_KEXEC_SIG is not set
+CONFIG_CRASH_DUMP=y
+CONFIG_KEXEC_JUMP=y
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_RELOCATABLE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_X86_NEED_RELOCS=y
+CONFIG_PHYSICAL_ALIGN=0x200000
+CONFIG_DYNAMIC_MEMORY_LAYOUT=y
+CONFIG_RANDOMIZE_MEMORY=y
+CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
+# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
+# CONFIG_COMPAT_VDSO is not set
+# CONFIG_LEGACY_VSYSCALL_EMULATE is not set
+CONFIG_LEGACY_VSYSCALL_XONLY=y
+# CONFIG_LEGACY_VSYSCALL_NONE is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MODIFY_LDT_SYSCALL=y
+CONFIG_HAVE_LIVEPATCH=y
+# CONFIG_LIVEPATCH is not set
+# end of Processor type and features
+
+CONFIG_ARCH_HAS_ADD_PAGES=y
+CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
+CONFIG_USE_PERCPU_NUMA_NODE_ID=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_ARCH_HIBERNATION_HEADER=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATE_CALLBACKS=y
+CONFIG_HIBERNATION=y
+CONFIG_HIBERNATION_SNAPSHOT_DEV=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
+CONFIG_PM_CLK=y
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
+CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
+CONFIG_ENERGY_MODEL=y
+CONFIG_ARCH_SUPPORTS_ACPI=y
+CONFIG_ACPI=y
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_DEBUGGER is not set
+CONFIG_ACPI_SPCR_TABLE=y
+CONFIG_ACPI_FPDT=y
+CONFIG_ACPI_LPIT=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y
+CONFIG_ACPI_EC_DEBUGFS=m
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=y
+CONFIG_ACPI_TAD=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_CPU_FREQ_PSS=y
+CONFIG_ACPI_PROCESSOR_CSTATE=y
+CONFIG_ACPI_PROCESSOR_IDLE=y
+CONFIG_ACPI_CPPC_LIB=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_IPMI=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_PROCESSOR_AGGREGATOR=m
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_PLATFORM_PROFILE=m
+CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
+CONFIG_ACPI_TABLE_UPGRADE=y
+CONFIG_ACPI_DEBUG=y
+CONFIG_ACPI_PCI_SLOT=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HOTPLUG_MEMORY=y
+CONFIG_ACPI_HOTPLUG_IOAPIC=y
+CONFIG_ACPI_SBS=m
+CONFIG_ACPI_HED=y
+CONFIG_ACPI_CUSTOM_METHOD=m
+CONFIG_ACPI_BGRT=y
+CONFIG_ACPI_NFIT=m
+# CONFIG_NFIT_SECURITY_DEBUG is not set
+CONFIG_ACPI_NUMA=y
+CONFIG_ACPI_HMAT=y
+CONFIG_HAVE_ACPI_APEI=y
+CONFIG_HAVE_ACPI_APEI_NMI=y
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=y
+CONFIG_ACPI_APEI_PCIEAER=y
+CONFIG_ACPI_APEI_MEMORY_FAILURE=y
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_ERST_DEBUG=m
+CONFIG_ACPI_DPTF=y
+CONFIG_DPTF_POWER=m
+CONFIG_DPTF_PCH_FIVR=m
+CONFIG_ACPI_WATCHDOG=y
+CONFIG_ACPI_EXTLOG=m
+CONFIG_ACPI_ADXL=y
+CONFIG_ACPI_CONFIGFS=m
+CONFIG_PMIC_OPREGION=y
+CONFIG_BYTCRC_PMIC_OPREGION=y
+CONFIG_CHTCRC_PMIC_OPREGION=y
+CONFIG_XPOWER_PMIC_OPREGION=y
+CONFIG_BXT_WC_PMIC_OPREGION=y
+CONFIG_CHT_WC_PMIC_OPREGION=y
+CONFIG_CHT_DC_TI_PMIC_OPREGION=y
+CONFIG_TPS68470_PMIC_OPREGION=y
+CONFIG_ACPI_VIOT=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_PRMT=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+
+#
+# CPU frequency scaling drivers
+#
+CONFIG_X86_INTEL_PSTATE=y
+CONFIG_X86_PCC_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_ACPI_CPUFREQ_CPB=y
+CONFIG_X86_POWERNOW_K8=m
+CONFIG_X86_AMD_FREQ_SENSITIVITY=m
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+CONFIG_X86_P4_CLOCKMOD=m
+
+#
+# shared options
+#
+CONFIG_X86_SPEEDSTEP_LIB=m
+# end of CPU Frequency scaling
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_IDLE_GOV_TEO=y
+CONFIG_CPU_IDLE_GOV_HALTPOLL=y
+CONFIG_HALTPOLL_CPUIDLE=m
+# end of CPU Idle
+
+CONFIG_INTEL_IDLE=y
+# end of Power management and ACPI options
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_XEN=y
+CONFIG_MMCONF_FAM10H=y
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+# end of Bus options (PCI etc.)
+
+#
+# Binary Emulations
+#
+CONFIG_IA32_EMULATION=y
+# CONFIG_X86_X32 is not set
+CONFIG_COMPAT_32=y
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+# end of Binary Emulations
+
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_IRQFD=y
+CONFIG_HAVE_KVM_IRQ_ROUTING=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_HAVE_KVM_MSI=y
+CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
+CONFIG_KVM_VFIO=y
+CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
+CONFIG_KVM_COMPAT=y
+CONFIG_HAVE_KVM_IRQ_BYPASS=y
+CONFIG_HAVE_KVM_NO_POLL=y
+CONFIG_KVM_XFER_TO_GUEST_WORK=y
+CONFIG_HAVE_KVM_PM_NOTIFIER=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_X86_SGX_KVM=y
+CONFIG_KVM_AMD=m
+CONFIG_KVM_AMD_SEV=y
+CONFIG_KVM_XEN=y
+CONFIG_KVM_MMU_AUDIT=y
+CONFIG_AS_AVX512=y
+CONFIG_AS_SHA1_NI=y
+CONFIG_AS_SHA256_NI=y
+CONFIG_AS_TPAUSE=y
+
+#
+# General architecture-dependent options
+#
+CONFIG_CRASH_CORE=y
+CONFIG_KEXEC_CORE=y
+CONFIG_HOTPLUG_SMT=y
+CONFIG_GENERIC_ENTRY=y
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_STATIC_CALL_SELFTEST is not set
+CONFIG_OPTPROBES=y
+CONFIG_KPROBES_ON_FTRACE=y
+CONFIG_UPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_KRETPROBES=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
+CONFIG_HAVE_NMI=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_ARCH_WANTS_NO_INSTR=y
+CONFIG_HAVE_ASM_MODVERSIONS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
+CONFIG_MMU_GATHER_TABLE_FREE=y
+CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
+CONFIG_HAVE_ARCH_SECCOMP=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP=y
+CONFIG_SECCOMP_FILTER=y
+# CONFIG_SECCOMP_CACHE_DEBUG is not set
+CONFIG_HAVE_ARCH_STACKLEAK=y
+CONFIG_HAVE_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
+CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y
+CONFIG_LTO_NONE=y
+CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_CONTEXT_TRACKING_OFFSTACK=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOVE_PUD=y
+CONFIG_HAVE_MOVE_PMD=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS=28
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
+CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
+CONFIG_HAVE_STACK_VALIDATION=y
+CONFIG_HAVE_RELIABLE_STACKTRACE=y
+CONFIG_ISA_BUS_API=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_VMAP_STACK=y
+CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y
+CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_STRICT_MODULE_RWX=y
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
+CONFIG_ARCH_USE_MEMREMAP_PROT=y
+CONFIG_LOCK_EVENT_COUNTS=y
+CONFIG_ARCH_HAS_MEM_ENCRYPT=y
+CONFIG_ARCH_HAS_CC_PLATFORM=y
+CONFIG_HAVE_STATIC_CALL=y
+CONFIG_HAVE_STATIC_CALL_INLINE=y
+CONFIG_HAVE_PREEMPT_DYNAMIC=y
+CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_HAS_ELFCORE_COMPAT=y
+CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+# end of GCOV-based kernel profiling
+
+CONFIG_HAVE_GCC_PLUGINS=y
+CONFIG_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set
+# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set
+# end of General architecture-dependent options
+
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULE_SIG_FORMAT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_FORCE is not set
+CONFIG_MODULE_SIG_ALL=y
+# CONFIG_MODULE_SIG_SHA1 is not set
+# CONFIG_MODULE_SIG_SHA224 is not set
+# CONFIG_MODULE_SIG_SHA256 is not set
+# CONFIG_MODULE_SIG_SHA384 is not set
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_MODULE_SIG_HASH="sha512"
+# CONFIG_MODULE_COMPRESS_NONE is not set
+# CONFIG_MODULE_COMPRESS_GZIP is not set
+CONFIG_MODULE_COMPRESS_XZ=y
+# CONFIG_MODULE_COMPRESS_ZSTD is not set
+CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y
+CONFIG_MODPROBE_PATH="/sbin/modprobe"
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+CONFIG_BLK_RQ_ALLOC_TIME=y
+CONFIG_BLK_CGROUP_RWSTAT=y
+CONFIG_BLK_DEV_BSG_COMMON=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_INTEGRITY_T10=y
+CONFIG_BLK_DEV_ZONED=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_BLK_DEV_THROTTLING_LOW=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_WBT_MQ=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
+CONFIG_BLK_CGROUP_FC_APPID=y
+CONFIG_BLK_CGROUP_IOCOST=y
+CONFIG_BLK_CGROUP_IOPRIO=y
+CONFIG_BLK_DEBUG_FS=y
+CONFIG_BLK_DEBUG_FS_ZONED=y
+CONFIG_BLK_SED_OPAL=y
+CONFIG_BLK_INLINE_ENCRYPTION=y
+CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_AIX_PARTITION=y
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_CMDLINE_PARTITION is not set
+# end of Partition Types
+
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_BLK_MQ_RDMA=y
+CONFIG_BLK_PM=y
+CONFIG_BLOCK_HOLDER_DEPRECATED=y
+
+#
+# IO Schedulers
+#
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+# CONFIG_BFQ_CGROUP_DEBUG is not set
+# end of IO Schedulers
+
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+CONFIG_ASN1=y
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_FREEZER=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+CONFIG_BINFMT_MISC=y
+CONFIG_COREDUMP=y
+# end of Executable file formats
+
+#
+# Memory Management options
+#
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_FAST_GUP=y
+CONFIG_NUMA_KEEP_MEMINFO=y
+CONFIG_MEMORY_ISOLATION=y
+CONFIG_HAVE_BOOTMEM_INFO_NODE=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_MHP_MEMMAP_ON_MEMORY=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+CONFIG_MEMORY_BALLOON=y
+CONFIG_BALLOON_COMPACTION=y
+CONFIG_COMPACTION=y
+CONFIG_PAGE_REPORTING=y
+CONFIG_MIGRATION=y
+CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
+CONFIG_ARCH_ENABLE_THP_MIGRATION=y
+CONFIG_CONTIG_ALLOC=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_MEMORY_FAILURE=y
+CONFIG_HWPOISON_INJECT=m
+CONFIG_TRANSPARENT_HUGEPAGE=y
+# CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set
+CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_THP_SWAP=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+CONFIG_CMA_DEBUGFS=y
+CONFIG_CMA_SYSFS=y
+CONFIG_CMA_AREAS=7
+CONFIG_MEM_SOFT_DIRTY=y
+CONFIG_ZSWAP=y
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842 is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set
+CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y
+CONFIG_ZSWAP_COMPRESSOR_DEFAULT="zstd"
+# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD is not set
+CONFIG_ZSWAP_ZPOOL_DEFAULT_Z3FOLD=y
+# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC is not set
+CONFIG_ZSWAP_ZPOOL_DEFAULT="z3fold"
+CONFIG_ZSWAP_DEFAULT_ON=y
+CONFIG_ZPOOL=y
+CONFIG_ZBUD=y
+CONFIG_Z3FOLD=y
+CONFIG_ZSMALLOC=y
+# CONFIG_ZSMALLOC_STAT is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
+CONFIG_PAGE_IDLE_FLAG=y
+CONFIG_IDLE_PAGE_TRACKING=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_PTE_DEVMAP=y
+CONFIG_ZONE_DMA=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ZONE_DEVICE=y
+CONFIG_DEV_PAGEMAP_OPS=y
+CONFIG_HMM_MIRROR=y
+CONFIG_DEVICE_PRIVATE=y
+CONFIG_VMAP_PFN=y
+CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
+CONFIG_ARCH_HAS_PKEYS=y
+# CONFIG_PERCPU_STATS is not set
+# CONFIG_GUP_TEST is not set
+CONFIG_READ_ONLY_THP_FOR_FS=y
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_MAPPING_DIRTY_HELPERS=y
+CONFIG_SECRETMEM=y
+
+#
+# Data Access Monitoring
+#
+# CONFIG_DAMON is not set
+# end of Data Access Monitoring
+# end of Memory Management options
+
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+CONFIG_NET_INGRESS=y
+CONFIG_NET_EGRESS=y
+CONFIG_NET_REDIRECT=y
+CONFIG_SKB_EXTENSIONS=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_SCM=y
+CONFIG_AF_UNIX_OOB=y
+CONFIG_UNIX_DIAG=m
+CONFIG_TLS=m
+CONFIG_TLS_DEVICE=y
+# CONFIG_TLS_TOE is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_OFFLOAD=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_USER_COMPAT is not set
+CONFIG_XFRM_INTERFACE=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_XFRM_AH=m
+CONFIG_XFRM_ESP=m
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_XFRM_ESPINTCP=y
+CONFIG_SMC=m
+CONFIG_SMC_DIAG=m
+CONFIG_XDP_SOCKETS=y
+CONFIG_XDP_SOCKETS_DIAG=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_CLASSID=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IP_TUNNEL=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE_COMMON=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
+CONFIG_NET_UDP_TUNNEL=m
+CONFIG_NET_FOU=m
+CONFIG_NET_FOU_IP_TUNNELS=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_ESP_OFFLOAD=m
+CONFIG_INET_ESPINTCP=y
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_INET_UDP_DIAG=m
+CONFIG_INET_RAW_DIAG=m
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_NV=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_TCP_CONG_DCTCP=m
+CONFIG_TCP_CONG_CDG=m
+CONFIG_TCP_CONG_BBR=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_ESP_OFFLOAD=m
+CONFIG_INET6_ESPINTCP=y
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_IPV6_ILA=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_VTI=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_FOU=m
+CONFIG_IPV6_FOU_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_IPV6_SEG6_LWTUNNEL=y
+CONFIG_IPV6_SEG6_HMAC=y
+CONFIG_IPV6_SEG6_BPF=y
+CONFIG_IPV6_RPL_LWTUNNEL=y
+CONFIG_IPV6_IOAM6_LWTUNNEL=y
+CONFIG_NETLABEL=y
+CONFIG_MPTCP=y
+CONFIG_INET_MPTCP_DIAG=m
+CONFIG_MPTCP_IPV6=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=m
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_INGRESS=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_FAMILY_BRIDGE=y
+CONFIG_NETFILTER_FAMILY_ARP=y
+CONFIG_NETFILTER_NETLINK_HOOK=m
+CONFIG_NETFILTER_NETLINK_ACCT=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_NETLINK_OSF=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_LOG_SYSLOG=m
+CONFIG_NETFILTER_CONNCOUNT=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_LABELS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_GRE=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_BROADCAST=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NF_CT_NETLINK_TIMEOUT=m
+CONFIG_NF_CT_NETLINK_HELPER=m
+CONFIG_NETFILTER_NETLINK_GLUE_CT=y
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_REDIRECT=y
+CONFIG_NF_NAT_MASQUERADE=y
+CONFIG_NETFILTER_SYNPROXY=m
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=y
+CONFIG_NF_TABLES_NETDEV=y
+CONFIG_NFT_NUMGEN=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_FLOW_OFFLOAD=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_CONNLIMIT=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_MASQ=m
+CONFIG_NFT_REDIR=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_TUNNEL=m
+CONFIG_NFT_OBJREF=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_QUOTA=m
+CONFIG_NFT_REJECT=m
+CONFIG_NFT_REJECT_INET=m
+CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_FIB=m
+CONFIG_NFT_FIB_INET=m
+CONFIG_NFT_XFRM=m
+CONFIG_NFT_SOCKET=m
+CONFIG_NFT_OSF=m
+CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
+CONFIG_NF_DUP_NETDEV=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
+CONFIG_NFT_FIB_NETDEV=m
+CONFIG_NFT_REJECT_NETDEV=m
+CONFIG_NF_FLOW_TABLE_INET=m
+CONFIG_NF_FLOW_TABLE=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XTABLES_COMPAT=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+CONFIG_NETFILTER_XT_SET=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_NAT=m
+CONFIG_NETFILTER_XT_TARGET_NETMAP=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=m
+CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CGROUP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ECN=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_L2TP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# end of Core Netfilter Configuration
+
+CONFIG_IP_SET=m
+CONFIG_IP_SET_MAX=256
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_IPMAC=m
+CONFIG_IP_SET_HASH_MAC=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=15
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_FO=m
+CONFIG_IP_VS_OVF=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_MH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_TWOS=m
+
+#
+# IPVS SH scheduler
+#
+CONFIG_IP_VS_SH_TAB_BITS=8
+
+#
+# IPVS MH scheduler
+#
+CONFIG_IP_VS_MH_TAB_INDEX=12
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PE_SIP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_SOCKET_IPV4=m
+CONFIG_NF_TPROXY_IPV4=m
+CONFIG_NF_TABLES_IPV4=y
+CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
+CONFIG_NFT_FIB_IPV4=m
+CONFIG_NF_TABLES_ARP=y
+CONFIG_NF_FLOW_TABLE_IPV4=m
+CONFIG_NF_DUP_IPV4=m
+CONFIG_NF_LOG_ARP=m
+CONFIG_NF_LOG_IPV4=m
+CONFIG_NF_REJECT_IPV4=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# end of IP: Netfilter Configuration
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_SOCKET_IPV6=m
+CONFIG_NF_TPROXY_IPV6=m
+CONFIG_NF_TABLES_IPV6=y
+CONFIG_NFT_REJECT_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_NFT_FIB_IPV6=m
+CONFIG_NF_FLOW_TABLE_IPV6=m
+CONFIG_NF_DUP_IPV6=m
+CONFIG_NF_REJECT_IPV6=m
+CONFIG_NF_LOG_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_SRH=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_IP6_NF_NAT=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+# end of IPv6: Netfilter Configuration
+
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
+CONFIG_NFT_BRIDGE_REJECT=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+# CONFIG_BPFILTER is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set
+CONFIG_SCTP_COOKIE_HMAC_MD5=y
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_INET_SCTP_DIAG=m
+CONFIG_RDS=m
+CONFIG_RDS_RDMA=m
+CONFIG_RDS_TCP=m
+# CONFIG_RDS_DEBUG is not set
+CONFIG_TIPC=m
+CONFIG_TIPC_MEDIA_IB=y
+CONFIG_TIPC_MEDIA_UDP=y
+CONFIG_TIPC_CRYPTO=y
+CONFIG_TIPC_DIAG=m
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_MRP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_BRIDGE_MRP=y
+CONFIG_BRIDGE_CFM=y
+CONFIG_NET_DSA=m
+CONFIG_NET_DSA_TAG_AR9331=m
+CONFIG_NET_DSA_TAG_BRCM_COMMON=m
+CONFIG_NET_DSA_TAG_BRCM=m
+CONFIG_NET_DSA_TAG_BRCM_LEGACY=m
+CONFIG_NET_DSA_TAG_BRCM_PREPEND=m
+CONFIG_NET_DSA_TAG_HELLCREEK=m
+CONFIG_NET_DSA_TAG_GSWIP=m
+CONFIG_NET_DSA_TAG_DSA_COMMON=m
+CONFIG_NET_DSA_TAG_DSA=m
+CONFIG_NET_DSA_TAG_EDSA=m
+CONFIG_NET_DSA_TAG_MTK=m
+CONFIG_NET_DSA_TAG_KSZ=m
+CONFIG_NET_DSA_TAG_RTL4_A=m
+CONFIG_NET_DSA_TAG_OCELOT=m
+CONFIG_NET_DSA_TAG_OCELOT_8021Q=m
+CONFIG_NET_DSA_TAG_QCA=m
+CONFIG_NET_DSA_TAG_LAN9303=m
+CONFIG_NET_DSA_TAG_SJA1105=m
+CONFIG_NET_DSA_TAG_TRAILER=m
+CONFIG_NET_DSA_TAG_XRS700X=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+CONFIG_PHONET=m
+CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_DEBUGFS=y
+CONFIG_6LOWPAN_NHC=m
+CONFIG_6LOWPAN_NHC_DEST=m
+CONFIG_6LOWPAN_NHC_FRAGMENT=m
+CONFIG_6LOWPAN_NHC_HOP=m
+CONFIG_6LOWPAN_NHC_IPV6=m
+CONFIG_6LOWPAN_NHC_MOBILITY=m
+CONFIG_6LOWPAN_NHC_ROUTING=m
+CONFIG_6LOWPAN_NHC_UDP=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
+CONFIG_IEEE802154=m
+CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y
+CONFIG_IEEE802154_SOCKET=m
+CONFIG_IEEE802154_6LOWPAN=m
+CONFIG_MAC802154=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_CBS=m
+CONFIG_NET_SCH_ETF=m
+CONFIG_NET_SCH_TAPRIO=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_SKBPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_NET_SCH_CAKE=m
+CONFIG_NET_SCH_FQ=m
+CONFIG_NET_SCH_HHF=m
+CONFIG_NET_SCH_PIE=m
+CONFIG_NET_SCH_FQ_PIE=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_SCH_ETS=m
+CONFIG_NET_SCH_DEFAULT=y
+# CONFIG_DEFAULT_FQ is not set
+# CONFIG_DEFAULT_CODEL is not set
+CONFIG_DEFAULT_FQ_CODEL=y
+# CONFIG_DEFAULT_FQ_PIE is not set
+# CONFIG_DEFAULT_SFQ is not set
+# CONFIG_DEFAULT_PFIFO_FAST is not set
+CONFIG_DEFAULT_NET_SCH="fq_codel"
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_NET_CLS_BPF=m
+CONFIG_NET_CLS_FLOWER=m
+CONFIG_NET_CLS_MATCHALL=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_EMATCH_CANID=m
+CONFIG_NET_EMATCH_IPSET=m
+CONFIG_NET_EMATCH_IPT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_SAMPLE=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_MPLS=m
+CONFIG_NET_ACT_VLAN=m
+CONFIG_NET_ACT_BPF=m
+CONFIG_NET_ACT_CONNMARK=m
+CONFIG_NET_ACT_CTINFO=m
+CONFIG_NET_ACT_SKBMOD=m
+CONFIG_NET_ACT_IFE=m
+CONFIG_NET_ACT_TUNNEL_KEY=m
+CONFIG_NET_ACT_CT=m
+CONFIG_NET_ACT_GATE=m
+CONFIG_NET_IFE_SKBMARK=m
+CONFIG_NET_IFE_SKBPRIO=m
+CONFIG_NET_IFE_SKBTCINDEX=m
+CONFIG_NET_TC_SKB_EXT=y
+CONFIG_NET_SCH_FIFO=y
+CONFIG_DCB=y
+CONFIG_DNS_RESOLVER=m
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_BATMAN_V=y
+CONFIG_BATMAN_ADV_BLA=y
+CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
+# CONFIG_BATMAN_ADV_DEBUG is not set
+# CONFIG_BATMAN_ADV_TRACING is not set
+CONFIG_OPENVSWITCH=m
+CONFIG_OPENVSWITCH_GRE=m
+CONFIG_OPENVSWITCH_VXLAN=m
+CONFIG_OPENVSWITCH_GENEVE=m
+CONFIG_VSOCKETS=m
+CONFIG_VSOCKETS_DIAG=m
+CONFIG_VSOCKETS_LOOPBACK=m
+CONFIG_VMWARE_VMCI_VSOCKETS=m
+CONFIG_VIRTIO_VSOCKETS=m
+CONFIG_VIRTIO_VSOCKETS_COMMON=m
+CONFIG_HYPERV_VSOCKETS=m
+CONFIG_NETLINK_DIAG=m
+CONFIG_MPLS=y
+CONFIG_NET_MPLS_GSO=m
+CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
+CONFIG_NET_NSH=m
+CONFIG_HSR=m
+CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_L3_MASTER_DEV=y
+CONFIG_QRTR=m
+CONFIG_QRTR_SMD=m
+CONFIG_QRTR_TUN=m
+CONFIG_QRTR_MHI=m
+CONFIG_NET_NCSI=y
+CONFIG_NCSI_OEM_CMD_GET_MAC=y
+CONFIG_NCSI_OEM_CMD_KEEP_PHY=y
+CONFIG_PCPU_DEV_REFCNT=y
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+CONFIG_XPS=y
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_CGROUP_NET_CLASSID=y
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_BPF_STREAM_PARSER=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_DROP_MONITOR=y
+# end of Network testing
+# end of Networking options
+
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_YAM=m
+# end of AX.25 network device drivers
+
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_ISOTP=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_VXCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_JANZ_ICAN3=m
+CONFIG_CAN_KVASER_PCIEFD=m
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+CONFIG_CAN_C_CAN_PCI=m
+CONFIG_CAN_CC770=m
+# CONFIG_CAN_CC770_ISA is not set
+CONFIG_CAN_CC770_PLATFORM=m
+CONFIG_CAN_IFI_CANFD=m
+CONFIG_CAN_M_CAN=m
+CONFIG_CAN_M_CAN_PCI=m
+CONFIG_CAN_M_CAN_PLATFORM=m
+CONFIG_CAN_M_CAN_TCAN4X5X=m
+CONFIG_CAN_PEAK_PCIEFD=m
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_EMS_PCI=m
+# CONFIG_CAN_EMS_PCMCIA is not set
+CONFIG_CAN_F81601=m
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PEAK_PCI=m
+CONFIG_CAN_PEAK_PCIEC=y
+CONFIG_CAN_PEAK_PCMCIA=m
+CONFIG_CAN_PLX_PCI=m
+# CONFIG_CAN_SJA1000_ISA is not set
+CONFIG_CAN_SJA1000_PLATFORM=m
+CONFIG_CAN_SOFTING=m
+CONFIG_CAN_SOFTING_CS=m
+
+#
+# CAN SPI interfaces
+#
+CONFIG_CAN_HI311X=m
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_MCP251XFD=m
+# CONFIG_CAN_MCP251XFD_SANITY is not set
+# end of CAN SPI interfaces
+
+#
+# CAN USB interfaces
+#
+CONFIG_CAN_8DEV_USB=m
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
+CONFIG_CAN_ETAS_ES58X=m
+CONFIG_CAN_GS_USB=m
+CONFIG_CAN_KVASER_USB=m
+CONFIG_CAN_MCBA_USB=m
+CONFIG_CAN_PEAK_USB=m
+CONFIG_CAN_UCAN=m
+# end of CAN USB interfaces
+
+# CONFIG_CAN_DEBUG_DEVICES is not set
+# end of CAN Device Drivers
+
+CONFIG_BT=m
+CONFIG_BT_BREDR=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+# CONFIG_BT_HS is not set
+CONFIG_BT_LE=y
+CONFIG_BT_6LOWPAN=m
+CONFIG_BT_LEDS=y
+CONFIG_BT_MSFTEXT=y
+CONFIG_BT_AOSPEXT=y
+CONFIG_BT_DEBUGFS=y
+# CONFIG_BT_SELFTEST is not set
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_INTEL=m
+CONFIG_BT_BCM=m
+CONFIG_BT_RTL=m
+CONFIG_BT_QCA=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTUSB_AUTOSUSPEND=y
+CONFIG_BT_HCIBTUSB_BCM=y
+CONFIG_BT_HCIBTUSB_MTK=y
+CONFIG_BT_HCIBTUSB_RTL=y
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_SERDEV=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_NOKIA=m
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIUART_INTEL=y
+CONFIG_BT_HCIUART_BCM=y
+CONFIG_BT_HCIUART_RTL=y
+CONFIG_BT_HCIUART_QCA=y
+CONFIG_BT_HCIUART_AG6XX=y
+CONFIG_BT_HCIUART_MRVL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_BT_ATH3K=m
+CONFIG_BT_MTKSDIO=m
+CONFIG_BT_MTKUART=m
+CONFIG_BT_HCIRSI=m
+CONFIG_BT_VIRTIO=m
+# end of Bluetooth device drivers
+
+CONFIG_AF_RXRPC=m
+CONFIG_AF_RXRPC_IPV6=y
+# CONFIG_AF_RXRPC_INJECT_LOSS is not set
+CONFIG_AF_RXRPC_DEBUG=y
+CONFIG_RXKAD=y
+CONFIG_AF_KCM=m
+CONFIG_STREAM_PARSER=y
+CONFIG_MCTP=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
+CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_CFG80211_WEXT_EXPORT=y
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=m
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_XEN=m
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+CONFIG_CEPH_LIB=m
+CONFIG_CEPH_LIB_PRETTYDEBUG=y
+CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y
+CONFIG_NFC=m
+CONFIG_NFC_DIGITAL=m
+CONFIG_NFC_NCI=m
+CONFIG_NFC_NCI_SPI=m
+CONFIG_NFC_NCI_UART=m
+CONFIG_NFC_HCI=m
+CONFIG_NFC_SHDLC=y
+
+#
+# Near Field Communication (NFC) devices
+#
+CONFIG_NFC_TRF7970A=m
+CONFIG_NFC_MEI_PHY=m
+CONFIG_NFC_SIM=m
+CONFIG_NFC_PORT100=m
+CONFIG_NFC_VIRTUAL_NCI=m
+CONFIG_NFC_FDP=m
+CONFIG_NFC_FDP_I2C=m
+CONFIG_NFC_PN544=m
+CONFIG_NFC_PN544_I2C=m
+CONFIG_NFC_PN544_MEI=m
+CONFIG_NFC_PN533=m
+CONFIG_NFC_PN533_USB=m
+CONFIG_NFC_PN533_I2C=m
+CONFIG_NFC_PN532_UART=m
+CONFIG_NFC_MICROREAD=m
+CONFIG_NFC_MICROREAD_I2C=m
+CONFIG_NFC_MICROREAD_MEI=m
+CONFIG_NFC_MRVL=m
+CONFIG_NFC_MRVL_USB=m
+CONFIG_NFC_MRVL_UART=m
+CONFIG_NFC_MRVL_I2C=m
+CONFIG_NFC_MRVL_SPI=m
+CONFIG_NFC_ST21NFCA=m
+CONFIG_NFC_ST21NFCA_I2C=m
+CONFIG_NFC_ST_NCI=m
+CONFIG_NFC_ST_NCI_I2C=m
+CONFIG_NFC_ST_NCI_SPI=m
+CONFIG_NFC_NXP_NCI=m
+CONFIG_NFC_NXP_NCI_I2C=m
+CONFIG_NFC_S3FWRN5=m
+CONFIG_NFC_S3FWRN5_I2C=m
+CONFIG_NFC_S3FWRN82_UART=m
+CONFIG_NFC_ST95HF=m
+# end of Near Field Communication (NFC) devices
+
+CONFIG_PSAMPLE=m
+CONFIG_NET_IFE=m
+CONFIG_LWTUNNEL=y
+CONFIG_LWTUNNEL_BPF=y
+CONFIG_DST_CACHE=y
+CONFIG_GRO_CELLS=y
+CONFIG_SOCK_VALIDATE_XMIT=y
+CONFIG_NET_SELFTESTS=m
+CONFIG_NET_SOCK_MSG=y
+CONFIG_NET_DEVLINK=y
+CONFIG_PAGE_POOL=y
+CONFIG_FAILOVER=m
+CONFIG_ETHTOOL_NETLINK=y
+
+#
+# Device Drivers
+#
+CONFIG_HAVE_EISA=y
+# CONFIG_EISA is not set
+CONFIG_HAVE_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEAER_INJECT=m
+CONFIG_PCIE_ECRC=y
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+CONFIG_PCIE_DPC=y
+CONFIG_PCIE_PTM=y
+CONFIG_PCIE_EDR=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+CONFIG_PCI_STUB=y
+CONFIG_PCI_PF_STUB=m
+CONFIG_XEN_PCIDEV_FRONTEND=m
+CONFIG_PCI_ATS=y
+CONFIG_PCI_LOCKLESS_CONFIG=y
+CONFIG_PCI_IOV=y
+CONFIG_PCI_PRI=y
+CONFIG_PCI_PASID=y
+CONFIG_PCI_P2PDMA=y
+CONFIG_PCI_LABEL=y
+CONFIG_PCI_HYPERV=m
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_ACPI=y
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=y
+
+#
+# PCI controller drivers
+#
+CONFIG_VMD=m
+CONFIG_PCI_HYPERV_INTERFACE=m
+
+#
+# DesignWare PCI Core Support
+#
+CONFIG_PCIE_DW=y
+CONFIG_PCIE_DW_HOST=y
+CONFIG_PCIE_DW_PLAT=y
+CONFIG_PCIE_DW_PLAT_HOST=y
+CONFIG_PCI_MESON=y
+# end of DesignWare PCI Core Support
+
+#
+# Mobiveil PCIe Core Support
+#
+# end of Mobiveil PCIe Core Support
+
+#
+# Cadence PCIe controllers support
+#
+# end of Cadence PCIe controllers support
+# end of PCI controller drivers
+
+#
+# PCI Endpoint
+#
+# CONFIG_PCI_ENDPOINT is not set
+# end of PCI Endpoint
+
+#
+# PCI switch controller drivers
+#
+CONFIG_PCI_SW_SWITCHTEC=m
+# end of PCI switch controller drivers
+
+CONFIG_CXL_BUS=m
+CONFIG_CXL_MEM=m
+# CONFIG_CXL_MEM_RAW_COMMANDS is not set
+CONFIG_CXL_ACPI=m
+CONFIG_CXL_PMEM=m
+CONFIG_PCCARD=m
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=y
+# CONFIG_RAPIDIO is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_AUXILIARY_BUS=y
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Firmware loader
+#
+CONFIG_FW_LOADER=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER is not set
+CONFIG_FW_LOADER_COMPRESS=y
+CONFIG_FW_CACHE=y
+# end of Firmware loader
+
+CONFIG_WANT_DEV_COREDUMP=y
+CONFIG_ALLOW_DEV_COREDUMP=y
+CONFIG_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+CONFIG_HMEM_REPORTING=y
+# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
+CONFIG_SYS_HYPERVISOR=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CPU_VULNERABILITIES=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SLIMBUS=m
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_W1=m
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGMAP_IRQ=y
+CONFIG_REGMAP_SOUNDWIRE=m
+CONFIG_REGMAP_SOUNDWIRE_MBQ=m
+CONFIG_REGMAP_SCCB=m
+CONFIG_REGMAP_SPI_AVMM=m
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_DMA_FENCE_TRACE is not set
+# end of Generic Driver Options
+
+#
+# Bus devices
+#
+CONFIG_MHI_BUS=m
+# CONFIG_MHI_BUS_DEBUG is not set
+CONFIG_MHI_BUS_PCI_GENERIC=m
+# end of Bus devices
+
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Firmware Drivers
+#
+
+#
+# ARM System Control and Management Interface Protocol
+#
+# end of ARM System Control and Management Interface Protocol
+
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DMIID=y
+CONFIG_DMI_SYSFS=y
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+CONFIG_ISCSI_IBFT_FIND=y
+CONFIG_ISCSI_IBFT=m
+CONFIG_FW_CFG_SYSFS=m
+# CONFIG_FW_CFG_SYSFS_CMDLINE is not set
+CONFIG_SYSFB=y
+# CONFIG_SYSFB_SIMPLEFB is not set
+CONFIG_GOOGLE_FIRMWARE=y
+# CONFIG_GOOGLE_SMI is not set
+CONFIG_GOOGLE_COREBOOT_TABLE=m
+CONFIG_GOOGLE_MEMCONSOLE=m
+# CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set
+CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=m
+CONFIG_GOOGLE_VPD=m
+
+#
+# EFI (Extensible Firmware Interface) Support
+#
+# CONFIG_EFI_VARS is not set
+CONFIG_EFI_ESRT=y
+CONFIG_EFI_VARS_PSTORE=y
+CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y
+CONFIG_EFI_RUNTIME_MAP=y
+# CONFIG_EFI_FAKE_MEMMAP is not set
+CONFIG_EFI_SOFT_RESERVE=y
+CONFIG_EFI_RUNTIME_WRAPPERS=y
+CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
+CONFIG_EFI_BOOTLOADER_CONTROL=m
+CONFIG_EFI_CAPSULE_LOADER=m
+# CONFIG_EFI_TEST is not set
+CONFIG_APPLE_PROPERTIES=y
+# CONFIG_RESET_ATTACK_MITIGATION is not set
+CONFIG_EFI_RCI2_TABLE=y
+# CONFIG_EFI_DISABLE_PCI_DMA is not set
+# end of EFI (Extensible Firmware Interface) Support
+
+CONFIG_EFI_EMBEDDED_FIRMWARE=y
+CONFIG_UEFI_CPER=y
+CONFIG_UEFI_CPER_X86=y
+CONFIG_EFI_DEV_PATH_PARSER=y
+CONFIG_EFI_EARLYCON=y
+CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
+
+#
+# Tegra firmware driver
+#
+# end of Tegra firmware driver
+# end of Firmware Drivers
+
+CONFIG_GNSS=m
+CONFIG_GNSS_SERIAL=m
+CONFIG_GNSS_MTK_SERIAL=m
+CONFIG_GNSS_SIRF_SERIAL=m
+CONFIG_GNSS_UBX_SERIAL=m
+CONFIG_MTD=m
+# CONFIG_MTD_TESTS is not set
+
+#
+# Partition parsers
+#
+# CONFIG_MTD_AR7_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# end of Partition parsers
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+
+#
+# Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK.
+#
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# end of RAM/ROM/Flash chip drivers
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+CONFIG_MTD_PLATRAM=m
+# end of Mapping drivers for chip access
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_MCHP23K256 is not set
+# CONFIG_MTD_MCHP48L640 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_PHRAM=m
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# end of Self-contained MTD device drivers
+
+#
+# NAND
+#
+CONFIG_MTD_NAND_CORE=m
+# CONFIG_MTD_ONENAND is not set
+CONFIG_MTD_RAW_NAND=m
+
+#
+# Raw/parallel NAND flash controllers
+#
+# CONFIG_MTD_NAND_DENALI_PCI is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_MXIC is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_ARASAN is not set
+
+#
+# Misc
+#
+CONFIG_MTD_NAND_NANDSIM=m
+# CONFIG_MTD_NAND_RICOH is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_SPI_NAND is not set
+
+#
+# ECC engine support
+#
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_ECC_SW_HAMMING=y
+CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
+CONFIG_MTD_NAND_ECC_SW_BCH=y
+# end of ECC engine support
+# end of NAND
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# end of LPDDR & LPDDR2 PCM memory drivers
+
+CONFIG_MTD_SPI_NOR=m
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set
+CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y
+# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set
+CONFIG_SPI_INTEL_SPI=m
+CONFIG_SPI_INTEL_SPI_PCI=m
+CONFIG_SPI_INTEL_SPI_PLATFORM=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+# CONFIG_MTD_HYPERBUS is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+CONFIG_PARPORT_PC_FIFO=y
+CONFIG_PARPORT_PC_SUPERIO=y
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_AX88796=m
+CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_NULL_BLK=m
+CONFIG_BLK_DEV_FD=m
+CONFIG_CDROM=m
+# CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
+CONFIG_ZRAM=m
+# CONFIG_ZRAM_DEF_COMP_LZORLE is not set
+CONFIG_ZRAM_DEF_COMP_ZSTD=y
+# CONFIG_ZRAM_DEF_COMP_LZ4 is not set
+# CONFIG_ZRAM_DEF_COMP_LZO is not set
+# CONFIG_ZRAM_DEF_COMP_LZ4HC is not set
+# CONFIG_ZRAM_DEF_COMP_842 is not set
+CONFIG_ZRAM_DEF_COMP="zstd"
+CONFIG_ZRAM_WRITEBACK=y
+# CONFIG_ZRAM_MEMORY_TRACKING is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
+# CONFIG_DRBD_FAULT_INJECTION is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_XEN_BLKDEV_BACKEND=m
+CONFIG_VIRTIO_BLK=m
+CONFIG_BLK_DEV_RBD=m
+CONFIG_BLK_DEV_RSXX=m
+CONFIG_BLK_DEV_RNBD=y
+CONFIG_BLK_DEV_RNBD_CLIENT=m
+CONFIG_BLK_DEV_RNBD_SERVER=m
+
+#
+# NVME Support
+#
+CONFIG_NVME_CORE=y
+CONFIG_BLK_DEV_NVME=y
+CONFIG_NVME_MULTIPATH=y
+CONFIG_NVME_HWMON=y
+CONFIG_NVME_FABRICS=m
+CONFIG_NVME_RDMA=m
+CONFIG_NVME_FC=m
+CONFIG_NVME_TCP=m
+CONFIG_NVME_TARGET=m
+CONFIG_NVME_TARGET_PASSTHRU=y
+CONFIG_NVME_TARGET_LOOP=m
+CONFIG_NVME_TARGET_RDMA=m
+CONFIG_NVME_TARGET_FC=m
+CONFIG_NVME_TARGET_FCLOOP=m
+CONFIG_NVME_TARGET_TCP=m
+# end of NVME Support
+
+#
+# Misc devices
+#
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+# CONFIG_DUMMY_IRQ is not set
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_HP_ILO=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_VMWARE_BALLOON=m
+CONFIG_LATTICE_ECP3_CONFIG=m
+# CONFIG_SRAM is not set
+CONFIG_DW_XDATA_PCIE=m
+CONFIG_PCI_ENDPOINT_TEST=m
+CONFIG_XILINX_SDFEC=m
+CONFIG_MISC_RTSX=m
+CONFIG_C2PORT=m
+CONFIG_C2PORT_DURAMAR_2150=m
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=m
+# CONFIG_EEPROM_AT25 is not set
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+# CONFIG_EEPROM_93XX46 is not set
+CONFIG_EEPROM_IDT_89HPESX=m
+CONFIG_EEPROM_EE1004=m
+# end of EEPROM support
+
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+
+#
+# Texas Instruments shared transport line discipline
+#
+CONFIG_TI_ST=m
+# end of Texas Instruments shared transport line discipline
+
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_ALTERA_STAPL=m
+CONFIG_INTEL_MEI=m
+CONFIG_INTEL_MEI_ME=m
+CONFIG_INTEL_MEI_TXE=m
+CONFIG_INTEL_MEI_HDCP=m
+CONFIG_VMWARE_VMCI=m
+CONFIG_GENWQE=m
+CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY=0
+CONFIG_ECHO=m
+CONFIG_BCM_VK=m
+CONFIG_BCM_VK_TTY=y
+CONFIG_MISC_ALCOR_PCI=m
+CONFIG_MISC_RTSX_PCI=m
+CONFIG_MISC_RTSX_USB=m
+CONFIG_HABANA_AI=m
+CONFIG_UACCE=m
+CONFIG_PVPANIC=y
+CONFIG_PVPANIC_MMIO=m
+CONFIG_PVPANIC_PCI=m
+# end of Misc devices
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI_COMMON=y
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_BLK_DEV_BSG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+CONFIG_SCSI_SRP_ATTRS=m
+# end of SCSI Transports
+
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+CONFIG_SCSI_BNX2X_FCOE=m
+CONFIG_BE2ISCSI=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_HPSA=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+CONFIG_AIC94XX_DEBUG=y
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_MVSAS_DEBUG=y
+CONFIG_SCSI_MVSAS_TASKLET=y
+CONFIG_SCSI_MVUMI=m
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_SCSI_ESAS2R=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_MPT3SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+CONFIG_SCSI_MPT3SAS_MAX_SGE=128
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_MPI3MR=m
+CONFIG_SCSI_SMARTPQI=m
+CONFIG_SCSI_UFSHCD=m
+CONFIG_SCSI_UFSHCD_PCI=m
+# CONFIG_SCSI_UFS_DWC_TC_PCI is not set
+CONFIG_SCSI_UFSHCD_PLATFORM=m
+CONFIG_SCSI_UFS_CDNS_PLATFORM=m
+# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
+CONFIG_SCSI_UFS_BSG=y
+CONFIG_SCSI_UFS_CRYPTO=y
+CONFIG_SCSI_UFS_HPB=y
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+CONFIG_SCSI_FLASHPOINT=y
+CONFIG_SCSI_MYRB=m
+CONFIG_SCSI_MYRS=m
+CONFIG_VMWARE_PVSCSI=m
+CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_HYPERV_STORAGE=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_FCOE=m
+CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_SNIC=m
+# CONFIG_SCSI_SNIC_DEBUG_FS is not set
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_FDOMAIN=m
+CONFIG_SCSI_FDOMAIN_PCI=m
+CONFIG_SCSI_ISCI=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_TCM_QLA2XXX=m
+# CONFIG_TCM_QLA2XXX_DEBUG is not set
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_QEDI=m
+CONFIG_QEDF=m
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+CONFIG_SCSI_EFCT=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_AM53C974=m
+CONFIG_SCSI_WD719X=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_SCSI_PMCRAID=m
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_BFA_FC=m
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_CHELSIO_FCOE=m
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+# end of SCSI device support
+
+CONFIG_ATA=y
+CONFIG_SATA_HOST=y
+CONFIG_PATA_TIMINGS=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_FORCE=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_ZPODD=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_MOBILE_LPM_POLICY=3
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+CONFIG_ATA_PIIX=m
+CONFIG_SATA_DWC=m
+# CONFIG_SATA_DWC_OLD_DMA is not set
+# CONFIG_SATA_DWC_DEBUG is not set
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+
+#
+# PATA SFF controllers with BMDMA
+#
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CYPRESS=m
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+CONFIG_PATA_HPT3X3_DMA=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_OPTIDMA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+CONFIG_PATA_RADISYS=m
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BCACHE=m
+# CONFIG_BCACHE_DEBUG is not set
+# CONFIG_BCACHE_CLOSURES_DEBUG is not set
+CONFIG_BCACHE_ASYNC_REGISTRATION=y
+CONFIG_BLK_DEV_DM_BUILTIN=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_DEBUG=y
+CONFIG_DM_BUFIO=m
+CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING=y
+# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set
+CONFIG_DM_BIO_PRISON=m
+CONFIG_DM_PERSISTENT_DATA=m
+CONFIG_DM_UNSTRIPED=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
+CONFIG_DM_CACHE_SMQ=m
+CONFIG_DM_WRITECACHE=m
+CONFIG_DM_EBS=m
+CONFIG_DM_ERA=m
+CONFIG_DM_CLONE=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_RAID=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_MULTIPATH_HST=m
+CONFIG_DM_MULTIPATH_IOA=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_DUST=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=m
+CONFIG_DM_VERITY=m
+CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
+# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING is not set
+CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_SWITCH=m
+CONFIG_DM_LOG_WRITES=m
+CONFIG_DM_INTEGRITY=m
+CONFIG_DM_ZONED=m
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_TCM_USER2=m
+CONFIG_LOOPBACK_TARGET=m
+CONFIG_TCM_FC=m
+CONFIG_ISCSI_TARGET=m
+CONFIG_ISCSI_TARGET_CXGB4=m
+CONFIG_SBP_TARGET=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_FIREWIRE_NOSY=m
+# end of IEEE 1394 (FireWire) support
+
+CONFIG_MACINTOSH_DRIVERS=y
+CONFIG_MAC_EMUMOUSEBTN=m
+CONFIG_NETDEVICES=y
+CONFIG_MII=m
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_WIREGUARD=m
+# CONFIG_WIREGUARD_DEBUG is not set
+CONFIG_EQUALIZER=m
+CONFIG_NET_FC=y
+CONFIG_IFB=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_IPVLAN_L3S=y
+CONFIG_IPVLAN=m
+CONFIG_IPVTAP=m
+CONFIG_VXLAN=m
+CONFIG_GENEVE=m
+CONFIG_BAREUDP=m
+CONFIG_GTP=m
+CONFIG_MACSEC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_NTB_NETDEV=m
+CONFIG_TUN=m
+CONFIG_TAP=m
+# CONFIG_TUN_VNET_CROSS_LE is not set
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_NLMON=m
+CONFIG_NET_VRF=m
+CONFIG_VSOCKMON=m
+CONFIG_MHI_NET=m
+CONFIG_SUNGEM_PHY=m
+# CONFIG_ARCNET is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_SOLOS=m
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_B53=m
+CONFIG_B53_SPI_DRIVER=m
+CONFIG_B53_MDIO_DRIVER=m
+CONFIG_B53_MMAP_DRIVER=m
+CONFIG_B53_SRAB_DRIVER=m
+CONFIG_B53_SERDES=m
+CONFIG_NET_DSA_BCM_SF2=m
+CONFIG_NET_DSA_LOOP=m
+CONFIG_NET_DSA_HIRSCHMANN_HELLCREEK=m
+# CONFIG_NET_DSA_LANTIQ_GSWIP is not set
+CONFIG_NET_DSA_MT7530=m
+CONFIG_NET_DSA_MV88E6060=m
+CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON=m
+CONFIG_NET_DSA_MICROCHIP_KSZ9477=m
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C=m
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI=m
+CONFIG_NET_DSA_MICROCHIP_KSZ8795=m
+CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI=m
+CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI=m
+CONFIG_NET_DSA_MV88E6XXX=m
+CONFIG_NET_DSA_MV88E6XXX_PTP=y
+CONFIG_NET_DSA_MSCC_SEVILLE=m
+CONFIG_NET_DSA_AR9331=m
+CONFIG_NET_DSA_SJA1105=m
+CONFIG_NET_DSA_SJA1105_PTP=y
+CONFIG_NET_DSA_SJA1105_TAS=y
+CONFIG_NET_DSA_SJA1105_VL=y
+CONFIG_NET_DSA_XRS700X=m
+CONFIG_NET_DSA_XRS700X_I2C=m
+CONFIG_NET_DSA_XRS700X_MDIO=m
+CONFIG_NET_DSA_QCA8K=m
+CONFIG_NET_DSA_REALTEK_SMI=m
+CONFIG_NET_DSA_SMSC_LAN9303=m
+CONFIG_NET_DSA_SMSC_LAN9303_I2C=m
+CONFIG_NET_DSA_SMSC_LAN9303_MDIO=m
+CONFIG_NET_DSA_VITESSE_VSC73XX=m
+CONFIG_NET_DSA_VITESSE_VSC73XX_SPI=m
+CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM=m
+# end of Distributed Switch Architecture drivers
+
+CONFIG_ETHERNET=y
+CONFIG_MDIO=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_3C589=m
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_NET_VENDOR_ADAPTEC=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_NET_VENDOR_AGERE=y
+CONFIG_ET131X=m
+CONFIG_NET_VENDOR_ALACRITECH=y
+CONFIG_SLICOSS=m
+CONFIG_NET_VENDOR_ALTEON=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_ALTERA_TSE=m
+CONFIG_NET_VENDOR_AMAZON=y
+CONFIG_ENA_ETHERNET=m
+CONFIG_NET_VENDOR_AMD=y
+CONFIG_AMD8111_ETH=m
+CONFIG_PCNET32=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_AMD_XGBE=m
+CONFIG_AMD_XGBE_DCB=y
+CONFIG_AMD_XGBE_HAVE_ECC=y
+CONFIG_NET_VENDOR_AQUANTIA=y
+CONFIG_AQTION=m
+CONFIG_NET_VENDOR_ARC=y
+CONFIG_NET_VENDOR_ATHEROS=y
+CONFIG_ATL2=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_ALX=m
+CONFIG_NET_VENDOR_BROADCOM=y
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_BCMGENET=m
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_TIGON3=m
+CONFIG_TIGON3_HWMON=y
+CONFIG_BNX2X=m
+CONFIG_BNX2X_SRIOV=y
+CONFIG_SYSTEMPORT=m
+CONFIG_BNXT=m
+CONFIG_BNXT_SRIOV=y
+CONFIG_BNXT_FLOWER_OFFLOAD=y
+CONFIG_BNXT_DCB=y
+CONFIG_BNXT_HWMON=y
+CONFIG_NET_VENDOR_BROCADE=y
+CONFIG_BNA=m
+CONFIG_NET_VENDOR_CADENCE=y
+CONFIG_MACB=m
+CONFIG_MACB_USE_HWSTAMP=y
+CONFIG_MACB_PCI=m
+CONFIG_NET_VENDOR_CAVIUM=y
+CONFIG_THUNDER_NIC_PF=m
+CONFIG_THUNDER_NIC_VF=m
+CONFIG_THUNDER_NIC_BGX=m
+CONFIG_THUNDER_NIC_RGX=m
+CONFIG_CAVIUM_PTP=m
+CONFIG_LIQUIDIO=m
+CONFIG_LIQUIDIO_VF=m
+CONFIG_NET_VENDOR_CHELSIO=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4_DCB=y
+CONFIG_CHELSIO_T4_FCOE=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_CHELSIO_LIB=m
+CONFIG_CHELSIO_INLINE_CRYPTO=y
+CONFIG_CHELSIO_IPSEC_INLINE=m
+CONFIG_CHELSIO_TLS_DEVICE=m
+CONFIG_NET_VENDOR_CISCO=y
+CONFIG_ENIC=m
+CONFIG_NET_VENDOR_CORTINA=y
+CONFIG_CX_ECAT=m
+CONFIG_DNET=m
+CONFIG_NET_VENDOR_DEC=y
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+CONFIG_TULIP_MWI=y
+CONFIG_TULIP_MMIO=y
+CONFIG_TULIP_NAPI=y
+CONFIG_TULIP_NAPI_HW_MITIGATION=y
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_NET_VENDOR_DLINK=y
+CONFIG_DL2K=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_NET_VENDOR_EMULEX=y
+CONFIG_BE2NET=m
+CONFIG_BE2NET_HWMON=y
+CONFIG_BE2NET_BE2=y
+CONFIG_BE2NET_BE3=y
+CONFIG_BE2NET_LANCER=y
+CONFIG_BE2NET_SKYHAWK=y
+CONFIG_NET_VENDOR_EZCHIP=y
+CONFIG_NET_VENDOR_FUJITSU=y
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_NET_VENDOR_GOOGLE=y
+CONFIG_GVE=m
+CONFIG_NET_VENDOR_HUAWEI=y
+CONFIG_HINIC=m
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_E100=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_E1000E_HWTS=y
+CONFIG_IGB=m
+CONFIG_IGB_HWMON=y
+CONFIG_IGB_DCA=y
+CONFIG_IGBVF=m
+CONFIG_IXGB=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_HWMON=y
+CONFIG_IXGBE_DCA=y
+CONFIG_IXGBE_DCB=y
+# CONFIG_IXGBE_IPSEC is not set
+CONFIG_IXGBEVF=m
+CONFIG_IXGBEVF_IPSEC=y
+CONFIG_I40E=m
+CONFIG_I40E_DCB=y
+CONFIG_IAVF=m
+CONFIG_I40EVF=m
+CONFIG_ICE=m
+CONFIG_FM10K=m
+CONFIG_IGC=m
+CONFIG_NET_VENDOR_MICROSOFT=y
+CONFIG_MICROSOFT_MANA=m
+CONFIG_JME=m
+CONFIG_NET_VENDOR_LITEX=y
+CONFIG_NET_VENDOR_MARVELL=y
+CONFIG_MVMDIO=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKGE_GENESIS=y
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_PRESTERA=m
+CONFIG_PRESTERA_PCI=m
+CONFIG_NET_VENDOR_MELLANOX=y
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_EN_DCB=y
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_MLX4_CORE_GEN2=y
+CONFIG_MLX5_CORE=m
+CONFIG_MLX5_ACCEL=y
+CONFIG_MLX5_FPGA=y
+CONFIG_MLX5_CORE_EN=y
+CONFIG_MLX5_EN_ARFS=y
+CONFIG_MLX5_EN_RXNFC=y
+CONFIG_MLX5_MPFS=y
+CONFIG_MLX5_ESWITCH=y
+CONFIG_MLX5_BRIDGE=y
+CONFIG_MLX5_CLS_ACT=y
+CONFIG_MLX5_TC_CT=y
+CONFIG_MLX5_TC_SAMPLE=y
+CONFIG_MLX5_CORE_EN_DCB=y
+CONFIG_MLX5_CORE_IPOIB=y
+CONFIG_MLX5_FPGA_IPSEC=y
+CONFIG_MLX5_IPSEC=y
+CONFIG_MLX5_EN_IPSEC=y
+CONFIG_MLX5_FPGA_TLS=y
+CONFIG_MLX5_TLS=y
+CONFIG_MLX5_EN_TLS=y
+CONFIG_MLX5_SW_STEERING=y
+CONFIG_MLX5_SF=y
+CONFIG_MLX5_SF_MANAGER=y
+CONFIG_MLXSW_CORE=m
+CONFIG_MLXSW_CORE_HWMON=y
+CONFIG_MLXSW_CORE_THERMAL=y
+CONFIG_MLXSW_PCI=m
+CONFIG_MLXSW_I2C=m
+CONFIG_MLXSW_SPECTRUM=m
+CONFIG_MLXSW_SPECTRUM_DCB=y
+CONFIG_MLXSW_MINIMAL=m
+CONFIG_MLXFW=m
+CONFIG_NET_VENDOR_MICREL=y
+CONFIG_KS8842=m
+CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
+CONFIG_KSZ884X_PCI=m
+CONFIG_NET_VENDOR_MICROCHIP=y
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ENCX24J600=m
+CONFIG_LAN743X=m
+CONFIG_NET_VENDOR_MICROSEMI=y
+CONFIG_MSCC_OCELOT_SWITCH_LIB=m
+CONFIG_NET_VENDOR_MYRI=y
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_FEALNX=m
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NATSEMI=m
+CONFIG_NS83820=m
+CONFIG_NET_VENDOR_NETERION=y
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_NET_VENDOR_NETRONOME=y
+CONFIG_NFP=m
+CONFIG_NFP_APP_FLOWER=y
+CONFIG_NFP_APP_ABM_NIC=y
+# CONFIG_NFP_DEBUG is not set
+CONFIG_NET_VENDOR_NI=y
+CONFIG_NI_XGE_MANAGEMENT_ENET=m
+CONFIG_NET_VENDOR_8390=y
+CONFIG_PCMCIA_AXNET=m
+CONFIG_NE2K_PCI=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_NET_VENDOR_NVIDIA=y
+CONFIG_FORCEDETH=m
+CONFIG_NET_VENDOR_OKI=y
+CONFIG_ETHOC=m
+CONFIG_NET_VENDOR_PACKET_ENGINES=y
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_NET_VENDOR_PENSANDO=y
+CONFIG_IONIC=m
+CONFIG_NET_VENDOR_QLOGIC=y
+CONFIG_QLA3XXX=m
+CONFIG_QLCNIC=m
+CONFIG_QLCNIC_SRIOV=y
+CONFIG_QLCNIC_DCB=y
+CONFIG_QLCNIC_HWMON=y
+CONFIG_NETXEN_NIC=m
+CONFIG_QED=m
+CONFIG_QED_LL2=y
+CONFIG_QED_SRIOV=y
+CONFIG_QEDE=m
+CONFIG_QED_RDMA=y
+CONFIG_QED_ISCSI=y
+CONFIG_QED_FCOE=y
+CONFIG_QED_OOO=y
+CONFIG_NET_VENDOR_QUALCOMM=y
+CONFIG_QCOM_EMAC=m
+CONFIG_RMNET=m
+CONFIG_NET_VENDOR_RDC=y
+CONFIG_R6040=m
+CONFIG_NET_VENDOR_REALTEK=y
+CONFIG_ATP=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R8169=m
+CONFIG_NET_VENDOR_RENESAS=y
+CONFIG_NET_VENDOR_ROCKER=y
+CONFIG_ROCKER=m
+CONFIG_NET_VENDOR_SAMSUNG=y
+CONFIG_SXGBE_ETH=m
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SOLARFLARE=y
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_SFC_MCDI_MON=y
+CONFIG_SFC_SRIOV=y
+CONFIG_SFC_MCDI_LOGGING=y
+CONFIG_SFC_FALCON=m
+CONFIG_SFC_FALCON_MTD=y
+CONFIG_NET_VENDOR_SILAN=y
+CONFIG_SC92031=m
+CONFIG_NET_VENDOR_SIS=y
+CONFIG_SIS900=m
+CONFIG_SIS190=m
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_EPIC100=m
+CONFIG_SMSC911X=m
+CONFIG_SMSC9420=m
+CONFIG_NET_VENDOR_SOCIONEXT=y
+CONFIG_NET_VENDOR_STMICRO=y
+CONFIG_STMMAC_ETH=m
+# CONFIG_STMMAC_SELFTESTS is not set
+CONFIG_STMMAC_PLATFORM=m
+CONFIG_DWMAC_GENERIC=m
+CONFIG_DWMAC_INTEL=m
+CONFIG_DWMAC_LOONGSON=m
+CONFIG_STMMAC_PCI=m
+CONFIG_NET_VENDOR_SUN=y
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NIU=m
+CONFIG_NET_VENDOR_SYNOPSYS=y
+CONFIG_DWC_XLGMAC=m
+CONFIG_DWC_XLGMAC_PCI=m
+CONFIG_NET_VENDOR_TEHUTI=y
+CONFIG_TEHUTI=m
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TI_CPSW_PHY_SEL is not set
+CONFIG_TLAN=m
+CONFIG_NET_VENDOR_VIA=y
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_VELOCITY=m
+CONFIG_NET_VENDOR_WIZNET=y
+CONFIG_WIZNET_W5100=m
+CONFIG_WIZNET_W5300=m
+# CONFIG_WIZNET_BUS_DIRECT is not set
+# CONFIG_WIZNET_BUS_INDIRECT is not set
+CONFIG_WIZNET_BUS_ANY=y
+CONFIG_WIZNET_W5100_SPI=m
+CONFIG_NET_VENDOR_XILINX=y
+CONFIG_XILINX_EMACLITE=m
+CONFIG_XILINX_AXI_EMAC=m
+CONFIG_XILINX_LL_TEMAC=m
+CONFIG_NET_VENDOR_XIRCOM=y
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_FDDI=m
+CONFIG_DEFXX=m
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_NET_SB1000=m
+CONFIG_PHYLINK=m
+CONFIG_PHYLIB=m
+CONFIG_SWPHY=y
+CONFIG_LED_TRIGGER_PHY=y
+CONFIG_FIXED_PHY=m
+CONFIG_SFP=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_AMD_PHY=m
+CONFIG_ADIN_PHY=m
+CONFIG_AQUANTIA_PHY=m
+CONFIG_AX88796B_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_BCM54140_PHY=m
+CONFIG_BCM7XXX_PHY=m
+CONFIG_BCM84881_PHY=m
+CONFIG_BCM87XX_PHY=m
+CONFIG_BCM_NET_PHYLIB=m
+CONFIG_CICADA_PHY=m
+CONFIG_CORTINA_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_INTEL_XWAY_PHY=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MARVELL_PHY=m
+CONFIG_MARVELL_10G_PHY=m
+CONFIG_MARVELL_88X2222_PHY=m
+CONFIG_MAXLINEAR_GPHY=m
+CONFIG_MEDIATEK_GE_PHY=m
+CONFIG_MICREL_PHY=m
+CONFIG_MICROCHIP_PHY=m
+CONFIG_MICROCHIP_T1_PHY=m
+CONFIG_MICROSEMI_PHY=m
+CONFIG_MOTORCOMM_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_NXP_C45_TJA11XX_PHY=m
+CONFIG_NXP_TJA11XX_PHY=m
+CONFIG_AT803X_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_RENESAS_PHY=m
+# CONFIG_ROCKCHIP_PHY is not set
+CONFIG_SMSC_PHY=m
+CONFIG_STE10XP=m
+CONFIG_TERANETICS_PHY=m
+CONFIG_DP83822_PHY=m
+CONFIG_DP83TC811_PHY=m
+CONFIG_DP83848_PHY=m
+CONFIG_DP83867_PHY=m
+CONFIG_DP83869_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_XILINX_GMII2RGMII=m
+CONFIG_MICREL_KS8995MA=m
+
+#
+# MCTP Device Drivers
+#
+CONFIG_MDIO_DEVICE=m
+CONFIG_MDIO_BUS=m
+CONFIG_FWNODE_MDIO=m
+CONFIG_ACPI_MDIO=m
+CONFIG_MDIO_DEVRES=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_BCM_UNIMAC=m
+CONFIG_MDIO_CAVIUM=m
+CONFIG_MDIO_GPIO=m
+CONFIG_MDIO_I2C=m
+CONFIG_MDIO_MVUSB=m
+CONFIG_MDIO_MSCC_MIIM=m
+CONFIG_MDIO_THUNDER=m
+
+#
+# MDIO Multiplexers
+#
+
+#
+# PCS device drivers
+#
+CONFIG_PCS_XPCS=m
+CONFIG_PCS_LYNX=m
+# end of PCS device drivers
+
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOATM=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLHC=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_NET_DRIVERS=m
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_AX88179_178A=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
+CONFIG_USB_NET_CDC_MBIM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9700=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET_ENABLE=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_QMI_WWAN=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+CONFIG_USB_NET_CH9200=m
+CONFIG_USB_NET_AQC111=m
+CONFIG_USB_RTL8153_ECM=m
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_ADM8211=m
+CONFIG_ATH_COMMON=m
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH5K=m
+CONFIG_ATH5K_DEBUG=y
+CONFIG_ATH5K_TRACER=y
+CONFIG_ATH5K_PCI=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_COMMON_DEBUG=y
+CONFIG_ATH9K_BTCOEX_SUPPORT=y
+CONFIG_ATH9K=m
+CONFIG_ATH9K_PCI=y
+CONFIG_ATH9K_AHB=y
+CONFIG_ATH9K_DEBUGFS=y
+CONFIG_ATH9K_STATION_STATISTICS=y
+CONFIG_ATH9K_DYNACK=y
+CONFIG_ATH9K_WOW=y
+CONFIG_ATH9K_RFKILL=y
+CONFIG_ATH9K_CHANNEL_CONTEXT=y
+CONFIG_ATH9K_PCOEM=y
+CONFIG_ATH9K_PCI_NO_EEPROM=m
+CONFIG_ATH9K_HTC=m
+CONFIG_ATH9K_HTC_DEBUGFS=y
+CONFIG_ATH9K_HWRNG=y
+CONFIG_ATH9K_COMMON_SPECTRAL=y
+CONFIG_CARL9170=m
+CONFIG_CARL9170_LEDS=y
+CONFIG_CARL9170_DEBUGFS=y
+CONFIG_CARL9170_WPC=y
+# CONFIG_CARL9170_HWRNG is not set
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_SDIO=m
+CONFIG_ATH6KL_USB=m
+CONFIG_ATH6KL_DEBUG=y
+CONFIG_ATH6KL_TRACING=y
+CONFIG_AR5523=m
+CONFIG_WIL6210=m
+CONFIG_WIL6210_ISR_COR=y
+CONFIG_WIL6210_TRACING=y
+CONFIG_WIL6210_DEBUGFS=y
+CONFIG_ATH10K=m
+CONFIG_ATH10K_CE=y
+CONFIG_ATH10K_PCI=m
+CONFIG_ATH10K_SDIO=m
+CONFIG_ATH10K_USB=m
+CONFIG_ATH10K_DEBUG=y
+CONFIG_ATH10K_DEBUGFS=y
+CONFIG_ATH10K_SPECTRAL=y
+CONFIG_ATH10K_TRACING=y
+CONFIG_WCN36XX=m
+CONFIG_WCN36XX_DEBUGFS=y
+CONFIG_ATH11K=m
+CONFIG_ATH11K_AHB=m
+CONFIG_ATH11K_PCI=m
+CONFIG_ATH11K_DEBUG=y
+CONFIG_ATH11K_DEBUGFS=y
+# CONFIG_ATH11K_TRACING is not set
+CONFIG_ATH11K_SPECTRAL=y
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AT76C50X_USB=m
+CONFIG_WLAN_VENDOR_BROADCOM=y
+CONFIG_B43=m
+CONFIG_B43_BCMA=y
+CONFIG_B43_SSB=y
+CONFIG_B43_BUSES_BCMA_AND_SSB=y
+# CONFIG_B43_BUSES_BCMA is not set
+# CONFIG_B43_BUSES_SSB is not set
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_BCMA_PIO=y
+CONFIG_B43_PIO=y
+CONFIG_B43_PHY_G=y
+CONFIG_B43_PHY_N=y
+CONFIG_B43_PHY_LP=y
+CONFIG_B43_PHY_HT=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_HWRNG=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_HWRNG=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_BRCMUTIL=m
+CONFIG_BRCMSMAC=m
+CONFIG_BRCMFMAC=m
+CONFIG_BRCMFMAC_PROTO_BCDC=y
+CONFIG_BRCMFMAC_PROTO_MSGBUF=y
+CONFIG_BRCMFMAC_SDIO=y
+CONFIG_BRCMFMAC_USB=y
+CONFIG_BRCMFMAC_PCIE=y
+CONFIG_BRCM_TRACING=y
+CONFIG_BRCMDBG=y
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_AIRO=m
+CONFIG_AIRO_CS=m
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=m
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLEGACY=m
+CONFIG_IWL4965=m
+CONFIG_IWL3945=m
+
+#
+# iwl3945 / iwl4965 Debugging Options
+#
+CONFIG_IWLEGACY_DEBUG=y
+CONFIG_IWLEGACY_DEBUGFS=y
+# end of iwl3945 / iwl4965 Debugging Options
+
+CONFIG_IWLWIFI=m
+CONFIG_IWLWIFI_LEDS=y
+CONFIG_IWLDVM=m
+CONFIG_IWLMVM=m
+CONFIG_IWLWIFI_OPMODE_MODULAR=y
+# CONFIG_IWLWIFI_BCAST_FILTERING is not set
+
+#
+# Debugging Options
+#
+CONFIG_IWLWIFI_DEBUG=y
+CONFIG_IWLWIFI_DEBUGFS=y
+CONFIG_IWLWIFI_DEVICE_TRACING=y
+# end of Debugging Options
+
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_HERMES=m
+CONFIG_HERMES_PRISM=y
+CONFIG_HERMES_CACHE_FW_ON_INIT=y
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_P54_SPI=m
+# CONFIG_P54_SPI_DEFAULT_EEPROM is not set
+CONFIG_P54_LEDS=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_SPI=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_MESH=y
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_MWIFIEX_PCIE=m
+CONFIG_MWIFIEX_USB=m
+CONFIG_MWL8K=m
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_MT7601U=m
+CONFIG_MT76_CORE=m
+CONFIG_MT76_LEDS=y
+CONFIG_MT76_USB=m
+CONFIG_MT76_SDIO=m
+CONFIG_MT76x02_LIB=m
+CONFIG_MT76x02_USB=m
+CONFIG_MT76_CONNAC_LIB=m
+CONFIG_MT76x0_COMMON=m
+CONFIG_MT76x0U=m
+CONFIG_MT76x0E=m
+CONFIG_MT76x2_COMMON=m
+CONFIG_MT76x2E=m
+CONFIG_MT76x2U=m
+CONFIG_MT7603E=m
+CONFIG_MT7615_COMMON=m
+CONFIG_MT7615E=m
+CONFIG_MT7663_USB_SDIO_COMMON=m
+CONFIG_MT7663U=m
+CONFIG_MT7663S=m
+CONFIG_MT7915E=m
+CONFIG_MT7921E=m
+CONFIG_WLAN_VENDOR_MICROCHIP=y
+CONFIG_WILC1000=m
+CONFIG_WILC1000_SDIO=m
+CONFIG_WILC1000_SPI=m
+# CONFIG_WILC1000_HW_OOB_INTR is not set
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2800PCI=m
+CONFIG_RT2800PCI_RT33XX=y
+CONFIG_RT2800PCI_RT35XX=y
+CONFIG_RT2800PCI_RT53XX=y
+CONFIG_RT2800PCI_RT3290=y
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+CONFIG_RT2800USB_RT35XX=y
+CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_RT55XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RT2800_LIB=m
+CONFIG_RT2800_LIB_MMIO=m
+CONFIG_RT2X00_LIB_MMIO=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+CONFIG_RT2X00_LIB_DEBUGFS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+CONFIG_RTL_CARDS=m
+CONFIG_RTL8192CE=m
+CONFIG_RTL8192SE=m
+CONFIG_RTL8192DE=m
+CONFIG_RTL8723AE=m
+CONFIG_RTL8723BE=m
+CONFIG_RTL8188EE=m
+CONFIG_RTL8192EE=m
+CONFIG_RTL8821AE=m
+CONFIG_RTL8192CU=m
+CONFIG_RTLWIFI=m
+CONFIG_RTLWIFI_PCI=m
+CONFIG_RTLWIFI_USB=m
+CONFIG_RTLWIFI_DEBUG=y
+CONFIG_RTL8192C_COMMON=m
+CONFIG_RTL8723_COMMON=m
+CONFIG_RTLBTCOEXIST=m
+CONFIG_RTL8XXXU=m
+CONFIG_RTL8XXXU_UNTESTED=y
+CONFIG_RTW88=m
+CONFIG_RTW88_CORE=m
+CONFIG_RTW88_PCI=m
+CONFIG_RTW88_8822B=m
+CONFIG_RTW88_8822C=m
+CONFIG_RTW88_8723D=m
+CONFIG_RTW88_8821C=m
+CONFIG_RTW88_8822BE=m
+CONFIG_RTW88_8822CE=m
+CONFIG_RTW88_8723DE=m
+CONFIG_RTW88_8821CE=m
+CONFIG_RTW88_DEBUG=y
+CONFIG_RTW88_DEBUGFS=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_RSI_91X=m
+CONFIG_RSI_DEBUGFS=y
+CONFIG_RSI_SDIO=m
+CONFIG_RSI_USB=m
+CONFIG_RSI_COEX=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_CW1200=m
+CONFIG_CW1200_WLAN_SDIO=m
+CONFIG_CW1200_WLAN_SPI=m
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_WILINK_PLATFORM_DATA=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+CONFIG_USB_ZD1201=m
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_WLAN_VENDOR_QUANTENNA=y
+CONFIG_QTNFMAC=m
+CONFIG_QTNFMAC_PCIE=m
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_VIRT_WIFI=m
+# CONFIG_WAN is not set
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKELB=m
+CONFIG_IEEE802154_AT86RF230=m
+# CONFIG_IEEE802154_AT86RF230_DEBUGFS is not set
+CONFIG_IEEE802154_MRF24J40=m
+CONFIG_IEEE802154_CC2520=m
+CONFIG_IEEE802154_ATUSB=m
+CONFIG_IEEE802154_ADF7242=m
+CONFIG_IEEE802154_CA8210=m
+# CONFIG_IEEE802154_CA8210_DEBUGFS is not set
+CONFIG_IEEE802154_MCR20A=m
+CONFIG_IEEE802154_HWSIM=m
+
+#
+# Wireless WAN
+#
+CONFIG_WWAN=y
+CONFIG_WWAN_HWSIM=m
+CONFIG_MHI_WWAN_CTRL=m
+CONFIG_MHI_WWAN_MBIM=m
+CONFIG_RPMSG_WWAN_CTRL=m
+CONFIG_IOSM=m
+# end of Wireless WAN
+
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_XEN_NETDEV_BACKEND=m
+CONFIG_VMXNET3=m
+CONFIG_FUJITSU_ES=m
+CONFIG_USB4_NET=m
+CONFIG_HYPERV_NET=m
+CONFIG_NETDEVSIM=m
+CONFIG_NET_FAILOVER=m
+CONFIG_ISDN=y
+CONFIG_ISDN_CAPI=y
+CONFIG_CAPI_TRACE=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_MISDN=m
+CONFIG_MISDN_DSP=m
+CONFIG_MISDN_L1OIP=m
+
+#
+# mISDN hardware drivers
+#
+CONFIG_MISDN_HFCPCI=m
+CONFIG_MISDN_HFCMULTI=m
+CONFIG_MISDN_HFCUSB=m
+CONFIG_MISDN_AVMFRITZ=m
+CONFIG_MISDN_SPEEDFAX=m
+CONFIG_MISDN_INFINEON=m
+CONFIG_MISDN_W6692=m
+CONFIG_MISDN_NETJET=m
+CONFIG_MISDN_HDLC=m
+CONFIG_MISDN_IPAC=m
+CONFIG_MISDN_ISAR=m
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_SPARSEKMAP=m
+CONFIG_INPUT_MATRIXKMAP=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ADC=m
+CONFIG_KEYBOARD_ADP5520=m
+CONFIG_KEYBOARD_ADP5588=m
+CONFIG_KEYBOARD_ADP5589=m
+CONFIG_KEYBOARD_APPLESPI=m
+CONFIG_KEYBOARD_ATKBD=m
+CONFIG_KEYBOARD_QT1050=m
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_DLINK_DIR685=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_TCA8418=m
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_LM8323=m
+CONFIG_KEYBOARD_LM8333=m
+CONFIG_KEYBOARD_MAX7359=m
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_MPR121=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_KEYBOARD_OPENCORES=m
+CONFIG_KEYBOARD_SAMSUNG=m
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_IQS62X=m
+CONFIG_KEYBOARD_TM2_TOUCHKEY=m
+CONFIG_KEYBOARD_TWL4030=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_CROS_EC=m
+CONFIG_KEYBOARD_MTK_PMIC=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_ELANTECH_SMBUS=y
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_PS2_FOCALTECH=y
+CONFIG_MOUSE_PS2_VMMOUSE=y
+CONFIG_MOUSE_PS2_SMBUS=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_CYAPA=m
+CONFIG_MOUSE_ELAN_I2C=m
+CONFIG_MOUSE_ELAN_I2C_I2C=y
+CONFIG_MOUSE_ELAN_I2C_SMBUS=y
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+CONFIG_MOUSE_SYNAPTICS_USB=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADC=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=m
+CONFIG_JOYSTICK_IFORCE_232=m
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_AS5011=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_JOYSTICK_WALKERA0701=m
+CONFIG_JOYSTICK_PSXPAD_SPI=m
+CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
+CONFIG_JOYSTICK_PXRC=m
+CONFIG_JOYSTICK_QWIIC=m
+CONFIG_JOYSTICK_FSIA6B=m
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_HANWANG=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_PEGASUS=m
+CONFIG_TABLET_SERIAL_WACOM4=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_88PM860X=m
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AD7879_SPI=m
+CONFIG_TOUCHSCREEN_ADC=m
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_ATMEL_MXT_T37=y
+CONFIG_TOUCHSCREEN_AUO_PIXCIR=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_BU21029=m
+CONFIG_TOUCHSCREEN_CHIPONE_ICN8505=m
+CONFIG_TOUCHSCREEN_CY8CTMA140=m
+CONFIG_TOUCHSCREEN_CY8CTMG110=m
+CONFIG_TOUCHSCREEN_CYTTSP_CORE=m
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=m
+CONFIG_TOUCHSCREEN_CYTTSP_SPI=m
+CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m
+CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m
+CONFIG_TOUCHSCREEN_CYTTSP4_SPI=m
+CONFIG_TOUCHSCREEN_DA9034=m
+CONFIG_TOUCHSCREEN_DA9052=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_EGALAX_SERIAL=m
+CONFIG_TOUCHSCREEN_EXC3000=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_HIDEEP=m
+CONFIG_TOUCHSCREEN_HYCON_HY46XX=m
+CONFIG_TOUCHSCREEN_ILI210X=m
+CONFIG_TOUCHSCREEN_ILITEK=m
+CONFIG_TOUCHSCREEN_S6SY761=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_EKTF2127=m
+CONFIG_TOUCHSCREEN_ELAN=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+CONFIG_TOUCHSCREEN_WACOM_I2C=m
+CONFIG_TOUCHSCREEN_MAX11801=m
+CONFIG_TOUCHSCREEN_MCS5000=m
+CONFIG_TOUCHSCREEN_MMS114=m
+CONFIG_TOUCHSCREEN_MELFAS_MIP4=m
+CONFIG_TOUCHSCREEN_MSG2638=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
+CONFIG_TOUCHSCREEN_UCB1400=m
+CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_WDT87XX_I2C=m
+CONFIG_TOUCHSCREEN_WM831X=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_MC13783=m
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_ELO=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC_SERIO=m
+CONFIG_TOUCHSCREEN_TSC200X_CORE=m
+CONFIG_TOUCHSCREEN_TSC2004=m
+CONFIG_TOUCHSCREEN_TSC2005=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_TSC2007_IIO=y
+CONFIG_TOUCHSCREEN_PCAP=m
+CONFIG_TOUCHSCREEN_RM_TS=m
+CONFIG_TOUCHSCREEN_SILEAD=m
+CONFIG_TOUCHSCREEN_SIS_I2C=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_STMFTS=m
+CONFIG_TOUCHSCREEN_SUR40=m
+CONFIG_TOUCHSCREEN_SURFACE3_SPI=m
+CONFIG_TOUCHSCREEN_SX8654=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_TOUCHSCREEN_ZET6223=m
+CONFIG_TOUCHSCREEN_ZFORCE=m
+CONFIG_TOUCHSCREEN_ROHM_BU21023=m
+CONFIG_TOUCHSCREEN_IQS5XX=m
+CONFIG_TOUCHSCREEN_ZINITIX=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_88PM860X_ONKEY=m
+CONFIG_INPUT_88PM80X_ONKEY=m
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_AD714X_I2C=m
+CONFIG_INPUT_AD714X_SPI=m
+CONFIG_INPUT_ARIZONA_HAPTICS=m
+CONFIG_INPUT_ATC260X_ONKEY=m
+CONFIG_INPUT_BMA150=m
+CONFIG_INPUT_E3X0_BUTTON=m
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_MAX77693_HAPTIC=m
+CONFIG_INPUT_MAX8925_ONKEY=m
+CONFIG_INPUT_MAX8997_HAPTIC=m
+CONFIG_INPUT_MC13783_PWRBUTTON=m
+CONFIG_INPUT_MMA8450=m
+CONFIG_INPUT_APANEL=m
+CONFIG_INPUT_GPIO_BEEPER=m
+CONFIG_INPUT_GPIO_DECODER=m
+CONFIG_INPUT_GPIO_VIBRA=m
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_KXTJ9=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_REGULATOR_HAPTIC=m
+CONFIG_INPUT_RETU_PWRBUTTON=m
+CONFIG_INPUT_AXP20X_PEK=m
+CONFIG_INPUT_TWL4030_PWRBUTTON=m
+CONFIG_INPUT_TWL4030_VIBRA=m
+CONFIG_INPUT_TWL6040_VIBRA=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_PALMAS_PWRBUTTON=m
+CONFIG_INPUT_PCF50633_PMU=m
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_PWM_BEEPER=m
+CONFIG_INPUT_PWM_VIBRA=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_DA7280_HAPTICS=m
+CONFIG_INPUT_DA9052_ONKEY=m
+CONFIG_INPUT_DA9055_ONKEY=m
+CONFIG_INPUT_DA9063_ONKEY=m
+CONFIG_INPUT_WM831X_ON=m
+CONFIG_INPUT_PCAP=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+CONFIG_INPUT_ADXL34X_SPI=m
+CONFIG_INPUT_IMS_PCU=m
+CONFIG_INPUT_IQS269A=m
+CONFIG_INPUT_IQS626A=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m
+CONFIG_INPUT_IDEAPAD_SLIDEBAR=m
+CONFIG_INPUT_SOC_BUTTON_ARRAY=m
+CONFIG_INPUT_DRV260X_HAPTICS=m
+CONFIG_INPUT_DRV2665_HAPTICS=m
+CONFIG_INPUT_DRV2667_HAPTICS=m
+CONFIG_INPUT_RAVE_SP_PWRBUTTON=m
+CONFIG_RMI4_CORE=m
+CONFIG_RMI4_I2C=m
+CONFIG_RMI4_SPI=m
+CONFIG_RMI4_SMB=m
+CONFIG_RMI4_F03=y
+CONFIG_RMI4_F03_SERIO=m
+CONFIG_RMI4_2D_SENSOR=y
+CONFIG_RMI4_F11=y
+CONFIG_RMI4_F12=y
+CONFIG_RMI4_F30=y
+CONFIG_RMI4_F34=y
+CONFIG_RMI4_F3A=y
+# CONFIG_RMI4_F54 is not set
+CONFIG_RMI4_F55=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+CONFIG_SERIO_I8042=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=m
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+CONFIG_SERIO_ARC_PS2=m
+CONFIG_HYPERV_KEYBOARD=m
+CONFIG_SERIO_GPIO_PS2=m
+CONFIG_USERIO=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+# end of Hardware I/O ports
+# end of Input device support
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_LDISC_AUTOLOAD=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_PNP=y
+# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
+CONFIG_SERIAL_8250_FINTEK=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DMA=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_EXAR=m
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_MEN_MCB=m
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=32
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_8250_DWLIB=y
+CONFIG_SERIAL_8250_DW=m
+CONFIG_SERIAL_8250_RT288X=y
+CONFIG_SERIAL_8250_LPSS=y
+CONFIG_SERIAL_8250_MID=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX310X=m
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_UARTLITE_NR_UARTS=1
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_LANTIQ is not set
+CONFIG_SERIAL_SCCNXP=m
+CONFIG_SERIAL_SC16IS7XX_CORE=m
+CONFIG_SERIAL_SC16IS7XX=m
+CONFIG_SERIAL_SC16IS7XX_I2C=y
+CONFIG_SERIAL_SC16IS7XX_SPI=y
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_ALTERA_JTAGUART=m
+CONFIG_SERIAL_ALTERA_UART=m
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+CONFIG_SERIAL_ARC=m
+CONFIG_SERIAL_ARC_NR_PORTS=1
+CONFIG_SERIAL_RP2=m
+CONFIG_SERIAL_RP2_NR_UARTS=32
+CONFIG_SERIAL_FSL_LPUART=m
+CONFIG_SERIAL_FSL_LINFLEXUART=m
+CONFIG_SERIAL_MEN_Z135=m
+CONFIG_SERIAL_SPRD=m
+# end of Serial drivers
+
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+CONFIG_N_GSM=m
+CONFIG_NOZOMI=m
+CONFIG_NULL_TTY=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+CONFIG_HVC_XEN_FRONTEND=y
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+CONFIG_IPMI_DMI_DECODE=y
+CONFIG_IPMI_PLAT_DATA=y
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_SSIF=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_IPMB_DEVICE_INTERFACE=m
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_BA431=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_HW_RANDOM_XIPHERA=m
+CONFIG_APPLICOM=m
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_SCR24X=m
+CONFIG_IPWIRELESS=m
+# end of PCMCIA character devices
+
+CONFIG_MWAVE=m
+CONFIG_DEVMEM=y
+CONFIG_NVRAM=y
+CONFIG_DEVPORT=y
+CONFIG_HPET=y
+# CONFIG_HPET_MMAP is not set
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_HW_RANDOM_TPM=y
+CONFIG_TCG_TIS_CORE=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_TIS_SPI=m
+CONFIG_TCG_TIS_SPI_CR50=y
+CONFIG_TCG_TIS_I2C_CR50=m
+CONFIG_TCG_TIS_I2C_ATMEL=m
+CONFIG_TCG_TIS_I2C_INFINEON=m
+CONFIG_TCG_TIS_I2C_NUVOTON=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TCG_XEN=m
+CONFIG_TCG_CRB=m
+CONFIG_TCG_VTPM_PROXY=m
+CONFIG_TCG_TIS_ST33ZP24=m
+CONFIG_TCG_TIS_ST33ZP24_I2C=m
+CONFIG_TCG_TIS_ST33ZP24_SPI=m
+CONFIG_TELCLOCK=m
+CONFIG_XILLYBUS_CLASS=m
+CONFIG_XILLYBUS=m
+CONFIG_XILLYBUS_PCIE=m
+CONFIG_XILLYUSB=m
+# CONFIG_RANDOM_TRUST_CPU is not set
+# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+# end of Character devices
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_ACPI_I2C_OPREGION=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=m
+CONFIG_I2C_MUX_LTC4306=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_MUX_REG=m
+CONFIG_I2C_MUX_MLXCPLD=m
+# end of Multiplexer I2C Chip support
+
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=m
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_AMD_MP2=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_ISMT=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_CHT_WC=m
+# CONFIG_I2C_NCT6775 is not set
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_NVIDIA_GPU=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_CBUS_GPIO=m
+CONFIG_I2C_DESIGNWARE_CORE=y
+CONFIG_I2C_DESIGNWARE_SLAVE=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_DESIGNWARE_BAYTRAIL=y
+CONFIG_I2C_DESIGNWARE_PCI=y
+CONFIG_I2C_EMEV2=m
+CONFIG_I2C_GPIO=m
+# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
+CONFIG_I2C_KEMPLD=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_DIOLAN_U2C=m
+CONFIG_I2C_DLN2=m
+CONFIG_I2C_CP2615=m
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_ROBOTFUZZ_OSIF=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+CONFIG_I2C_VIPERBOARD=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_MLXCPLD=m
+CONFIG_I2C_CROS_EC_TUNNEL=m
+CONFIG_I2C_VIRTIO=m
+# end of I2C Hardware Bus support
+
+CONFIG_I2C_STUB=m
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_SLAVE_EEPROM=m
+CONFIG_I2C_SLAVE_TESTUNIT=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# end of I2C support
+
+# CONFIG_I3C is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ALTERA=m
+CONFIG_SPI_ALTERA_CORE=m
+CONFIG_SPI_ALTERA_DFL=m
+CONFIG_SPI_AXI_SPI_ENGINE=m
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+CONFIG_SPI_CADENCE=m
+CONFIG_SPI_DESIGNWARE=m
+CONFIG_SPI_DW_DMA=y
+CONFIG_SPI_DW_PCI=m
+CONFIG_SPI_DW_MMIO=m
+CONFIG_SPI_DLN2=m
+CONFIG_SPI_NXP_FLEXSPI=m
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_LM70_LLP=m
+# CONFIG_SPI_LANTIQ_SSC is not set
+CONFIG_SPI_OC_TINY=m
+CONFIG_SPI_PXA2XX=m
+CONFIG_SPI_PXA2XX_PCI=m
+# CONFIG_SPI_ROCKCHIP is not set
+CONFIG_SPI_SC18IS602=m
+CONFIG_SPI_SIFIVE=m
+CONFIG_SPI_MXIC=m
+CONFIG_SPI_XCOMM=m
+CONFIG_SPI_XILINX=m
+CONFIG_SPI_ZYNQMP_GQSPI=m
+CONFIG_SPI_AMD=m
+
+#
+# SPI Multiplexer support
+#
+CONFIG_SPI_MUX=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_LOOPBACK_TEST=m
+CONFIG_SPI_TLE62X0=m
+CONFIG_SPI_SLAVE=y
+CONFIG_SPI_SLAVE_TIME=m
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
+CONFIG_SPI_DYNAMIC=y
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+CONFIG_PPS=y
+# CONFIG_PPS_DEBUG is not set
+
+#
+# PPS clients support
+#
+CONFIG_PPS_CLIENT_KTIMER=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_PARPORT=m
+CONFIG_PPS_CLIENT_GPIO=m
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_DP83640_PHY=m
+CONFIG_PTP_1588_CLOCK_INES=m
+CONFIG_PTP_1588_CLOCK_KVM=m
+CONFIG_PTP_1588_CLOCK_IDT82P33=m
+CONFIG_PTP_1588_CLOCK_IDTCM=m
+CONFIG_PTP_1588_CLOCK_VMW=m
+CONFIG_PTP_1588_CLOCK_OCP=m
+# end of PTP clock support
+
+CONFIG_PINCTRL=y
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+CONFIG_PINCTRL_AMD=m
+CONFIG_PINCTRL_DA9062=m
+CONFIG_PINCTRL_MCP23S08_I2C=m
+CONFIG_PINCTRL_MCP23S08_SPI=m
+CONFIG_PINCTRL_MCP23S08=m
+CONFIG_PINCTRL_SX150X=y
+CONFIG_PINCTRL_BAYTRAIL=y
+CONFIG_PINCTRL_CHERRYVIEW=y
+CONFIG_PINCTRL_LYNXPOINT=y
+CONFIG_PINCTRL_INTEL=y
+CONFIG_PINCTRL_ALDERLAKE=y
+CONFIG_PINCTRL_BROXTON=y
+CONFIG_PINCTRL_CANNONLAKE=y
+CONFIG_PINCTRL_CEDARFORK=y
+CONFIG_PINCTRL_DENVERTON=y
+CONFIG_PINCTRL_ELKHARTLAKE=y
+CONFIG_PINCTRL_EMMITSBURG=y
+CONFIG_PINCTRL_GEMINILAKE=y
+CONFIG_PINCTRL_ICELAKE=y
+CONFIG_PINCTRL_JASPERLAKE=y
+CONFIG_PINCTRL_LAKEFIELD=y
+CONFIG_PINCTRL_LEWISBURG=y
+CONFIG_PINCTRL_SUNRISEPOINT=y
+CONFIG_PINCTRL_TIGERLAKE=y
+
+#
+# Renesas pinctrl drivers
+#
+# end of Renesas pinctrl drivers
+
+CONFIG_PINCTRL_MADERA=m
+CONFIG_PINCTRL_CS47L15=y
+CONFIG_PINCTRL_CS47L35=y
+CONFIG_PINCTRL_CS47L85=y
+CONFIG_PINCTRL_CS47L90=y
+CONFIG_PINCTRL_CS47L92=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_FASTPATH_LIMIT=512
+CONFIG_GPIO_ACPI=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_CDEV_V1=y
+CONFIG_GPIO_GENERIC=m
+CONFIG_GPIO_MAX730X=m
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_AMDPT=m
+CONFIG_GPIO_DWAPB=m
+CONFIG_GPIO_EXAR=m
+CONFIG_GPIO_GENERIC_PLATFORM=m
+CONFIG_GPIO_ICH=m
+CONFIG_GPIO_MB86S7X=m
+CONFIG_GPIO_MENZ127=m
+CONFIG_GPIO_SIOX=m
+CONFIG_GPIO_VX855=m
+CONFIG_GPIO_AMD_FCH=m
+# end of Memory mapped GPIO drivers
+
+#
+# Port-mapped I/O GPIO drivers
+#
+CONFIG_GPIO_F7188X=m
+CONFIG_GPIO_IT87=m
+CONFIG_GPIO_SCH=m
+CONFIG_GPIO_SCH311X=m
+CONFIG_GPIO_WINBOND=m
+CONFIG_GPIO_WS16C48=m
+# end of Port-mapped I/O GPIO drivers
+
+#
+# I2C GPIO expanders
+#
+CONFIG_GPIO_ADP5588=m
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_PCA9570=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_TPIC2810=m
+# end of I2C GPIO expanders
+
+#
+# MFD GPIO expanders
+#
+CONFIG_GPIO_ADP5520=m
+CONFIG_GPIO_ARIZONA=m
+CONFIG_GPIO_BD9571MWV=m
+CONFIG_GPIO_CRYSTAL_COVE=m
+CONFIG_GPIO_DA9052=m
+CONFIG_GPIO_DA9055=m
+CONFIG_GPIO_DLN2=m
+CONFIG_GPIO_JANZ_TTL=m
+CONFIG_GPIO_KEMPLD=m
+CONFIG_GPIO_LP3943=m
+CONFIG_GPIO_LP873X=m
+CONFIG_GPIO_MADERA=m
+CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_RC5T583=y
+CONFIG_GPIO_TPS65086=m
+CONFIG_GPIO_TPS6586X=y
+CONFIG_GPIO_TPS65910=y
+CONFIG_GPIO_TPS65912=m
+CONFIG_GPIO_TPS68470=y
+CONFIG_GPIO_TQMX86=m
+CONFIG_GPIO_TWL4030=m
+CONFIG_GPIO_TWL6040=m
+CONFIG_GPIO_UCB1400=m
+CONFIG_GPIO_WHISKEY_COVE=m
+CONFIG_GPIO_WM831X=m
+CONFIG_GPIO_WM8350=m
+CONFIG_GPIO_WM8994=m
+# end of MFD GPIO expanders
+
+#
+# PCI GPIO expanders
+#
+CONFIG_GPIO_AMD8111=m
+CONFIG_GPIO_ML_IOH=m
+CONFIG_GPIO_PCI_IDIO_16=m
+CONFIG_GPIO_PCIE_IDIO_24=m
+CONFIG_GPIO_RDC321X=m
+# end of PCI GPIO expanders
+
+#
+# SPI GPIO expanders
+#
+CONFIG_GPIO_MAX3191X=m
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MC33880=m
+CONFIG_GPIO_PISOSR=m
+CONFIG_GPIO_XRA1403=m
+# end of SPI GPIO expanders
+
+#
+# USB GPIO expanders
+#
+CONFIG_GPIO_VIPERBOARD=m
+# end of USB GPIO expanders
+
+#
+# Virtual GPIO drivers
+#
+CONFIG_GPIO_AGGREGATOR=m
+CONFIG_GPIO_MOCKUP=m
+CONFIG_GPIO_VIRTIO=m
+# end of Virtual GPIO drivers
+
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_DS1WM=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_MASTER_SGI=m
+# end of 1-wire Bus Masters
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2405=m
+CONFIG_W1_SLAVE_DS2408=m
+# CONFIG_W1_SLAVE_DS2408_READBACK is not set
+CONFIG_W1_SLAVE_DS2413=m
+CONFIG_W1_SLAVE_DS2406=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2805=m
+CONFIG_W1_SLAVE_DS2430=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2438=m
+CONFIG_W1_SLAVE_DS250X=m
+CONFIG_W1_SLAVE_DS2780=m
+CONFIG_W1_SLAVE_DS2781=m
+CONFIG_W1_SLAVE_DS28E04=m
+CONFIG_W1_SLAVE_DS28E17=m
+# end of 1-wire Slaves
+
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_ATC260X=m
+CONFIG_POWER_RESET_MT6323=y
+CONFIG_POWER_RESET_RESTART=y
+CONFIG_POWER_RESET_TPS65086=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_POWER_SUPPLY_HWMON=y
+CONFIG_PDA_POWER=m
+CONFIG_GENERIC_ADC_BATTERY=m
+CONFIG_MAX8925_POWER=m
+CONFIG_WM831X_BACKUP=m
+CONFIG_WM831X_POWER=m
+CONFIG_WM8350_POWER=m
+CONFIG_TEST_POWER=m
+CONFIG_BATTERY_88PM860X=m
+CONFIG_CHARGER_ADP5061=m
+CONFIG_BATTERY_CW2015=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_BATTERY_DS2780=m
+CONFIG_BATTERY_DS2781=m
+CONFIG_BATTERY_DS2782=m
+CONFIG_BATTERY_SBS=m
+CONFIG_CHARGER_SBS=m
+CONFIG_MANAGER_SBS=m
+CONFIG_BATTERY_BQ27XXX=m
+CONFIG_BATTERY_BQ27XXX_I2C=m
+CONFIG_BATTERY_BQ27XXX_HDQ=m
+# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set
+CONFIG_BATTERY_DA9030=m
+CONFIG_BATTERY_DA9052=m
+CONFIG_CHARGER_DA9150=m
+CONFIG_BATTERY_DA9150=m
+CONFIG_CHARGER_AXP20X=m
+CONFIG_BATTERY_AXP20X=m
+CONFIG_AXP20X_POWER=m
+CONFIG_AXP288_CHARGER=m
+CONFIG_AXP288_FUEL_GAUGE=m
+CONFIG_BATTERY_MAX17040=m
+CONFIG_BATTERY_MAX17042=m
+CONFIG_BATTERY_MAX1721X=m
+CONFIG_BATTERY_TWL4030_MADC=m
+CONFIG_CHARGER_88PM860X=m
+CONFIG_CHARGER_PCF50633=m
+CONFIG_BATTERY_RX51=m
+CONFIG_CHARGER_ISP1704=m
+CONFIG_CHARGER_MAX8903=m
+CONFIG_CHARGER_TWL4030=m
+CONFIG_CHARGER_LP8727=m
+CONFIG_CHARGER_LP8788=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_CHARGER_MANAGER=y
+CONFIG_CHARGER_LT3651=m
+CONFIG_CHARGER_LTC4162L=m
+CONFIG_CHARGER_MAX14577=m
+CONFIG_CHARGER_MAX77693=m
+CONFIG_CHARGER_MAX8997=m
+CONFIG_CHARGER_MAX8998=m
+CONFIG_CHARGER_MP2629=m
+CONFIG_CHARGER_MT6360=m
+CONFIG_CHARGER_BQ2415X=m
+CONFIG_CHARGER_BQ24190=m
+CONFIG_CHARGER_BQ24257=m
+CONFIG_CHARGER_BQ24735=m
+CONFIG_CHARGER_BQ2515X=m
+CONFIG_CHARGER_BQ25890=m
+CONFIG_CHARGER_BQ25980=m
+CONFIG_CHARGER_BQ256XX=m
+CONFIG_CHARGER_SMB347=m
+CONFIG_CHARGER_TPS65090=m
+CONFIG_BATTERY_GAUGE_LTC2941=m
+CONFIG_BATTERY_GOLDFISH=m
+CONFIG_BATTERY_RT5033=m
+CONFIG_CHARGER_RT9455=m
+CONFIG_CHARGER_CROS_USBPD=m
+CONFIG_CHARGER_CROS_PCHG=m
+CONFIG_CHARGER_BD99954=m
+CONFIG_CHARGER_WILCO=m
+CONFIG_BATTERY_SURFACE=m
+CONFIG_CHARGER_SURFACE=m
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7314=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM1177=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7X10=m
+CONFIG_SENSORS_ADT7310=m
+CONFIG_SENSORS_ADT7410=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_AHT10=m
+CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=m
+CONFIG_SENSORS_AS370=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_AXI_FAN_CONTROL=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_K10TEMP=m
+CONFIG_SENSORS_FAM15H_POWER=m
+CONFIG_SENSORS_APPLESMC=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ASPEED=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_CORSAIR_CPRO=m
+CONFIG_SENSORS_CORSAIR_PSU=m
+CONFIG_SENSORS_DRIVETEMP=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_DELL_SMM=m
+CONFIG_SENSORS_DA9052_ADC=m
+CONFIG_SENSORS_DA9055=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_MC13783_ADC=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_FTSTEUTATES=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_G762=m
+CONFIG_SENSORS_HIH6130=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IIO_HWMON=m
+CONFIG_SENSORS_I5500=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_POWR1220=m
+CONFIG_SENSORS_LINEAGE=m
+CONFIG_SENSORS_LTC2945=m
+CONFIG_SENSORS_LTC2947=m
+CONFIG_SENSORS_LTC2947_I2C=m
+CONFIG_SENSORS_LTC2947_SPI=m
+CONFIG_SENSORS_LTC2990=m
+CONFIG_SENSORS_LTC2992=m
+CONFIG_SENSORS_LTC4151=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4222=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4260=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX127=m
+CONFIG_SENSORS_MAX16065=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX1668=m
+CONFIG_SENSORS_MAX197=m
+CONFIG_SENSORS_MAX31722=m
+CONFIG_SENSORS_MAX31730=m
+CONFIG_SENSORS_MAX6621=m
+CONFIG_SENSORS_MAX6639=m
+CONFIG_SENSORS_MAX6642=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_MAX6697=m
+CONFIG_SENSORS_MAX31790=m
+CONFIG_SENSORS_MCP3021=m
+CONFIG_SENSORS_MLXREG_FAN=m
+CONFIG_SENSORS_TC654=m
+CONFIG_SENSORS_TPS23861=m
+CONFIG_SENSORS_MENF21BMC_HWMON=m
+CONFIG_SENSORS_MR75203=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LM95234=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_LM95245=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_NTC_THERMISTOR=m
+CONFIG_SENSORS_NCT6683=m
+CONFIG_SENSORS_NCT6775=m
+CONFIG_SENSORS_NCT7802=m
+CONFIG_SENSORS_NCT7904=m
+CONFIG_SENSORS_NPCM7XX=m
+CONFIG_SENSORS_NZXT_KRAKEN2=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_PMBUS=m
+CONFIG_SENSORS_PMBUS=m
+CONFIG_SENSORS_ADM1266=m
+CONFIG_SENSORS_ADM1275=m
+CONFIG_SENSORS_BEL_PFE=m
+CONFIG_SENSORS_BPA_RS600=m
+CONFIG_SENSORS_FSP_3Y=m
+CONFIG_SENSORS_IBM_CFFPS=m
+CONFIG_SENSORS_DPS920AB=m
+CONFIG_SENSORS_INSPUR_IPSPS=m
+CONFIG_SENSORS_IR35221=m
+CONFIG_SENSORS_IR36021=m
+CONFIG_SENSORS_IR38064=m
+CONFIG_SENSORS_IRPS5401=m
+CONFIG_SENSORS_ISL68137=m
+CONFIG_SENSORS_LM25066=m
+CONFIG_SENSORS_LTC2978=m
+# CONFIG_SENSORS_LTC2978_REGULATOR is not set
+CONFIG_SENSORS_LTC3815=m
+CONFIG_SENSORS_MAX15301=m
+CONFIG_SENSORS_MAX16064=m
+CONFIG_SENSORS_MAX16601=m
+CONFIG_SENSORS_MAX20730=m
+CONFIG_SENSORS_MAX20751=m
+CONFIG_SENSORS_MAX31785=m
+CONFIG_SENSORS_MAX34440=m
+CONFIG_SENSORS_MAX8688=m
+CONFIG_SENSORS_MP2888=m
+CONFIG_SENSORS_MP2975=m
+CONFIG_SENSORS_PIM4328=m
+CONFIG_SENSORS_PM6764TR=m
+CONFIG_SENSORS_PXE1610=m
+CONFIG_SENSORS_Q54SJ108A2=m
+CONFIG_SENSORS_STPDDC60=m
+CONFIG_SENSORS_TPS40422=m
+CONFIG_SENSORS_TPS53679=m
+CONFIG_SENSORS_UCD9000=m
+CONFIG_SENSORS_UCD9200=m
+CONFIG_SENSORS_XDPE122=m
+CONFIG_SENSORS_ZL6100=m
+CONFIG_SENSORS_SBTSI=m
+CONFIG_SENSORS_SBRMI=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SHT3x=m
+CONFIG_SENSORS_SHT4x=m
+CONFIG_SENSORS_SHTC1=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_EMC6W201=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_SCH56XX_COMMON=m
+CONFIG_SENSORS_SCH5627=m
+CONFIG_SENSORS_SCH5636=m
+CONFIG_SENSORS_STTS751=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_ADC128D818=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_INA209=m
+CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_INA3221=m
+CONFIG_SENSORS_TC74=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP103=m
+CONFIG_SENSORS_TMP108=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_TMP513=m
+CONFIG_SENSORS_VIA_CPUTEMP=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83773G=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+# CONFIG_SENSORS_W83795_FANCTRL is not set
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_WM831X=m
+CONFIG_SENSORS_WM8350=m
+CONFIG_SENSORS_XGENE=m
+CONFIG_SENSORS_INTEL_M10_BMC_HWMON=m
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ACPI_POWER=m
+CONFIG_SENSORS_ATK0110=m
+CONFIG_THERMAL=y
+CONFIG_THERMAL_NETLINK=y
+# CONFIG_THERMAL_STATISTICS is not set
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=100
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
+CONFIG_DEVFREQ_THERMAL=y
+# CONFIG_THERMAL_EMULATION is not set
+
+#
+# Intel thermal drivers
+#
+CONFIG_INTEL_POWERCLAMP=m
+CONFIG_X86_THERMAL_VECTOR=y
+CONFIG_X86_PKG_TEMP_THERMAL=m
+CONFIG_INTEL_SOC_DTS_IOSF_CORE=m
+CONFIG_INTEL_SOC_DTS_THERMAL=m
+
+#
+# ACPI INT340X thermal drivers
+#
+CONFIG_INT340X_THERMAL=m
+CONFIG_ACPI_THERMAL_REL=m
+CONFIG_INT3406_THERMAL=m
+CONFIG_PROC_THERMAL_MMIO_RAPL=m
+# end of ACPI INT340X thermal drivers
+
+CONFIG_INTEL_BXT_PMIC_THERMAL=m
+CONFIG_INTEL_PCH_THERMAL=m
+CONFIG_INTEL_TCC_COOLING=m
+CONFIG_INTEL_MENLOW=m
+# end of Intel thermal drivers
+
+CONFIG_GENERIC_ADC_THERMAL=m
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
+CONFIG_WATCHDOG_OPEN_TIMEOUT=0
+CONFIG_WATCHDOG_SYSFS=y
+# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+CONFIG_WATCHDOG_PRETIMEOUT_GOV=y
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=m
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y
+# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set
+CONFIG_DA9052_WATCHDOG=m
+CONFIG_DA9055_WATCHDOG=m
+CONFIG_DA9063_WATCHDOG=m
+CONFIG_DA9062_WATCHDOG=m
+CONFIG_MENF21BMC_WATCHDOG=m
+CONFIG_MENZ069_WATCHDOG=m
+CONFIG_WDAT_WDT=m
+CONFIG_WM831X_WATCHDOG=m
+CONFIG_WM8350_WATCHDOG=m
+CONFIG_XILINX_WATCHDOG=m
+CONFIG_ZIIRAVE_WATCHDOG=m
+CONFIG_RAVE_SP_WATCHDOG=m
+CONFIG_MLX_WDT=m
+CONFIG_CADENCE_WATCHDOG=m
+CONFIG_DW_WATCHDOG=m
+CONFIG_TWL4030_WATCHDOG=m
+CONFIG_MAX63XX_WATCHDOG=m
+CONFIG_RETU_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_EBC_C384_WDT=m
+CONFIG_F71808E_WDT=m
+CONFIG_SP5100_TCO=m
+CONFIG_SBC_FITPC2_WATCHDOG=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_IE6XX_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+CONFIG_HP_WATCHDOG=m
+CONFIG_HPWDT_NMI_DECODING=y
+CONFIG_KEMPLD_WDT=m
+CONFIG_SC1200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_NV_TCO=m
+CONFIG_60XX_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC_SCH311X_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_TQMX86_WDT=m
+CONFIG_VIA_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+CONFIG_INTEL_MEI_WDT=m
+CONFIG_NI903X_WDT=m
+CONFIG_NIC7018_WDT=m
+CONFIG_MEN_A21_WDT=m
+CONFIG_XEN_WDT=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_SSB_DRIVER_GPIO=y
+CONFIG_BCMA_POSSIBLE=y
+CONFIG_BCMA=m
+CONFIG_BCMA_BLOCKIO=y
+CONFIG_BCMA_HOST_PCI_POSSIBLE=y
+CONFIG_BCMA_HOST_PCI=y
+# CONFIG_BCMA_HOST_SOC is not set
+CONFIG_BCMA_DRIVER_PCI=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+CONFIG_BCMA_DRIVER_GPIO=y
+# CONFIG_BCMA_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+CONFIG_MFD_AS3711=y
+CONFIG_PMIC_ADP5520=y
+CONFIG_MFD_AAT2870_CORE=y
+CONFIG_MFD_BCM590XX=m
+CONFIG_MFD_BD9571MWV=m
+CONFIG_MFD_AXP20X=m
+CONFIG_MFD_AXP20X_I2C=m
+CONFIG_MFD_CROS_EC_DEV=m
+CONFIG_MFD_MADERA=m
+CONFIG_MFD_MADERA_I2C=m
+CONFIG_MFD_MADERA_SPI=m
+CONFIG_MFD_CS47L15=y
+CONFIG_MFD_CS47L35=y
+CONFIG_MFD_CS47L85=y
+CONFIG_MFD_CS47L90=y
+CONFIG_MFD_CS47L92=y
+CONFIG_PMIC_DA903X=y
+CONFIG_PMIC_DA9052=y
+CONFIG_MFD_DA9052_SPI=y
+CONFIG_MFD_DA9052_I2C=y
+CONFIG_MFD_DA9055=y
+CONFIG_MFD_DA9062=m
+CONFIG_MFD_DA9063=m
+CONFIG_MFD_DA9150=m
+CONFIG_MFD_DLN2=m
+CONFIG_MFD_MC13XXX=m
+CONFIG_MFD_MC13XXX_SPI=m
+CONFIG_MFD_MC13XXX_I2C=m
+CONFIG_MFD_MP2629=m
+CONFIG_HTC_PASIC3=m
+CONFIG_HTC_I2CPLD=y
+CONFIG_MFD_INTEL_QUARK_I2C_GPIO=m
+CONFIG_LPC_ICH=m
+CONFIG_LPC_SCH=m
+CONFIG_INTEL_SOC_PMIC=y
+CONFIG_INTEL_SOC_PMIC_BXTWC=m
+CONFIG_INTEL_SOC_PMIC_CHTWC=y
+CONFIG_INTEL_SOC_PMIC_CHTDC_TI=m
+CONFIG_INTEL_SOC_PMIC_MRFLD=m
+CONFIG_MFD_INTEL_LPSS=m
+CONFIG_MFD_INTEL_LPSS_ACPI=m
+CONFIG_MFD_INTEL_LPSS_PCI=m
+CONFIG_MFD_INTEL_PMC_BXT=m
+CONFIG_MFD_INTEL_PMT=m
+CONFIG_MFD_IQS62X=m
+CONFIG_MFD_JANZ_CMODIO=m
+CONFIG_MFD_KEMPLD=m
+CONFIG_MFD_88PM800=m
+CONFIG_MFD_88PM805=m
+CONFIG_MFD_88PM860X=y
+CONFIG_MFD_MAX14577=m
+CONFIG_MFD_MAX77693=m
+CONFIG_MFD_MAX77843=y
+CONFIG_MFD_MAX8907=m
+CONFIG_MFD_MAX8925=y
+CONFIG_MFD_MAX8997=y
+CONFIG_MFD_MAX8998=y
+CONFIG_MFD_MT6360=m
+CONFIG_MFD_MT6397=m
+CONFIG_MFD_MENF21BMC=m
+CONFIG_EZX_PCAP=y
+CONFIG_MFD_VIPERBOARD=m
+CONFIG_MFD_RETU=m
+CONFIG_MFD_PCF50633=m
+CONFIG_PCF50633_ADC=m
+CONFIG_PCF50633_GPIO=m
+CONFIG_UCB1400_CORE=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_RT4831=m
+CONFIG_MFD_RT5033=m
+CONFIG_MFD_RC5T583=y
+CONFIG_MFD_SI476X_CORE=m
+CONFIG_MFD_SM501=m
+CONFIG_MFD_SM501_GPIO=y
+CONFIG_MFD_SKY81452=m
+CONFIG_MFD_SYSCON=y
+CONFIG_MFD_TI_AM335X_TSCADC=m
+CONFIG_MFD_LP3943=m
+CONFIG_MFD_LP8788=y
+CONFIG_MFD_TI_LMU=m
+CONFIG_MFD_PALMAS=y
+CONFIG_TPS6105X=m
+CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
+CONFIG_MFD_TPS65086=m
+CONFIG_MFD_TPS65090=y
+CONFIG_MFD_TI_LP873X=m
+CONFIG_MFD_TPS6586X=y
+CONFIG_MFD_TPS65910=y
+CONFIG_MFD_TPS65912=m
+CONFIG_MFD_TPS65912_I2C=m
+CONFIG_MFD_TPS65912_SPI=m
+CONFIG_MFD_TPS80031=y
+CONFIG_TWL4030_CORE=y
+CONFIG_MFD_TWL4030_AUDIO=y
+CONFIG_TWL6040_CORE=y
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_MFD_LM3533=m
+CONFIG_MFD_TQMX86=m
+CONFIG_MFD_VX855=m
+CONFIG_MFD_ARIZONA=m
+CONFIG_MFD_ARIZONA_I2C=m
+CONFIG_MFD_ARIZONA_SPI=m
+CONFIG_MFD_CS47L24=y
+CONFIG_MFD_WM5102=y
+CONFIG_MFD_WM5110=y
+CONFIG_MFD_WM8997=y
+CONFIG_MFD_WM8998=y
+CONFIG_MFD_WM8400=y
+CONFIG_MFD_WM831X=y
+CONFIG_MFD_WM831X_I2C=y
+CONFIG_MFD_WM831X_SPI=y
+CONFIG_MFD_WM8350=y
+CONFIG_MFD_WM8350_I2C=y
+CONFIG_MFD_WM8994=m
+CONFIG_MFD_WCD934X=m
+CONFIG_MFD_ATC260X=m
+CONFIG_MFD_ATC260X_I2C=m
+CONFIG_RAVE_SP_CORE=m
+CONFIG_MFD_INTEL_M10_BMC=m
+# end of Multifunction device drivers
+
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=m
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_REGULATOR_88PG86X=m
+CONFIG_REGULATOR_88PM800=m
+CONFIG_REGULATOR_88PM8607=m
+CONFIG_REGULATOR_ACT8865=m
+CONFIG_REGULATOR_AD5398=m
+CONFIG_REGULATOR_AAT2870=m
+CONFIG_REGULATOR_ARIZONA_LDO1=m
+CONFIG_REGULATOR_ARIZONA_MICSUPP=m
+CONFIG_REGULATOR_AS3711=m
+CONFIG_REGULATOR_ATC260X=m
+CONFIG_REGULATOR_AXP20X=m
+CONFIG_REGULATOR_BCM590XX=m
+CONFIG_REGULATOR_BD9571MWV=m
+CONFIG_REGULATOR_DA903X=m
+CONFIG_REGULATOR_DA9052=m
+CONFIG_REGULATOR_DA9055=m
+CONFIG_REGULATOR_DA9062=m
+CONFIG_REGULATOR_DA9210=m
+CONFIG_REGULATOR_DA9211=m
+CONFIG_REGULATOR_FAN53555=m
+CONFIG_REGULATOR_GPIO=m
+CONFIG_REGULATOR_ISL9305=m
+CONFIG_REGULATOR_ISL6271A=m
+CONFIG_REGULATOR_LM363X=m
+CONFIG_REGULATOR_LP3971=m
+CONFIG_REGULATOR_LP3972=m
+CONFIG_REGULATOR_LP872X=m
+CONFIG_REGULATOR_LP8755=m
+CONFIG_REGULATOR_LP8788=m
+CONFIG_REGULATOR_LTC3589=m
+CONFIG_REGULATOR_LTC3676=m
+CONFIG_REGULATOR_MAX14577=m
+CONFIG_REGULATOR_MAX1586=m
+CONFIG_REGULATOR_MAX8649=m
+CONFIG_REGULATOR_MAX8660=m
+CONFIG_REGULATOR_MAX8893=m
+CONFIG_REGULATOR_MAX8907=m
+CONFIG_REGULATOR_MAX8925=m
+CONFIG_REGULATOR_MAX8952=m
+CONFIG_REGULATOR_MAX8997=m
+CONFIG_REGULATOR_MAX8998=m
+CONFIG_REGULATOR_MAX77693=m
+CONFIG_REGULATOR_MAX77826=m
+CONFIG_REGULATOR_MC13XXX_CORE=m
+CONFIG_REGULATOR_MC13783=m
+CONFIG_REGULATOR_MC13892=m
+CONFIG_REGULATOR_MP8859=m
+CONFIG_REGULATOR_MT6311=m
+CONFIG_REGULATOR_MT6323=m
+CONFIG_REGULATOR_MT6358=m
+CONFIG_REGULATOR_MT6359=m
+CONFIG_REGULATOR_MT6360=m
+CONFIG_REGULATOR_MT6397=m
+CONFIG_REGULATOR_PALMAS=m
+CONFIG_REGULATOR_PCA9450=m
+CONFIG_REGULATOR_PCAP=m
+CONFIG_REGULATOR_PCF50633=m
+CONFIG_REGULATOR_PV88060=m
+CONFIG_REGULATOR_PV88080=m
+CONFIG_REGULATOR_PV88090=m
+CONFIG_REGULATOR_PWM=m
+CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=m
+CONFIG_REGULATOR_RC5T583=m
+CONFIG_REGULATOR_RT4801=m
+CONFIG_REGULATOR_RT4831=m
+CONFIG_REGULATOR_RT5033=m
+CONFIG_REGULATOR_RT6160=m
+CONFIG_REGULATOR_RT6245=m
+CONFIG_REGULATOR_RTQ2134=m
+CONFIG_REGULATOR_RTMV20=m
+CONFIG_REGULATOR_RTQ6752=m
+CONFIG_REGULATOR_SKY81452=m
+CONFIG_REGULATOR_SLG51000=m
+CONFIG_REGULATOR_TPS51632=m
+CONFIG_REGULATOR_TPS6105X=m
+CONFIG_REGULATOR_TPS62360=m
+CONFIG_REGULATOR_TPS65023=m
+CONFIG_REGULATOR_TPS6507X=m
+CONFIG_REGULATOR_TPS65086=m
+CONFIG_REGULATOR_TPS65090=m
+CONFIG_REGULATOR_TPS65132=m
+CONFIG_REGULATOR_TPS6524X=m
+CONFIG_REGULATOR_TPS6586X=m
+CONFIG_REGULATOR_TPS65910=m
+CONFIG_REGULATOR_TPS65912=m
+CONFIG_REGULATOR_TPS80031=m
+CONFIG_REGULATOR_TWL4030=m
+CONFIG_REGULATOR_WM831X=m
+CONFIG_REGULATOR_WM8350=m
+CONFIG_REGULATOR_WM8400=m
+CONFIG_REGULATOR_WM8994=m
+CONFIG_RC_CORE=y
+CONFIG_RC_MAP=m
+CONFIG_LIRC=y
+CONFIG_BPF_LIRC_MODE2=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_SANYO_DECODER=m
+CONFIG_IR_SHARP_DECODER=m
+CONFIG_IR_MCE_KBD_DECODER=m
+CONFIG_IR_XMP_DECODER=m
+CONFIG_IR_IMON_DECODER=m
+CONFIG_IR_RCMM_DECODER=m
+CONFIG_RC_DEVICES=y
+CONFIG_RC_ATI_REMOTE=m
+CONFIG_IR_ENE=m
+CONFIG_IR_IMON=m
+CONFIG_IR_IMON_RAW=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_ITE_CIR=m
+CONFIG_IR_FINTEK=m
+CONFIG_IR_NUVOTON=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_WINBOND_CIR=m
+CONFIG_IR_IGORPLUGUSB=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_TTUSBIR=m
+CONFIG_RC_LOOPBACK=m
+CONFIG_IR_SERIAL=m
+CONFIG_IR_SERIAL_TRANSMITTER=y
+CONFIG_IR_SIR=m
+CONFIG_RC_XBOX_DVD=m
+CONFIG_IR_TOY=m
+CONFIG_CEC_CORE=y
+CONFIG_CEC_NOTIFIER=y
+CONFIG_CEC_PIN=y
+CONFIG_MEDIA_CEC_RC=y
+# CONFIG_CEC_PIN_ERROR_INJ is not set
+CONFIG_MEDIA_CEC_SUPPORT=y
+CONFIG_CEC_CH7322=m
+CONFIG_CEC_CROS_EC=m
+CONFIG_CEC_GPIO=m
+CONFIG_CEC_SECO=m
+CONFIG_CEC_SECO_RC=y
+CONFIG_USB_PULSE8_CEC=m
+CONFIG_USB_RAINSHADOW_CEC=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_SUPPORT_FILTER=y
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Media device types
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+CONFIG_MEDIA_PLATFORM_SUPPORT=y
+CONFIG_MEDIA_TEST_SUPPORT=y
+# end of Media device types
+
+CONFIG_VIDEO_DEV=m
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_DVB_CORE=m
+
+#
+# Video4Linux options
+#
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L2_I2C=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_V4L2_FLASH_LED_CLASS=m
+CONFIG_V4L2_FWNODE=m
+CONFIG_V4L2_ASYNC=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+# end of Video4Linux options
+
+#
+# Media controller options
+#
+CONFIG_MEDIA_CONTROLLER_DVB=y
+CONFIG_MEDIA_CONTROLLER_REQUEST_API=y
+
+#
+# Please notice that the enabled Media controller Request API is EXPERIMENTAL
+#
+# end of Media controller options
+
+#
+# Digital TV options
+#
+CONFIG_DVB_MMAP=y
+CONFIG_DVB_NET=y
+CONFIG_DVB_MAX_ADAPTERS=16
+CONFIG_DVB_DYNAMIC_MINORS=y
+# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set
+# CONFIG_DVB_ULE_DEBUG is not set
+# end of Digital TV options
+
+#
+# Media drivers
+#
+
+#
+# Drivers filtered as selected at 'Filter media drivers'
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_DTCS033=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STK1135=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TOUPTEK=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_VIDEO_CPIA2=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_VIDEO_USBTV=m
+
+#
+# Analog TV USB devices
+#
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_STK1160_COMMON=m
+CONFIG_VIDEO_STK1160=m
+CONFIG_VIDEO_GO7007=m
+CONFIG_VIDEO_GO7007_USB=m
+CONFIG_VIDEO_GO7007_LOADER=m
+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
+
+#
+# Analog/digital TV USB devices
+#
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_AU0828_V4L2=y
+CONFIG_VIDEO_AU0828_RC=y
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_TM6000=m
+CONFIG_VIDEO_TM6000_ALSA=m
+CONFIG_VIDEO_TM6000_DVB=m
+
+#
+# Digital TV USB devices
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_DIB3000MC=m
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_CXUSB_ANALOG=y
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_PCTV452E=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_USB_TECHNISAT_USB2=m
+CONFIG_DVB_USB_V2=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_AF9035=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_LME2510=m
+CONFIG_DVB_USB_MXL111SF=m
+CONFIG_DVB_USB_RTL28XXU=m
+CONFIG_DVB_USB_DVBSKY=m
+CONFIG_DVB_USB_ZD1301=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_SMS_USB_DRV=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
+CONFIG_DVB_AS102=m
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_V4L2=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_EM28XX_RC=m
+CONFIG_MEDIA_PCI_SUPPORT=y
+
+#
+# Media capture support
+#
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SOLO6X10=m
+CONFIG_VIDEO_TW5864=m
+CONFIG_VIDEO_TW68=m
+CONFIG_VIDEO_TW686X=m
+
+#
+# Media capture/analog TV support
+#
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_IVTV_ALSA=m
+# CONFIG_VIDEO_FB_IVTV is not set
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DT3155=m
+
+#
+# Media capture/analog/hybrid TV support
+#
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_MEDIA_ALTERA_CI=m
+CONFIG_VIDEO_CX25821=m
+CONFIG_VIDEO_CX25821_ALSA=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_ENABLE_VP3054=y
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_BT848=m
+CONFIG_DVB_BT8XX=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_RC=y
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_SAA7134_GO7007=m
+CONFIG_VIDEO_SAA7164=m
+
+#
+# Media digital TV PCI Adapters
+#
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set
+CONFIG_DVB_PLUTO2=m
+CONFIG_DVB_DM1105=m
+CONFIG_DVB_PT1=m
+CONFIG_DVB_PT3=m
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+CONFIG_DVB_NGENE=m
+CONFIG_DVB_DDBRIDGE=m
+# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set
+CONFIG_DVB_SMIPCIE=m
+CONFIG_DVB_NETUP_UNIDVB=m
+CONFIG_VIDEO_IPU3_CIO2=m
+CONFIG_CIO2_BRIDGE=y
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_TEA575X=m
+CONFIG_RADIO_SI470X=m
+CONFIG_USB_SI470X=m
+CONFIG_I2C_SI470X=m
+CONFIG_RADIO_SI4713=m
+CONFIG_USB_SI4713=m
+CONFIG_PLATFORM_SI4713=m
+CONFIG_I2C_SI4713=m
+CONFIG_RADIO_SI476X=m
+CONFIG_USB_MR800=m
+CONFIG_USB_DSBR=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_SHARK=m
+CONFIG_RADIO_SHARK2=m
+CONFIG_USB_KEENE=m
+CONFIG_USB_RAREMONO=m
+CONFIG_USB_MA901=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_WL1273=m
+CONFIG_RADIO_WL128X=m
+CONFIG_MEDIA_COMMON_OPTIONS=y
+
+#
+# common driver options
+#
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_TTPCI_EEPROM=m
+CONFIG_CYPRESS_FIRMWARE=m
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEOBUF2_V4L2=m
+CONFIG_VIDEOBUF2_MEMOPS=m
+CONFIG_VIDEOBUF2_DMA_CONTIG=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+CONFIG_VIDEOBUF2_DMA_SG=m
+CONFIG_VIDEOBUF2_DVB=m
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_SMS_SIANO_MDTV=m
+CONFIG_SMS_SIANO_RC=y
+# CONFIG_SMS_SIANO_DEBUGFS is not set
+CONFIG_VIDEO_V4L2_TPG=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_CAFE_CCIC=m
+CONFIG_VIDEO_CADENCE=y
+CONFIG_VIDEO_CADENCE_CSI2RX=m
+CONFIG_VIDEO_CADENCE_CSI2TX=m
+CONFIG_VIDEO_ASPEED=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
+CONFIG_DVB_PLATFORM_DRIVERS=y
+
+#
+# MMC/SDIO DVB adapters
+#
+CONFIG_SMS_SDIO_DRV=m
+CONFIG_V4L_TEST_DRIVERS=y
+CONFIG_VIDEO_VIMC=m
+CONFIG_VIDEO_VIVID=m
+CONFIG_VIDEO_VIVID_CEC=y
+CONFIG_VIDEO_VIVID_MAX_DEVS=64
+CONFIG_VIDEO_VIM2M=m
+CONFIG_VIDEO_VICODEC=m
+CONFIG_DVB_TEST_DRIVERS=y
+CONFIG_DVB_VIDTV=m
+
+#
+# FireWire (IEEE 1394) Adapters
+#
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_INPUT=y
+# end of Media drivers
+
+CONFIG_MEDIA_HIDE_ANCILLARY_SUBDRV=y
+
+#
+# Media ancillary drivers
+#
+CONFIG_MEDIA_ATTACH=y
+
+#
+# IR I2C driver auto-selected by 'Autoselect ancillary drivers'
+#
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# audio, video and radio I2C drivers auto-selected by 'Autoselect ancillary drivers'
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS3308=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_UDA1342=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+CONFIG_VIDEO_SONY_BTF_MPX=m
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_TW2804=m
+CONFIG_VIDEO_TW9903=m
+CONFIG_VIDEO_TW9906=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+CONFIG_VIDEO_SAA6752HS=m
+CONFIG_VIDEO_M52790=m
+
+#
+# Camera sensor devices
+#
+CONFIG_VIDEO_APTINA_PLL=m
+CONFIG_VIDEO_CCS_PLL=m
+CONFIG_VIDEO_HI556=m
+CONFIG_VIDEO_IMX208=m
+CONFIG_VIDEO_IMX214=m
+CONFIG_VIDEO_IMX219=m
+CONFIG_VIDEO_IMX258=m
+CONFIG_VIDEO_IMX274=m
+CONFIG_VIDEO_IMX290=m
+CONFIG_VIDEO_IMX319=m
+CONFIG_VIDEO_IMX355=m
+CONFIG_VIDEO_OV02A10=m
+CONFIG_VIDEO_OV2640=m
+CONFIG_VIDEO_OV2659=m
+CONFIG_VIDEO_OV2680=m
+CONFIG_VIDEO_OV2685=m
+CONFIG_VIDEO_OV2740=m
+CONFIG_VIDEO_OV5647=m
+CONFIG_VIDEO_OV5648=m
+CONFIG_VIDEO_OV6650=m
+CONFIG_VIDEO_OV5670=m
+CONFIG_VIDEO_OV5675=m
+CONFIG_VIDEO_OV5695=m
+CONFIG_VIDEO_OV7251=m
+CONFIG_VIDEO_OV772X=m
+CONFIG_VIDEO_OV7640=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_OV7740=m
+CONFIG_VIDEO_OV8856=m
+CONFIG_VIDEO_OV8865=m
+CONFIG_VIDEO_OV9640=m
+CONFIG_VIDEO_OV9650=m
+CONFIG_VIDEO_OV9734=m
+CONFIG_VIDEO_OV13858=m
+CONFIG_VIDEO_VS6624=m
+CONFIG_VIDEO_MT9M001=m
+CONFIG_VIDEO_MT9M032=m
+CONFIG_VIDEO_MT9M111=m
+CONFIG_VIDEO_MT9P031=m
+CONFIG_VIDEO_MT9T001=m
+CONFIG_VIDEO_MT9T112=m
+CONFIG_VIDEO_MT9V011=m
+CONFIG_VIDEO_MT9V032=m
+CONFIG_VIDEO_MT9V111=m
+CONFIG_VIDEO_SR030PC30=m
+CONFIG_VIDEO_NOON010PC30=m
+CONFIG_VIDEO_M5MOLS=m
+CONFIG_VIDEO_MAX9271_LIB=m
+CONFIG_VIDEO_RDACM20=m
+CONFIG_VIDEO_RDACM21=m
+CONFIG_VIDEO_RJ54N1=m
+CONFIG_VIDEO_S5K6AA=m
+CONFIG_VIDEO_S5K6A3=m
+CONFIG_VIDEO_S5K4ECGX=m
+CONFIG_VIDEO_S5K5BAF=m
+CONFIG_VIDEO_CCS=m
+CONFIG_VIDEO_ET8EK8=m
+CONFIG_VIDEO_S5C73M3=m
+# end of Camera sensor devices
+
+#
+# Lens drivers
+#
+CONFIG_VIDEO_AD5820=m
+CONFIG_VIDEO_AK7375=m
+CONFIG_VIDEO_DW9714=m
+CONFIG_VIDEO_DW9768=m
+CONFIG_VIDEO_DW9807_VCM=m
+# end of Lens drivers
+
+#
+# Flash devices
+#
+CONFIG_VIDEO_ADP1653=m
+CONFIG_VIDEO_LM3560=m
+CONFIG_VIDEO_LM3646=m
+# end of Flash devices
+
+#
+# SPI I2C drivers auto-selected by 'Autoselect ancillary drivers'
+#
+
+#
+# Media SPI Adapters
+#
+CONFIG_CXD2880_SPI_DRV=m
+# end of Media SPI Adapters
+
+CONFIG_MEDIA_TUNER=m
+
+#
+# Tuner drivers auto-selected by 'Autoselect ancillary drivers'
+#
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA18250=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2063=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_XC4000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_MEDIA_TUNER_FC0011=m
+CONFIG_MEDIA_TUNER_FC0012=m
+CONFIG_MEDIA_TUNER_FC0013=m
+CONFIG_MEDIA_TUNER_TDA18212=m
+CONFIG_MEDIA_TUNER_E4000=m
+CONFIG_MEDIA_TUNER_FC2580=m
+CONFIG_MEDIA_TUNER_M88RS6000T=m
+CONFIG_MEDIA_TUNER_TUA9001=m
+CONFIG_MEDIA_TUNER_SI2157=m
+CONFIG_MEDIA_TUNER_IT913X=m
+CONFIG_MEDIA_TUNER_R820T=m
+CONFIG_MEDIA_TUNER_MXL301RF=m
+CONFIG_MEDIA_TUNER_QM1D1C0042=m
+CONFIG_MEDIA_TUNER_QM1D1B0004=m
+
+#
+# DVB Frontend drivers auto-selected by 'Autoselect ancillary drivers'
+#
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV0910=m
+CONFIG_DVB_STV6110x=m
+CONFIG_DVB_STV6111=m
+CONFIG_DVB_MXL5XX=m
+CONFIG_DVB_M88DS3103=m
+
+#
+# Multistandard (cable + terrestrial) frontends
+#
+CONFIG_DVB_DRXK=m
+CONFIG_DVB_TDA18271C2DD=m
+CONFIG_DVB_SI2165=m
+CONFIG_DVB_MN88472=m
+CONFIG_DVB_MN88473=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_CX24117=m
+CONFIG_DVB_CX24120=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_TS2020=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
+CONFIG_DVB_TDA10071=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRXD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+CONFIG_DVB_STV0367=m
+CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_CXD2841ER=m
+CONFIG_DVB_RTL2830=m
+CONFIG_DVB_RTL2832=m
+CONFIG_DVB_SI2168=m
+CONFIG_DVB_AS102_FE=m
+CONFIG_DVB_ZD1301_DEMOD=m
+CONFIG_DVB_GP8PSK_FE=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_LGDT3306A=m
+CONFIG_DVB_LG2160=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_AU8522_DTV=m
+CONFIG_DVB_AU8522_V4L=m
+CONFIG_DVB_S5H1411=m
+CONFIG_DVB_MXL692=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_TC90522=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_DRX39XYJ=m
+CONFIG_DVB_LNBH25=m
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_LNBP22=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_A8293=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
+CONFIG_DVB_IX2505V=m
+CONFIG_DVB_M88RS2000=m
+CONFIG_DVB_AF9033=m
+CONFIG_DVB_HORUS3A=m
+CONFIG_DVB_ASCOT2E=m
+CONFIG_DVB_HELENE=m
+
+#
+# Common Interface (EN50221) controller drivers
+#
+CONFIG_DVB_CXD2099=m
+CONFIG_DVB_SP2=m
+
+#
+# Tools to develop new frontends
+#
+CONFIG_DVB_DUMMY_FE=m
+# end of Media ancillary drivers
+
+#
+# Graphics support
+#
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_VIA=m
+CONFIG_INTEL_GTT=m
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=10
+CONFIG_VGA_SWITCHEROO=y
+CONFIG_DRM=y
+CONFIG_DRM_MIPI_DBI=m
+CONFIG_DRM_MIPI_DSI=y
+CONFIG_DRM_DP_AUX_CHARDEV=y
+# CONFIG_DRM_DEBUG_MM is not set
+# CONFIG_DRM_DEBUG_SELFTEST is not set
+CONFIG_DRM_KMS_HELPER=y
+CONFIG_DRM_FBDEV_EMULATION=y
+CONFIG_DRM_FBDEV_OVERALLOC=100
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_DRM_DP_CEC=y
+CONFIG_DRM_TTM=m
+CONFIG_DRM_VRAM_HELPER=m
+CONFIG_DRM_TTM_HELPER=m
+CONFIG_DRM_GEM_CMA_HELPER=y
+CONFIG_DRM_KMS_CMA_HELPER=y
+CONFIG_DRM_GEM_SHMEM_HELPER=y
+CONFIG_DRM_SCHED=m
+
+#
+# I2C encoder or helper chips
+#
+CONFIG_DRM_I2C_CH7006=m
+CONFIG_DRM_I2C_SIL164=m
+CONFIG_DRM_I2C_NXP_TDA998X=m
+CONFIG_DRM_I2C_NXP_TDA9950=m
+# end of I2C encoder or helper chips
+
+#
+# ARM devices
+#
+# end of ARM devices
+
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_RADEON_USERPTR=y
+CONFIG_DRM_AMDGPU=m
+CONFIG_DRM_AMDGPU_SI=y
+CONFIG_DRM_AMDGPU_CIK=y
+CONFIG_DRM_AMDGPU_USERPTR=y
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+CONFIG_DRM_AMD_ACP=y
+# end of ACP (Audio CoProcessor) Configuration
+
+#
+# Display Engine Configuration
+#
+CONFIG_DRM_AMD_DC=y
+CONFIG_DRM_AMD_DC_DCN=y
+CONFIG_DRM_AMD_DC_HDCP=y
+CONFIG_DRM_AMD_DC_SI=y
+CONFIG_DRM_AMD_SECURE_DISPLAY=y
+# end of Display Engine Configuration
+
+CONFIG_HSA_AMD=y
+CONFIG_HSA_AMD_SVM=y
+CONFIG_DRM_NOUVEAU=m
+# CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT is not set
+CONFIG_NOUVEAU_DEBUG=5
+CONFIG_NOUVEAU_DEBUG_DEFAULT=3
+# CONFIG_NOUVEAU_DEBUG_MMU is not set
+# CONFIG_NOUVEAU_DEBUG_PUSH is not set
+CONFIG_DRM_NOUVEAU_BACKLIGHT=y
+CONFIG_DRM_NOUVEAU_SVM=y
+CONFIG_DRM_I915=m
+CONFIG_DRM_I915_FORCE_PROBE="*"
+CONFIG_DRM_I915_CAPTURE_ERROR=y
+CONFIG_DRM_I915_COMPRESS_ERROR=y
+CONFIG_DRM_I915_USERPTR=y
+CONFIG_DRM_I915_GVT=y
+CONFIG_DRM_I915_GVT_KVMGT=m
+CONFIG_DRM_I915_REQUEST_TIMEOUT=20000
+CONFIG_DRM_I915_FENCE_TIMEOUT=10000
+CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=250
+CONFIG_DRM_I915_HEARTBEAT_INTERVAL=2500
+CONFIG_DRM_I915_PREEMPT_TIMEOUT=640
+CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT=8000
+CONFIG_DRM_I915_STOP_TIMEOUT=100
+CONFIG_DRM_I915_TIMESLICE_DURATION=1
+CONFIG_DRM_VGEM=m
+CONFIG_DRM_VKMS=m
+CONFIG_DRM_VMWGFX=m
+CONFIG_DRM_VMWGFX_FBCON=y
+CONFIG_DRM_VMWGFX_MKSSTATS=y
+CONFIG_DRM_GMA500=m
+CONFIG_DRM_UDL=m
+CONFIG_DRM_AST=m
+CONFIG_DRM_MGAG200=m
+CONFIG_DRM_QXL=m
+CONFIG_DRM_VIRTIO_GPU=m
+CONFIG_DRM_PANEL=y
+
+#
+# Display Panels
+#
+CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m
+CONFIG_DRM_PANEL_WIDECHIPS_WS2401=m
+# end of Display Panels
+
+CONFIG_DRM_BRIDGE=y
+CONFIG_DRM_PANEL_BRIDGE=y
+
+#
+# Display Interface Bridges
+#
+CONFIG_DRM_ANALOGIX_ANX78XX=m
+CONFIG_DRM_ANALOGIX_DP=m
+# end of Display Interface Bridges
+
+# CONFIG_DRM_ETNAVIV is not set
+CONFIG_DRM_BOCHS=m
+CONFIG_DRM_CIRRUS_QEMU=m
+CONFIG_DRM_GM12U320=m
+CONFIG_DRM_SIMPLEDRM=y
+CONFIG_TINYDRM_HX8357D=m
+CONFIG_TINYDRM_ILI9225=m
+CONFIG_TINYDRM_ILI9341=m
+CONFIG_TINYDRM_ILI9486=m
+CONFIG_TINYDRM_MI0283QT=m
+CONFIG_TINYDRM_REPAPER=m
+CONFIG_TINYDRM_ST7586=m
+CONFIG_TINYDRM_ST7735R=m
+CONFIG_DRM_XEN=y
+CONFIG_DRM_XEN_FRONTEND=m
+CONFIG_DRM_VBOXVIDEO=m
+CONFIG_DRM_GUD=m
+CONFIG_DRM_HYPERV=m
+# CONFIG_DRM_LEGACY is not set
+CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_BOOT_VESA_SUPPORT=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+CONFIG_FB_VESA=y
+CONFIG_FB_EFI=y
+# CONFIG_FB_N411 is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I740 is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_SM501 is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_XEN_FBDEV_FRONTEND is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_HYPERV is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_FB_SM712 is not set
+# end of Frame buffer Devices
+
+#
+# Backlight & LCD device support
+#
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_L4F00242T03=m
+CONFIG_LCD_LMS283GF05=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI922X=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_AMS369FG06=m
+CONFIG_LCD_LMS501KF03=m
+CONFIG_LCD_HX8357=m
+CONFIG_LCD_OTM3225A=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_KTD253=m
+CONFIG_BACKLIGHT_LM3533=m
+CONFIG_BACKLIGHT_PWM=m
+CONFIG_BACKLIGHT_DA903X=m
+CONFIG_BACKLIGHT_DA9052=m
+CONFIG_BACKLIGHT_MAX8925=m
+CONFIG_BACKLIGHT_APPLE=m
+CONFIG_BACKLIGHT_QCOM_WLED=m
+CONFIG_BACKLIGHT_RT4831=m
+CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_WM831X=m
+CONFIG_BACKLIGHT_ADP5520=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_ADP8870=m
+CONFIG_BACKLIGHT_88PM860X=m
+CONFIG_BACKLIGHT_PCF50633=m
+CONFIG_BACKLIGHT_AAT2870=m
+CONFIG_BACKLIGHT_LM3630A=m
+CONFIG_BACKLIGHT_LM3639=m
+CONFIG_BACKLIGHT_LP855X=m
+CONFIG_BACKLIGHT_LP8788=m
+CONFIG_BACKLIGHT_PANDORA=m
+CONFIG_BACKLIGHT_SKY81452=m
+CONFIG_BACKLIGHT_AS3711=m
+CONFIG_BACKLIGHT_GPIO=m
+CONFIG_BACKLIGHT_LV5207LP=m
+CONFIG_BACKLIGHT_BD6107=m
+CONFIG_BACKLIGHT_ARCXCNN=m
+CONFIG_BACKLIGHT_RAVE_SP=m
+# end of Backlight & LCD device support
+
+CONFIG_VIDEOMODE_HELPERS=y
+CONFIG_HDMI=y
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=80
+CONFIG_DUMMY_CONSOLE_ROWS=25
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+CONFIG_BOOTSPLASH=y
+# end of Console display driver support
+
+# CONFIG_LOGO is not set
+# end of Graphics support
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_PCM_ELD=y
+CONFIG_SND_PCM_IEC958=y
+CONFIG_SND_DMAENGINE_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_SEQ_DEVICE=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_COMPRESS_OFFLOAD=m
+CONFIG_SND_JACK=y
+CONFIG_SND_JACK_INPUT_DEV=y
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCM_TIMER=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_MAX_CARDS=32
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_PROC_FS=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+# CONFIG_SND_CTL_VALIDATION is not set
+# CONFIG_SND_JACK_INJECTION_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_CTL_LED=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQUENCER_OSS=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_SEQ_MIDI_EVENT=m
+CONFIG_SND_SEQ_MIDI=m
+CONFIG_SND_SEQ_MIDI_EMUL=m
+CONFIG_SND_SEQ_VIRMIDI=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_PCSP is not set
+CONFIG_SND_DUMMY=m
+CONFIG_SND_ALOOP=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
+CONFIG_SND_ES1968_RADIO=y
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LOLA=m
+CONFIG_SND_LX6464ES=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+
+#
+# HD-Audio
+#
+CONFIG_SND_HDA=m
+CONFIG_SND_HDA_GENERIC_LEDS=y
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_HWDEP=y
+CONFIG_SND_HDA_RECONFIG=y
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=0
+CONFIG_SND_HDA_PATCH_LOADER=y
+CONFIG_SND_HDA_CODEC_REALTEK=m
+CONFIG_SND_HDA_CODEC_ANALOG=m
+CONFIG_SND_HDA_CODEC_SIGMATEL=m
+CONFIG_SND_HDA_CODEC_VIA=m
+CONFIG_SND_HDA_CODEC_HDMI=m
+CONFIG_SND_HDA_CODEC_CIRRUS=m
+CONFIG_SND_HDA_CODEC_CS8409=m
+CONFIG_SND_HDA_CODEC_CONEXANT=m
+CONFIG_SND_HDA_CODEC_CA0110=m
+CONFIG_SND_HDA_CODEC_CA0132=m
+CONFIG_SND_HDA_CODEC_CA0132_DSP=y
+CONFIG_SND_HDA_CODEC_CMEDIA=m
+CONFIG_SND_HDA_CODEC_SI3054=m
+CONFIG_SND_HDA_GENERIC=m
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT=1
+CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM=y
+# end of HD-Audio
+
+CONFIG_SND_HDA_CORE=m
+CONFIG_SND_HDA_DSP_LOADER=y
+CONFIG_SND_HDA_COMPONENT=y
+CONFIG_SND_HDA_I915=y
+CONFIG_SND_HDA_EXT_CORE=m
+CONFIG_SND_HDA_PREALLOC_SIZE=0
+CONFIG_SND_INTEL_NHLT=y
+CONFIG_SND_INTEL_DSP_CONFIG=m
+CONFIG_SND_INTEL_SOUNDWIRE_ACPI=m
+# CONFIG_SND_INTEL_BYT_PREFER_SOF is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=y
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SND_USB_HIFACE=m
+CONFIG_SND_BCD2000=m
+CONFIG_SND_USB_LINE6=m
+CONFIG_SND_USB_POD=m
+CONFIG_SND_USB_PODHD=m
+CONFIG_SND_USB_TONEPORT=m
+CONFIG_SND_USB_VARIAX=m
+CONFIG_SND_FIREWIRE=y
+CONFIG_SND_FIREWIRE_LIB=m
+CONFIG_SND_DICE=m
+CONFIG_SND_OXFW=m
+CONFIG_SND_ISIGHT=m
+CONFIG_SND_FIREWORKS=m
+CONFIG_SND_BEBOB=m
+CONFIG_SND_FIREWIRE_DIGI00X=m
+CONFIG_SND_FIREWIRE_TASCAM=m
+CONFIG_SND_FIREWIRE_MOTU=m
+CONFIG_SND_FIREFACE=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_SOC=m
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
+CONFIG_SND_SOC_COMPRESS=y
+CONFIG_SND_SOC_TOPOLOGY=y
+CONFIG_SND_SOC_ACPI=m
+CONFIG_SND_SOC_ADI=m
+CONFIG_SND_SOC_ADI_AXI_I2S=m
+CONFIG_SND_SOC_ADI_AXI_SPDIF=m
+CONFIG_SND_SOC_AMD_ACP=m
+CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH=m
+CONFIG_SND_SOC_AMD_CZ_RT5645_MACH=m
+CONFIG_SND_SOC_AMD_ACP3x=m
+CONFIG_SND_SOC_AMD_RV_RT5682_MACH=m
+CONFIG_SND_SOC_AMD_RENOIR=m
+CONFIG_SND_SOC_AMD_RENOIR_MACH=m
+CONFIG_SND_SOC_AMD_ACP5x=m
+CONFIG_SND_ATMEL_SOC=m
+# CONFIG_SND_BCM63XX_I2S_WHISTLER is not set
+CONFIG_SND_DESIGNWARE_I2S=m
+CONFIG_SND_DESIGNWARE_PCM=y
+
+#
+# SoC Audio for Freescale CPUs
+#
+
+#
+# Common SoC Audio options for Freescale CPUs:
+#
+# CONFIG_SND_SOC_FSL_ASRC is not set
+# CONFIG_SND_SOC_FSL_SAI is not set
+# CONFIG_SND_SOC_FSL_AUDMIX is not set
+# CONFIG_SND_SOC_FSL_SSI is not set
+# CONFIG_SND_SOC_FSL_SPDIF is not set
+# CONFIG_SND_SOC_FSL_ESAI is not set
+# CONFIG_SND_SOC_FSL_MICFIL is not set
+CONFIG_SND_SOC_FSL_XCVR=m
+CONFIG_SND_SOC_FSL_RPMSG=m
+# CONFIG_SND_SOC_IMX_AUDMUX is not set
+# end of SoC Audio for Freescale CPUs
+
+CONFIG_SND_I2S_HI6210_I2S=m
+CONFIG_SND_SOC_IMG=y
+CONFIG_SND_SOC_IMG_I2S_IN=m
+CONFIG_SND_SOC_IMG_I2S_OUT=m
+CONFIG_SND_SOC_IMG_PARALLEL_OUT=m
+CONFIG_SND_SOC_IMG_SPDIF_IN=m
+CONFIG_SND_SOC_IMG_SPDIF_OUT=m
+CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC=m
+CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y
+CONFIG_SND_SOC_INTEL_SST=m
+CONFIG_SND_SOC_INTEL_CATPT=m
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM=m
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI=m
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI=m
+CONFIG_SND_SOC_INTEL_SKYLAKE=m
+CONFIG_SND_SOC_INTEL_SKL=m
+CONFIG_SND_SOC_INTEL_APL=m
+CONFIG_SND_SOC_INTEL_KBL=m
+CONFIG_SND_SOC_INTEL_GLK=m
+CONFIG_SND_SOC_INTEL_CNL=m
+CONFIG_SND_SOC_INTEL_CFL=m
+CONFIG_SND_SOC_INTEL_CML_H=m
+CONFIG_SND_SOC_INTEL_CML_LP=m
+CONFIG_SND_SOC_INTEL_SKYLAKE_FAMILY=m
+CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK=m
+CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC=y
+CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON=m
+CONFIG_SND_SOC_ACPI_INTEL_MATCH=m
+CONFIG_SND_SOC_INTEL_MACH=y
+CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES=y
+CONFIG_SND_SOC_INTEL_HDA_DSP_COMMON=m
+CONFIG_SND_SOC_INTEL_SOF_MAXIM_COMMON=m
+CONFIG_SND_SOC_INTEL_HASWELL_MACH=m
+CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH=m
+CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH=m
+CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m
+CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m
+CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH=m
+CONFIG_SND_SOC_INTEL_BYTCR_WM5102_MACH=m
+CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m
+CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m
+CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m
+CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH=m
+CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH=m
+CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH=m
+CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH=m
+# CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH is not set
+CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
+CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH=m
+CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH=m
+CONFIG_SND_SOC_INTEL_DA7219_MAX98357A_GENERIC=m
+CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON=m
+CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH=m
+CONFIG_SND_SOC_INTEL_BXT_RT298_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH=m
+CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH=m
+CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH=m
+CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH=m
+CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH=m
+CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH=m
+CONFIG_SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH=m
+CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH=m
+CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH=m
+CONFIG_SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH=m
+CONFIG_SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH=m
+CONFIG_SND_SOC_INTEL_EHL_RT5660_MACH=m
+CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH=m
+CONFIG_SND_SOC_MTK_BTCVSD=m
+CONFIG_SND_SOC_SOF_TOPLEVEL=y
+CONFIG_SND_SOC_SOF_PCI_DEV=m
+CONFIG_SND_SOC_SOF_PCI=m
+CONFIG_SND_SOC_SOF_ACPI=m
+CONFIG_SND_SOC_SOF_ACPI_DEV=m
+# CONFIG_SND_SOC_SOF_DEBUG_PROBES is not set
+CONFIG_SND_SOC_SOF=m
+CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE=y
+CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL=y
+CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC=m
+CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP=m
+CONFIG_SND_SOC_SOF_INTEL_COMMON=m
+CONFIG_SND_SOC_SOF_BAYTRAIL=m
+# CONFIG_SND_SOC_SOF_BROADWELL is not set
+CONFIG_SND_SOC_SOF_MERRIFIELD=m
+CONFIG_SND_SOC_SOF_INTEL_APL=m
+CONFIG_SND_SOC_SOF_APOLLOLAKE=m
+CONFIG_SND_SOC_SOF_GEMINILAKE=m
+CONFIG_SND_SOC_SOF_INTEL_CNL=m
+CONFIG_SND_SOC_SOF_CANNONLAKE=m
+CONFIG_SND_SOC_SOF_COFFEELAKE=m
+CONFIG_SND_SOC_SOF_COMETLAKE=m
+CONFIG_SND_SOC_SOF_INTEL_ICL=m
+CONFIG_SND_SOC_SOF_ICELAKE=m
+CONFIG_SND_SOC_SOF_JASPERLAKE=m
+CONFIG_SND_SOC_SOF_INTEL_TGL=m
+CONFIG_SND_SOC_SOF_TIGERLAKE=m
+CONFIG_SND_SOC_SOF_ELKHARTLAKE=m
+CONFIG_SND_SOC_SOF_ALDERLAKE=m
+CONFIG_SND_SOC_SOF_HDA_COMMON=m
+CONFIG_SND_SOC_SOF_HDA_LINK=y
+CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC=y
+CONFIG_SND_SOC_SOF_HDA_LINK_BASELINE=m
+CONFIG_SND_SOC_SOF_HDA=m
+CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE=m
+CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE=m
+CONFIG_SND_SOC_SOF_XTENSA=m
+
+#
+# STMicroelectronics STM32 SOC audio support
+#
+# end of STMicroelectronics STM32 SOC audio support
+
+CONFIG_SND_SOC_XILINX_I2S=m
+CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=m
+CONFIG_SND_SOC_XILINX_SPDIF=m
+CONFIG_SND_SOC_XTFPGA_I2S=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
+
+#
+# CODEC drivers
+#
+CONFIG_SND_SOC_ARIZONA=m
+CONFIG_SND_SOC_WM_ADSP=m
+CONFIG_SND_SOC_AC97_CODEC=m
+CONFIG_SND_SOC_ADAU_UTILS=m
+CONFIG_SND_SOC_ADAU1372=m
+CONFIG_SND_SOC_ADAU1372_I2C=m
+CONFIG_SND_SOC_ADAU1372_SPI=m
+CONFIG_SND_SOC_ADAU1701=m
+CONFIG_SND_SOC_ADAU17X1=m
+CONFIG_SND_SOC_ADAU1761=m
+CONFIG_SND_SOC_ADAU1761_I2C=m
+CONFIG_SND_SOC_ADAU1761_SPI=m
+CONFIG_SND_SOC_ADAU7002=m
+CONFIG_SND_SOC_ADAU7118=m
+CONFIG_SND_SOC_ADAU7118_HW=m
+CONFIG_SND_SOC_ADAU7118_I2C=m
+CONFIG_SND_SOC_AK4104=m
+CONFIG_SND_SOC_AK4118=m
+CONFIG_SND_SOC_AK4458=m
+CONFIG_SND_SOC_AK4554=m
+CONFIG_SND_SOC_AK4613=m
+CONFIG_SND_SOC_AK4642=m
+CONFIG_SND_SOC_AK5386=m
+CONFIG_SND_SOC_AK5558=m
+CONFIG_SND_SOC_ALC5623=m
+CONFIG_SND_SOC_BD28623=m
+# CONFIG_SND_SOC_BT_SCO is not set
+CONFIG_SND_SOC_CROS_EC_CODEC=m
+CONFIG_SND_SOC_CS35L32=m
+CONFIG_SND_SOC_CS35L33=m
+CONFIG_SND_SOC_CS35L34=m
+CONFIG_SND_SOC_CS35L35=m
+CONFIG_SND_SOC_CS35L36=m
+CONFIG_SND_SOC_CS42L42=m
+CONFIG_SND_SOC_CS42L51=m
+CONFIG_SND_SOC_CS42L51_I2C=m
+CONFIG_SND_SOC_CS42L52=m
+CONFIG_SND_SOC_CS42L56=m
+CONFIG_SND_SOC_CS42L73=m
+CONFIG_SND_SOC_CS4234=m
+CONFIG_SND_SOC_CS4265=m
+CONFIG_SND_SOC_CS4270=m
+CONFIG_SND_SOC_CS4271=m
+CONFIG_SND_SOC_CS4271_I2C=m
+CONFIG_SND_SOC_CS4271_SPI=m
+CONFIG_SND_SOC_CS42XX8=m
+CONFIG_SND_SOC_CS42XX8_I2C=m
+CONFIG_SND_SOC_CS43130=m
+CONFIG_SND_SOC_CS4341=m
+CONFIG_SND_SOC_CS4349=m
+CONFIG_SND_SOC_CS53L30=m
+CONFIG_SND_SOC_CX2072X=m
+CONFIG_SND_SOC_DA7213=m
+CONFIG_SND_SOC_DA7219=m
+CONFIG_SND_SOC_DMIC=m
+CONFIG_SND_SOC_HDMI_CODEC=m
+CONFIG_SND_SOC_ES7134=m
+CONFIG_SND_SOC_ES7241=m
+CONFIG_SND_SOC_ES8316=m
+CONFIG_SND_SOC_ES8328=m
+CONFIG_SND_SOC_ES8328_I2C=m
+CONFIG_SND_SOC_ES8328_SPI=m
+CONFIG_SND_SOC_GTM601=m
+CONFIG_SND_SOC_HDAC_HDMI=m
+CONFIG_SND_SOC_HDAC_HDA=m
+CONFIG_SND_SOC_ICS43432=m
+CONFIG_SND_SOC_INNO_RK3036=m
+CONFIG_SND_SOC_MAX98088=m
+CONFIG_SND_SOC_MAX98090=m
+CONFIG_SND_SOC_MAX98357A=m
+CONFIG_SND_SOC_MAX98504=m
+CONFIG_SND_SOC_MAX9867=m
+CONFIG_SND_SOC_MAX98927=m
+CONFIG_SND_SOC_MAX98373=m
+CONFIG_SND_SOC_MAX98373_I2C=m
+CONFIG_SND_SOC_MAX98373_SDW=m
+CONFIG_SND_SOC_MAX98390=m
+CONFIG_SND_SOC_MAX9860=m
+CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m
+CONFIG_SND_SOC_PCM1681=m
+CONFIG_SND_SOC_PCM1789=m
+CONFIG_SND_SOC_PCM1789_I2C=m
+CONFIG_SND_SOC_PCM179X=m
+CONFIG_SND_SOC_PCM179X_I2C=m
+CONFIG_SND_SOC_PCM179X_SPI=m
+CONFIG_SND_SOC_PCM186X=m
+CONFIG_SND_SOC_PCM186X_I2C=m
+CONFIG_SND_SOC_PCM186X_SPI=m
+CONFIG_SND_SOC_PCM3060=m
+CONFIG_SND_SOC_PCM3060_I2C=m
+CONFIG_SND_SOC_PCM3060_SPI=m
+CONFIG_SND_SOC_PCM3168A=m
+CONFIG_SND_SOC_PCM3168A_I2C=m
+CONFIG_SND_SOC_PCM3168A_SPI=m
+CONFIG_SND_SOC_PCM5102A=m
+CONFIG_SND_SOC_PCM512x=m
+CONFIG_SND_SOC_PCM512x_I2C=m
+CONFIG_SND_SOC_PCM512x_SPI=m
+CONFIG_SND_SOC_RK3328=m
+CONFIG_SND_SOC_RL6231=m
+CONFIG_SND_SOC_RL6347A=m
+CONFIG_SND_SOC_RT286=m
+CONFIG_SND_SOC_RT298=m
+CONFIG_SND_SOC_RT1011=m
+CONFIG_SND_SOC_RT1015=m
+CONFIG_SND_SOC_RT1015P=m
+CONFIG_SND_SOC_RT1308=m
+CONFIG_SND_SOC_RT1308_SDW=m
+CONFIG_SND_SOC_RT1316_SDW=m
+CONFIG_SND_SOC_RT5514=m
+CONFIG_SND_SOC_RT5514_SPI=m
+CONFIG_SND_SOC_RT5616=m
+CONFIG_SND_SOC_RT5631=m
+CONFIG_SND_SOC_RT5640=m
+CONFIG_SND_SOC_RT5645=m
+CONFIG_SND_SOC_RT5651=m
+CONFIG_SND_SOC_RT5659=m
+CONFIG_SND_SOC_RT5660=m
+CONFIG_SND_SOC_RT5663=m
+CONFIG_SND_SOC_RT5670=m
+CONFIG_SND_SOC_RT5677=m
+CONFIG_SND_SOC_RT5677_SPI=m
+CONFIG_SND_SOC_RT5682=m
+CONFIG_SND_SOC_RT5682_I2C=m
+CONFIG_SND_SOC_RT5682_SDW=m
+CONFIG_SND_SOC_RT700=m
+CONFIG_SND_SOC_RT700_SDW=m
+CONFIG_SND_SOC_RT711=m
+CONFIG_SND_SOC_RT711_SDW=m
+CONFIG_SND_SOC_RT711_SDCA_SDW=m
+CONFIG_SND_SOC_RT715=m
+CONFIG_SND_SOC_RT715_SDW=m
+CONFIG_SND_SOC_RT715_SDCA_SDW=m
+# CONFIG_SND_SOC_SDW_MOCKUP is not set
+CONFIG_SND_SOC_SGTL5000=m
+CONFIG_SND_SOC_SI476X=m
+CONFIG_SND_SOC_SIGMADSP=m
+CONFIG_SND_SOC_SIGMADSP_I2C=m
+CONFIG_SND_SOC_SIGMADSP_REGMAP=m
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
+CONFIG_SND_SOC_SIMPLE_MUX=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_SSM2305=m
+CONFIG_SND_SOC_SSM2518=m
+CONFIG_SND_SOC_SSM2602=m
+CONFIG_SND_SOC_SSM2602_SPI=m
+CONFIG_SND_SOC_SSM2602_I2C=m
+CONFIG_SND_SOC_SSM4567=m
+CONFIG_SND_SOC_STA32X=m
+CONFIG_SND_SOC_STA350=m
+CONFIG_SND_SOC_STI_SAS=m
+CONFIG_SND_SOC_TAS2552=m
+CONFIG_SND_SOC_TAS2562=m
+CONFIG_SND_SOC_TAS2764=m
+CONFIG_SND_SOC_TAS2770=m
+CONFIG_SND_SOC_TAS5086=m
+CONFIG_SND_SOC_TAS571X=m
+CONFIG_SND_SOC_TAS5720=m
+CONFIG_SND_SOC_TAS6424=m
+CONFIG_SND_SOC_TDA7419=m
+CONFIG_SND_SOC_TFA9879=m
+CONFIG_SND_SOC_TFA989X=m
+CONFIG_SND_SOC_TLV320AIC23=m
+CONFIG_SND_SOC_TLV320AIC23_I2C=m
+CONFIG_SND_SOC_TLV320AIC23_SPI=m
+CONFIG_SND_SOC_TLV320AIC31XX=m
+CONFIG_SND_SOC_TLV320AIC32X4=m
+CONFIG_SND_SOC_TLV320AIC32X4_I2C=m
+CONFIG_SND_SOC_TLV320AIC32X4_SPI=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TLV320AIC3X_I2C=m
+CONFIG_SND_SOC_TLV320AIC3X_SPI=m
+CONFIG_SND_SOC_TLV320ADCX140=m
+CONFIG_SND_SOC_TS3A227E=m
+CONFIG_SND_SOC_TSCS42XX=m
+CONFIG_SND_SOC_TSCS454=m
+CONFIG_SND_SOC_UDA1334=m
+CONFIG_SND_SOC_WCD9335=m
+CONFIG_SND_SOC_WCD_MBHC=m
+CONFIG_SND_SOC_WCD934X=m
+CONFIG_SND_SOC_WCD938X=m
+CONFIG_SND_SOC_WCD938X_SDW=m
+CONFIG_SND_SOC_WM5102=m
+CONFIG_SND_SOC_WM8510=m
+CONFIG_SND_SOC_WM8523=m
+CONFIG_SND_SOC_WM8524=m
+CONFIG_SND_SOC_WM8580=m
+CONFIG_SND_SOC_WM8711=m
+CONFIG_SND_SOC_WM8728=m
+CONFIG_SND_SOC_WM8731=m
+CONFIG_SND_SOC_WM8737=m
+CONFIG_SND_SOC_WM8741=m
+CONFIG_SND_SOC_WM8750=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8770=m
+CONFIG_SND_SOC_WM8776=m
+CONFIG_SND_SOC_WM8782=m
+CONFIG_SND_SOC_WM8804=m
+CONFIG_SND_SOC_WM8804_I2C=m
+CONFIG_SND_SOC_WM8804_SPI=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_WM8962=m
+CONFIG_SND_SOC_WM8974=m
+CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_WM8985=m
+CONFIG_SND_SOC_WSA881X=m
+CONFIG_SND_SOC_ZL38060=m
+CONFIG_SND_SOC_MAX9759=m
+CONFIG_SND_SOC_MT6351=m
+CONFIG_SND_SOC_MT6358=m
+CONFIG_SND_SOC_MT6660=m
+CONFIG_SND_SOC_NAU8315=m
+CONFIG_SND_SOC_NAU8540=m
+CONFIG_SND_SOC_NAU8810=m
+CONFIG_SND_SOC_NAU8822=m
+CONFIG_SND_SOC_NAU8824=m
+CONFIG_SND_SOC_NAU8825=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SOC_LPASS_WSA_MACRO=m
+CONFIG_SND_SOC_LPASS_VA_MACRO=m
+CONFIG_SND_SOC_LPASS_RX_MACRO=m
+CONFIG_SND_SOC_LPASS_TX_MACRO=m
+# end of CODEC drivers
+
+CONFIG_SND_SIMPLE_CARD_UTILS=m
+CONFIG_SND_SIMPLE_CARD=m
+CONFIG_SND_X86=y
+CONFIG_HDMI_LPE_AUDIO=m
+CONFIG_SND_SYNTH_EMUX=m
+CONFIG_SND_XEN_FRONTEND=m
+CONFIG_SND_VIRTIO=m
+CONFIG_AC97_BUS=m
+
+#
+# HID support
+#
+CONFIG_HID=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=m
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACCUTOUCH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=m
+CONFIG_HID_APPLEIR=m
+CONFIG_HID_ASUS=m
+CONFIG_HID_AUREAL=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BETOP_FF=m
+CONFIG_HID_BIGBEN_FF=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CORSAIR=m
+CONFIG_HID_COUGAR=m
+CONFIG_HID_MACALLY=m
+CONFIG_HID_PRODIKEYS=m
+CONFIG_HID_CMEDIA=m
+CONFIG_HID_CP2112=m
+CONFIG_HID_CREATIVE_SB0540=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELAN=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_ELO=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_FT260=m
+CONFIG_HID_GEMBIRD=m
+CONFIG_HID_GFRM=m
+CONFIG_HID_GLORIOUS=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HOLTEK_FF=y
+CONFIG_HID_GOOGLE_HAMMER=m
+CONFIG_HID_VIVALDI=m
+CONFIG_HID_GT683R=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_UCLOGIC=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_VIEWSONIC=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_ICADE=m
+CONFIG_HID_ITE=m
+CONFIG_HID_JABRA=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LED=m
+CONFIG_HID_LENOVO=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_LOGITECH_DJ=m
+CONFIG_HID_LOGITECH_HIDPP=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_LOGIWHEELS_FF=y
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MALTRON=m
+CONFIG_HID_MAYFLASH=m
+CONFIG_HID_REDRAGON=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_NTI=m
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PENMOUNT=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_PICOLCD_CIR=y
+CONFIG_HID_PLANTRONICS=m
+CONFIG_HID_PLAYSTATION=m
+CONFIG_PLAYSTATION_FF=y
+CONFIG_HID_PRIMAX=m
+CONFIG_HID_RETRODE=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAITEK=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SEMITEK=m
+CONFIG_HID_SONY=m
+CONFIG_SONY_FF=y
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_STEAM=m
+CONFIG_HID_STEELSERIES=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_RMI=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_HYPERV_MOUSE=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THINGM=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_UDRAW_PS3=m
+CONFIG_HID_U2FZERO=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_XINMO=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_SENSOR_HUB=m
+CONFIG_HID_SENSOR_CUSTOM_SENSOR=m
+CONFIG_HID_ALPS=m
+CONFIG_HID_MCP2221=m
+# end of Special HID drivers
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+# end of USB HID support
+
+#
+# I2C HID support
+#
+CONFIG_I2C_HID_ACPI=m
+# end of I2C HID support
+
+CONFIG_I2C_HID_CORE=m
+
+#
+# Intel ISH HID support
+#
+CONFIG_INTEL_ISH_HID=m
+CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER=m
+# end of Intel ISH HID support
+
+#
+# AMD SFH HID Support
+#
+CONFIG_AMD_SFH_HID=m
+# end of AMD SFH HID Support
+
+#
+# Surface System Aggregator Module HID support
+#
+CONFIG_SURFACE_HID=m
+CONFIG_SURFACE_KBD=m
+# end of Surface System Aggregator Module HID support
+
+CONFIG_SURFACE_HID_CORE=m
+# end of HID support
+
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_LED_TRIG=y
+CONFIG_USB_ULPI_BUS=m
+CONFIG_USB_CONN_GPIO=m
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_PCI=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_FEW_INIT_RETRIES is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_PRODUCTLIST is not set
+CONFIG_USB_LEDS_TRIGGER_USBPORT=m
+CONFIG_USB_AUTOSUSPEND_DELAY=2
+CONFIG_USB_MON=m
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_XHCI_HCD=y
+# CONFIG_USB_XHCI_DBGCAP is not set
+CONFIG_USB_XHCI_PCI=m
+CONFIG_USB_XHCI_PCI_RENESAS=m
+CONFIG_USB_XHCI_PLATFORM=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=y
+CONFIG_USB_EHCI_FSL=m
+CONFIG_USB_EHCI_HCD_PLATFORM=m
+CONFIG_USB_OXU210HP_HCD=m
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_FOTG210_HCD=m
+CONFIG_USB_MAX3421_HCD=m
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_HCD_PLATFORM=m
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_HCD_ISO is not set
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_HCD_BCMA=m
+CONFIG_USB_HCD_SSB=m
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_REALTEK_AUTOPM=y
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_UAS=m
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USBIP_CORE=m
+CONFIG_USBIP_VHCI_HCD=m
+CONFIG_USBIP_VHCI_HC_PORTS=8
+CONFIG_USBIP_VHCI_NR_HCS=1
+CONFIG_USBIP_HOST=m
+CONFIG_USBIP_VUDC=m
+# CONFIG_USBIP_DEBUG is not set
+CONFIG_USB_CDNS_SUPPORT=m
+CONFIG_USB_CDNS_HOST=y
+CONFIG_USB_CDNS3=m
+CONFIG_USB_CDNS3_GADGET=y
+CONFIG_USB_CDNS3_HOST=y
+CONFIG_USB_CDNS3_PCI_WRAP=m
+CONFIG_USB_CDNSP_PCI=m
+CONFIG_USB_CDNSP_GADGET=y
+CONFIG_USB_CDNSP_HOST=y
+CONFIG_USB_MUSB_HDRC=m
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_GADGET is not set
+CONFIG_USB_MUSB_DUAL_ROLE=y
+
+#
+# Platform Glue Layer
+#
+
+#
+# MUSB DMA mode
+#
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_DWC3=m
+CONFIG_USB_DWC3_ULPI=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_PCI=m
+CONFIG_USB_DWC3_HAPS=m
+CONFIG_USB_DWC2=m
+# CONFIG_USB_DWC2_HOST is not set
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_PERIPHERAL is not set
+CONFIG_USB_DWC2_DUAL_ROLE=y
+CONFIG_USB_DWC2_PCI=m
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+CONFIG_USB_CHIPIDEA=m
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_CHIPIDEA_PCI=m
+CONFIG_USB_CHIPIDEA_MSM=m
+CONFIG_USB_CHIPIDEA_GENERIC=m
+CONFIG_USB_ISP1760=m
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_ISP1761_UDC=y
+# CONFIG_USB_ISP1760_HOST_ROLE is not set
+# CONFIG_USB_ISP1760_GADGET_ROLE is not set
+CONFIG_USB_ISP1760_DUAL_ROLE=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_F8153X=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7715_PARPORT=y
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MXUPORT=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_USB_SERIAL_UPD78F0730=m
+CONFIG_USB_SERIAL_XR=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_APPLE_MFI_FASTCHARGE=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_EHSET_TEST_FIXTURE=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_USB_EZUSB_FX2=m
+CONFIG_USB_HUB_USB251XB=m
+CONFIG_USB_HSIC_USB3503=m
+CONFIG_USB_HSIC_USB4604=m
+CONFIG_USB_LINK_LAYER_TEST=m
+CONFIG_USB_CHAOSKEY=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+
+#
+# USB Physical Layer drivers
+#
+CONFIG_USB_PHY=y
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_USB_GPIO_VBUS=m
+CONFIG_TAHVO_USB=m
+# CONFIG_TAHVO_USB_HOST_BY_DEFAULT is not set
+CONFIG_USB_ISP1301=m
+# end of USB Physical Layer drivers
+
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+CONFIG_U_SERIAL_CONSOLE=y
+
+#
+# USB Peripheral Controller
+#
+CONFIG_USB_FOTG210_UDC=m
+CONFIG_USB_GR_UDC=m
+CONFIG_USB_R8A66597=m
+CONFIG_USB_PXA27X=m
+CONFIG_USB_MV_UDC=m
+CONFIG_USB_MV_U3D=m
+CONFIG_USB_SNP_CORE=m
+CONFIG_USB_M66592=m
+CONFIG_USB_BDC_UDC=m
+CONFIG_USB_AMD5536UDC=m
+CONFIG_USB_NET2272=m
+# CONFIG_USB_NET2272_DMA is not set
+CONFIG_USB_NET2280=m
+CONFIG_USB_GOKU=m
+CONFIG_USB_EG20T=m
+CONFIG_USB_MAX3420_UDC=m
+CONFIG_USB_DUMMY_HCD=m
+# end of USB Peripheral Controller
+
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_F_SS_LB=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_U_AUDIO=m
+CONFIG_USB_F_SERIAL=m
+CONFIG_USB_F_OBEX=m
+CONFIG_USB_F_NCM=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_PHONET=m
+CONFIG_USB_F_EEM=m
+CONFIG_USB_F_SUBSET=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_F_FS=m
+CONFIG_USB_F_UAC1=m
+CONFIG_USB_F_UAC1_LEGACY=m
+CONFIG_USB_F_UAC2=m
+CONFIG_USB_F_UVC=m
+CONFIG_USB_F_MIDI=m
+CONFIG_USB_F_HID=m
+CONFIG_USB_F_PRINTER=m
+CONFIG_USB_F_TCM=m
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_PHONET=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_CONFIGFS_F_TCM=y
+
+#
+# USB Gadget precomposed configurations
+#
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+# CONFIG_GADGET_UAC1 is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_GADGET_TARGET=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_NOKIA=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_RNDIS=y
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+# CONFIG_USB_G_DBGP_PRINTK is not set
+CONFIG_USB_G_DBGP_SERIAL=y
+CONFIG_USB_G_WEBCAM=m
+CONFIG_USB_RAW_GADGET=m
+# end of USB Gadget precomposed configurations
+
+CONFIG_TYPEC=m
+CONFIG_TYPEC_TCPM=m
+CONFIG_TYPEC_TCPCI=m
+CONFIG_TYPEC_RT1711H=m
+CONFIG_TYPEC_MT6360=m
+CONFIG_TYPEC_TCPCI_MAXIM=m
+CONFIG_TYPEC_FUSB302=m
+CONFIG_TYPEC_WCOVE=m
+CONFIG_TYPEC_UCSI=m
+CONFIG_UCSI_CCG=m
+CONFIG_UCSI_ACPI=m
+CONFIG_TYPEC_TPS6598X=m
+CONFIG_TYPEC_HD3SS3220=m
+CONFIG_TYPEC_STUSB160X=m
+
+#
+# USB Type-C Multiplexer/DeMultiplexer Switch support
+#
+CONFIG_TYPEC_MUX_PI3USB30532=m
+CONFIG_TYPEC_MUX_INTEL_PMC=m
+# end of USB Type-C Multiplexer/DeMultiplexer Switch support
+
+#
+# USB Type-C Alternate Mode drivers
+#
+CONFIG_TYPEC_DP_ALTMODE=m
+CONFIG_TYPEC_NVIDIA_ALTMODE=m
+# end of USB Type-C Alternate Mode drivers
+
+CONFIG_USB_ROLE_SWITCH=m
+CONFIG_USB_ROLES_INTEL_XHCI=m
+CONFIG_MMC=m
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_SDIO_UART=m
+CONFIG_MMC_TEST=m
+CONFIG_MMC_CRYPTO=y
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_SDHCI=m
+CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+CONFIG_MMC_SDHCI_PCI=m
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_ACPI=m
+CONFIG_MMC_SDHCI_PLTFM=m
+CONFIG_MMC_SDHCI_F_SDH30=m
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_ALCOR=m
+CONFIG_MMC_TIFM_SD=m
+CONFIG_MMC_SPI=m
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=m
+CONFIG_MMC_VUB300=m
+CONFIG_MMC_USHC=m
+CONFIG_MMC_USDHI6ROL0=m
+CONFIG_MMC_REALTEK_PCI=m
+CONFIG_MMC_REALTEK_USB=m
+CONFIG_MMC_CQHCI=m
+CONFIG_MMC_HSQ=m
+CONFIG_MMC_TOSHIBA_PCI=m
+CONFIG_MMC_MTK=m
+CONFIG_MMC_SDHCI_XENON=m
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+CONFIG_MS_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_MEMSTICK_R592=m
+CONFIG_MEMSTICK_REALTEK_PCI=m
+CONFIG_MEMSTICK_REALTEK_USB=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_CLASS_FLASH=m
+CONFIG_LEDS_CLASS_MULTICOLOR=m
+CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_88PM860X=m
+CONFIG_LEDS_APU=m
+CONFIG_LEDS_LM3530=m
+CONFIG_LEDS_LM3532=m
+CONFIG_LEDS_LM3533=m
+CONFIG_LEDS_LM3642=m
+CONFIG_LEDS_MT6323=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_PCA9532_GPIO=y
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_LP3952=m
+CONFIG_LEDS_LP50XX=m
+CONFIG_LEDS_LP8788=m
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_PCA955X_GPIO=y
+CONFIG_LEDS_PCA963X=m
+CONFIG_LEDS_WM831X_STATUS=m
+CONFIG_LEDS_WM8350=m
+CONFIG_LEDS_DA903X=m
+CONFIG_LEDS_DA9052=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_PWM=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_INTEL_SS4200=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_ADP5520=m
+CONFIG_LEDS_MC13783=m
+CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_TLC591XX=m
+CONFIG_LEDS_MAX8997=m
+CONFIG_LEDS_LM355x=m
+CONFIG_LEDS_MENF21BMC=m
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+CONFIG_LEDS_BLINKM=m
+CONFIG_LEDS_MLXCPLD=m
+CONFIG_LEDS_MLXREG=m
+CONFIG_LEDS_USER=m
+CONFIG_LEDS_NIC78BX=m
+CONFIG_LEDS_TI_LMU_COMMON=m
+CONFIG_LEDS_LM36274=m
+CONFIG_LEDS_TPS6105X=m
+
+#
+# Flash and Torch LED drivers
+#
+CONFIG_LEDS_AS3645A=m
+CONFIG_LEDS_LM3601X=m
+CONFIG_LEDS_RT8515=m
+CONFIG_LEDS_SGM3140=m
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_ONESHOT=m
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LEDS_TRIGGER_MTD=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_ACTIVITY=m
+CONFIG_LEDS_TRIGGER_GPIO=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_LEDS_TRIGGER_CAMERA=m
+CONFIG_LEDS_TRIGGER_PANIC=y
+CONFIG_LEDS_TRIGGER_NETDEV=m
+CONFIG_LEDS_TRIGGER_PATTERN=m
+CONFIG_LEDS_TRIGGER_AUDIO=m
+CONFIG_LEDS_TRIGGER_TTY=m
+CONFIG_ACCESSIBILITY=y
+CONFIG_A11Y_BRAILLE_CONSOLE=y
+
+#
+# Speakup console speech
+#
+CONFIG_SPEAKUP=m
+CONFIG_SPEAKUP_SYNTH_ACNTSA=m
+CONFIG_SPEAKUP_SYNTH_APOLLO=m
+CONFIG_SPEAKUP_SYNTH_AUDPTR=m
+CONFIG_SPEAKUP_SYNTH_BNS=m
+CONFIG_SPEAKUP_SYNTH_DECTLK=m
+CONFIG_SPEAKUP_SYNTH_DECEXT=m
+CONFIG_SPEAKUP_SYNTH_LTLK=m
+CONFIG_SPEAKUP_SYNTH_SOFT=m
+CONFIG_SPEAKUP_SYNTH_SPKOUT=m
+CONFIG_SPEAKUP_SYNTH_TXPRT=m
+CONFIG_SPEAKUP_SYNTH_DUMMY=m
+# end of Speakup console speech
+
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y
+CONFIG_INFINIBAND_VIRT_DMA=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_QIB=m
+CONFIG_INFINIBAND_QIB_DCA=y
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_INFINIBAND_EFA=m
+CONFIG_INFINIBAND_IRDMA=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_MLX5_INFINIBAND=m
+CONFIG_INFINIBAND_OCRDMA=m
+CONFIG_INFINIBAND_VMWARE_PVRDMA=m
+CONFIG_INFINIBAND_USNIC=m
+CONFIG_INFINIBAND_BNXT_RE=m
+CONFIG_INFINIBAND_HFI1=m
+# CONFIG_HFI1_DEBUG_SDMA_ORDER is not set
+# CONFIG_SDMA_VERBOSITY is not set
+CONFIG_INFINIBAND_QEDR=m
+CONFIG_INFINIBAND_RDMAVT=m
+CONFIG_RDMA_RXE=m
+CONFIG_RDMA_SIW=m
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_CM=y
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_SRPT=m
+CONFIG_INFINIBAND_ISER=m
+CONFIG_INFINIBAND_ISERT=m
+CONFIG_INFINIBAND_RTRS=m
+CONFIG_INFINIBAND_RTRS_CLIENT=m
+CONFIG_INFINIBAND_RTRS_SERVER=m
+CONFIG_INFINIBAND_OPA_VNIC=m
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EDAC=y
+CONFIG_EDAC_LEGACY_SYSFS=y
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_DECODE_MCE=m
+CONFIG_EDAC_GHES=y
+CONFIG_EDAC_AMD64=m
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_I82975X=m
+CONFIG_EDAC_I3000=m
+CONFIG_EDAC_I3200=m
+CONFIG_EDAC_IE31200=m
+CONFIG_EDAC_X38=m
+CONFIG_EDAC_I5400=m
+CONFIG_EDAC_I7CORE=m
+CONFIG_EDAC_I5000=m
+CONFIG_EDAC_I5100=m
+CONFIG_EDAC_I7300=m
+CONFIG_EDAC_SBRIDGE=m
+CONFIG_EDAC_SKX=m
+CONFIG_EDAC_I10NM=m
+CONFIG_EDAC_PND2=m
+CONFIG_EDAC_IGEN6=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_MC146818_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+CONFIG_RTC_NVMEM=y
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_88PM860X=m
+CONFIG_RTC_DRV_88PM80X=m
+CONFIG_RTC_DRV_ABB5ZES3=m
+CONFIG_RTC_DRV_ABEOZ9=m
+CONFIG_RTC_DRV_ABX80X=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1307_CENTURY=y
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1374_WDT=y
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_LP8788=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_MAX8907=m
+CONFIG_RTC_DRV_MAX8925=m
+CONFIG_RTC_DRV_MAX8998=m
+CONFIG_RTC_DRV_MAX8997=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_ISL12022=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8523=m
+CONFIG_RTC_DRV_PCF85063=m
+CONFIG_RTC_DRV_PCF85363=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_PALMAS=m
+CONFIG_RTC_DRV_TPS6586X=m
+CONFIG_RTC_DRV_TPS65910=m
+CONFIG_RTC_DRV_TPS80031=m
+CONFIG_RTC_DRV_RC5T583=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8010=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+CONFIG_RTC_DRV_EM3027=m
+CONFIG_RTC_DRV_RV3028=m
+CONFIG_RTC_DRV_RV3032=m
+CONFIG_RTC_DRV_RV8803=m
+CONFIG_RTC_DRV_SD3078=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T93=m
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1302=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1343=m
+CONFIG_RTC_DRV_DS1347=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6916=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RX4581=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_PCF2123=m
+CONFIG_RTC_DRV_MCP795=m
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS3232=m
+CONFIG_RTC_DRV_DS3232_HWMON=y
+CONFIG_RTC_DRV_PCF2127=m
+CONFIG_RTC_DRV_RV3029C2=m
+CONFIG_RTC_DRV_RV3029_HWMON=y
+CONFIG_RTC_DRV_RX6110=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1685_FAMILY=m
+CONFIG_RTC_DRV_DS1685=y
+# CONFIG_RTC_DRV_DS1689 is not set
+# CONFIG_RTC_DRV_DS17285 is not set
+# CONFIG_RTC_DRV_DS17485 is not set
+# CONFIG_RTC_DRV_DS17885 is not set
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_DS2404=m
+CONFIG_RTC_DRV_DA9052=m
+CONFIG_RTC_DRV_DA9055=m
+CONFIG_RTC_DRV_DA9063=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_WM831X=m
+CONFIG_RTC_DRV_WM8350=m
+CONFIG_RTC_DRV_PCF50633=m
+CONFIG_RTC_DRV_CROS_EC=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FTRTC010=m
+CONFIG_RTC_DRV_PCAP=m
+CONFIG_RTC_DRV_MC13XXX=m
+CONFIG_RTC_DRV_MT6397=m
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_RTC_DRV_HID_SENSOR_TIME=m
+CONFIG_RTC_DRV_GOLDFISH=m
+CONFIG_RTC_DRV_WILCO_EC=m
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_ACPI=y
+CONFIG_ALTERA_MSGDMA=m
+CONFIG_INTEL_IDMA64=m
+CONFIG_INTEL_IDXD_BUS=m
+CONFIG_INTEL_IDXD=m
+# CONFIG_INTEL_IDXD_COMPAT is not set
+CONFIG_INTEL_IDXD_SVM=y
+CONFIG_INTEL_IDXD_PERFMON=y
+CONFIG_INTEL_IOATDMA=m
+CONFIG_PLX_DMA=m
+CONFIG_AMD_PTDMA=m
+CONFIG_QCOM_HIDMA_MGMT=m
+CONFIG_QCOM_HIDMA=m
+CONFIG_DW_DMAC_CORE=y
+CONFIG_DW_DMAC=m
+CONFIG_DW_DMAC_PCI=y
+CONFIG_DW_EDMA=m
+CONFIG_DW_EDMA_PCIE=m
+CONFIG_HSU_DMA=y
+CONFIG_SF_PDMA=m
+CONFIG_INTEL_LDMA=y
+
+#
+# DMA Clients
+#
+CONFIG_ASYNC_TX_DMA=y
+# CONFIG_DMATEST is not set
+CONFIG_DMA_ENGINE_RAID=y
+
+#
+# DMABUF options
+#
+CONFIG_SYNC_FILE=y
+# CONFIG_SW_SYNC is not set
+CONFIG_UDMABUF=y
+# CONFIG_DMABUF_MOVE_NOTIFY is not set
+# CONFIG_DMABUF_DEBUG is not set
+# CONFIG_DMABUF_SELFTESTS is not set
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_SYSFS_STATS=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
+CONFIG_DMABUF_HEAPS_CMA=y
+# end of DMABUF options
+
+CONFIG_DCA=m
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_PANEL is not set
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_DMEM_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+CONFIG_UIO_PCI_GENERIC=m
+CONFIG_UIO_NETX=m
+CONFIG_UIO_PRUSS=m
+CONFIG_UIO_MF624=m
+CONFIG_UIO_HV_GENERIC=m
+CONFIG_UIO_DFL=m
+CONFIG_VFIO=m
+CONFIG_VFIO_IOMMU_TYPE1=m
+CONFIG_VFIO_VIRQFD=m
+# CONFIG_VFIO_NOIOMMU is not set
+CONFIG_VFIO_PCI_CORE=m
+CONFIG_VFIO_PCI_MMAP=y
+CONFIG_VFIO_PCI_INTX=y
+CONFIG_VFIO_PCI=m
+CONFIG_VFIO_PCI_VGA=y
+CONFIG_VFIO_PCI_IGD=y
+CONFIG_VFIO_MDEV=m
+CONFIG_IRQ_BYPASS_MANAGER=m
+CONFIG_VIRT_DRIVERS=y
+CONFIG_VBOXGUEST=m
+CONFIG_NITRO_ENCLAVES=m
+CONFIG_ACRN_HSM=m
+CONFIG_VIRTIO=y
+CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS=y
+CONFIG_VIRTIO_PCI_LIB=m
+CONFIG_VIRTIO_MENU=y
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_PCI_LEGACY=y
+CONFIG_VIRTIO_VDPA=m
+CONFIG_VIRTIO_PMEM=m
+CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_MEM=m
+CONFIG_VIRTIO_INPUT=m
+CONFIG_VIRTIO_MMIO=m
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+CONFIG_VIRTIO_DMA_SHARED_BUFFER=m
+CONFIG_VDPA=m
+CONFIG_VDPA_SIM=m
+CONFIG_VDPA_SIM_NET=m
+CONFIG_VDPA_SIM_BLOCK=m
+CONFIG_VDPA_USER=m
+CONFIG_IFCVF=m
+CONFIG_MLX5_VDPA=y
+CONFIG_MLX5_VDPA_NET=m
+CONFIG_VP_VDPA=m
+CONFIG_VHOST_IOTLB=m
+CONFIG_VHOST_RING=m
+CONFIG_VHOST=m
+CONFIG_VHOST_MENU=y
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_SCSI=m
+CONFIG_VHOST_VSOCK=m
+CONFIG_VHOST_VDPA=m
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+CONFIG_HYPERV=m
+CONFIG_HYPERV_TIMER=y
+CONFIG_HYPERV_UTILS=m
+CONFIG_HYPERV_BALLOON=m
+# end of Microsoft Hyper-V guest support
+
+#
+# Xen driver support
+#
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y
+CONFIG_XEN_MEMORY_HOTPLUG_LIMIT=512
+CONFIG_XEN_SCRUB_PAGES_DEFAULT=y
+CONFIG_XEN_DEV_EVTCHN=m
+CONFIG_XEN_BACKEND=y
+CONFIG_XENFS=m
+CONFIG_XEN_COMPAT_XENFS=y
+CONFIG_XEN_SYS_HYPERVISOR=y
+CONFIG_XEN_XENBUS_FRONTEND=y
+CONFIG_XEN_GNTDEV=m
+CONFIG_XEN_GNTDEV_DMABUF=y
+CONFIG_XEN_GRANT_DEV_ALLOC=m
+CONFIG_XEN_GRANT_DMA_ALLOC=y
+CONFIG_SWIOTLB_XEN=y
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PVCALLS_FRONTEND=m
+CONFIG_XEN_PVCALLS_BACKEND=y
+CONFIG_XEN_SCSI_BACKEND=m
+CONFIG_XEN_PRIVCMD=m
+CONFIG_XEN_ACPI_PROCESSOR=m
+CONFIG_XEN_MCE_LOG=y
+CONFIG_XEN_HAVE_PVMMU=y
+CONFIG_XEN_EFI=y
+CONFIG_XEN_AUTO_XLATE=y
+CONFIG_XEN_ACPI=y
+CONFIG_XEN_SYMS=y
+CONFIG_XEN_HAVE_VPMU=y
+CONFIG_XEN_FRONT_PGDIR_SHBUF=m
+CONFIG_XEN_UNPOPULATED_ALLOC=y
+# end of Xen driver support
+
+# CONFIG_GREYBUS is not set
+# CONFIG_COMEDI is not set
+CONFIG_STAGING=y
+CONFIG_PRISM2_USB=m
+CONFIG_RTL8192U=m
+CONFIG_RTLLIB=m
+CONFIG_RTLLIB_CRYPTO_CCMP=m
+CONFIG_RTLLIB_CRYPTO_TKIP=m
+CONFIG_RTLLIB_CRYPTO_WEP=m
+CONFIG_RTL8192E=m
+CONFIG_RTL8723BS=m
+CONFIG_R8712U=m
+CONFIG_R8188EU=m
+CONFIG_88EU_AP_MODE=y
+CONFIG_RTS5208=m
+CONFIG_VT6655=m
+CONFIG_VT6656=m
+
+#
+# IIO staging drivers
+#
+
+#
+# Accelerometers
+#
+CONFIG_ADIS16203=m
+CONFIG_ADIS16240=m
+# end of Accelerometers
+
+#
+# Analog to digital converters
+#
+CONFIG_AD7816=m
+CONFIG_AD7280=m
+# end of Analog to digital converters
+
+#
+# Analog digital bi-direction converters
+#
+CONFIG_ADT7316=m
+CONFIG_ADT7316_SPI=m
+CONFIG_ADT7316_I2C=m
+# end of Analog digital bi-direction converters
+
+#
+# Capacitance to digital converters
+#
+CONFIG_AD7746=m
+# end of Capacitance to digital converters
+
+#
+# Direct Digital Synthesis
+#
+CONFIG_AD9832=m
+CONFIG_AD9834=m
+# end of Direct Digital Synthesis
+
+#
+# Network Analyzer, Impedance Converters
+#
+CONFIG_AD5933=m
+# end of Network Analyzer, Impedance Converters
+
+#
+# Active energy metering IC
+#
+CONFIG_ADE7854=m
+CONFIG_ADE7854_I2C=m
+CONFIG_ADE7854_SPI=m
+# end of Active energy metering IC
+
+#
+# Resolver to digital converters
+#
+CONFIG_AD2S1210=m
+# end of Resolver to digital converters
+# end of IIO staging drivers
+
+# CONFIG_FB_SM750 is not set
+CONFIG_STAGING_MEDIA=y
+CONFIG_INTEL_ATOMISP=y
+CONFIG_VIDEO_ATOMISP=m
+CONFIG_VIDEO_ATOMISP_ISP2401=y
+CONFIG_VIDEO_ATOMISP_OV2722=m
+CONFIG_VIDEO_ATOMISP_GC2235=m
+CONFIG_VIDEO_ATOMISP_MSRLIST_HELPER=m
+CONFIG_VIDEO_ATOMISP_MT9M114=m
+CONFIG_VIDEO_ATOMISP_GC0310=m
+CONFIG_VIDEO_ATOMISP_OV2680=m
+CONFIG_VIDEO_ATOMISP_OV5693=m
+CONFIG_VIDEO_ATOMISP_LM3554=m
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIDEO_IPU3_IMGU=m
+CONFIG_DVB_AV7110_IR=y
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_PATCH=m
+CONFIG_DVB_SP8870=m
+
+#
+# Android
+#
+CONFIG_ASHMEM=y
+# end of Android
+
+CONFIG_LTE_GDM724X=m
+CONFIG_FIREWIRE_SERIAL=m
+CONFIG_FWTTY_MAX_TOTAL_PORTS=64
+CONFIG_FWTTY_MAX_CARD_PORTS=32
+CONFIG_GS_FPGABOOT=m
+CONFIG_UNISYSSPAR=y
+CONFIG_UNISYS_VISORNIC=m
+CONFIG_UNISYS_VISORINPUT=m
+CONFIG_UNISYS_VISORHBA=m
+# CONFIG_FB_TFT is not set
+CONFIG_MOST_COMPONENTS=m
+CONFIG_MOST_NET=m
+CONFIG_MOST_VIDEO=m
+CONFIG_MOST_I2C=m
+CONFIG_KS7010=m
+CONFIG_PI433=m
+CONFIG_FIELDBUS_DEV=m
+CONFIG_QLGE=m
+CONFIG_WFX=m
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_ACPI_WMI=m
+CONFIG_WMI_BMOF=m
+CONFIG_HUAWEI_WMI=m
+CONFIG_MXM_WMI=m
+CONFIG_PEAQ_WMI=m
+CONFIG_XIAOMI_WMI=m
+CONFIG_GIGABYTE_WMI=m
+CONFIG_ACERHDF=m
+CONFIG_ACER_WIRELESS=m
+CONFIG_ACER_WMI=m
+CONFIG_AMD_PMC=m
+CONFIG_ADV_SWBUTTON=m
+CONFIG_APPLE_GMUX=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_ASUS_WIRELESS=m
+CONFIG_ASUS_WMI=m
+CONFIG_ASUS_NB_WMI=m
+CONFIG_MERAKI_MX100=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_EEEPC_WMI=m
+CONFIG_X86_PLATFORM_DRIVERS_DELL=y
+CONFIG_ALIENWARE_WMI=m
+CONFIG_DCDBAS=m
+CONFIG_DELL_LAPTOP=m
+# CONFIG_DELL_RBU is not set
+CONFIG_DELL_RBTN=m
+CONFIG_DELL_SMBIOS=m
+CONFIG_DELL_SMBIOS_WMI=y
+CONFIG_DELL_SMBIOS_SMM=y
+CONFIG_DELL_SMO8800=m
+CONFIG_DELL_WMI=m
+CONFIG_DELL_WMI_PRIVACY=y
+CONFIG_DELL_WMI_AIO=m
+CONFIG_DELL_WMI_DESCRIPTOR=m
+CONFIG_DELL_WMI_LED=m
+CONFIG_DELL_WMI_SYSMAN=m
+CONFIG_AMILO_RFKILL=m
+CONFIG_FUJITSU_LAPTOP=m
+CONFIG_FUJITSU_TABLET=m
+CONFIG_GPD_POCKET_FAN=m
+CONFIG_HP_ACCEL=m
+CONFIG_WIRELESS_HOTKEY=m
+CONFIG_HP_WMI=m
+CONFIG_IBM_RTL=m
+CONFIG_IDEAPAD_LAPTOP=m
+CONFIG_SENSORS_HDAPS=m
+CONFIG_THINKPAD_ACPI=m
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y
+# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_THINKPAD_LMI=m
+CONFIG_X86_PLATFORM_DRIVERS_INTEL=y
+CONFIG_INTEL_ATOMISP2_PDX86=y
+CONFIG_INTEL_ATOMISP2_LED=m
+CONFIG_INTEL_SAR_INT1092=m
+CONFIG_INTEL_CHT_INT33FE=m
+CONFIG_INTEL_SKL_INT3472=m
+CONFIG_INTEL_PMC_CORE=y
+CONFIG_INTEL_PMT_CLASS=m
+CONFIG_INTEL_PMT_TELEMETRY=m
+CONFIG_INTEL_PMT_CRASHLOG=m
+
+#
+# Intel Speed Select Technology interface support
+#
+CONFIG_INTEL_SPEED_SELECT_INTERFACE=m
+# end of Intel Speed Select Technology interface support
+
+CONFIG_INTEL_TELEMETRY=m
+CONFIG_INTEL_WMI=y
+CONFIG_INTEL_WMI_SBL_FW_UPDATE=m
+CONFIG_INTEL_WMI_THUNDERBOLT=m
+CONFIG_INTEL_HID_EVENT=m
+CONFIG_INTEL_VBTN=m
+CONFIG_INTEL_INT0002_VGPIO=m
+CONFIG_INTEL_OAKTRAIL=m
+CONFIG_INTEL_BXTWC_PMIC_TMU=m
+CONFIG_INTEL_CHTDC_TI_PWRBTN=m
+CONFIG_INTEL_MRFLD_PWRBTN=m
+CONFIG_INTEL_PUNIT_IPC=m
+CONFIG_INTEL_RST=m
+CONFIG_INTEL_SMARTCONNECT=m
+CONFIG_INTEL_TURBO_MAX_3=y
+CONFIG_INTEL_UNCORE_FREQ_CONTROL=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_MSI_WMI=m
+CONFIG_PCENGINES_APU2=m
+CONFIG_SAMSUNG_LAPTOP=m
+CONFIG_SAMSUNG_Q10=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_TOSHIBA_BT_RFKILL=m
+CONFIG_TOSHIBA_HAPS=m
+CONFIG_TOSHIBA_WMI=m
+CONFIG_ACPI_CMPC=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_LG_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+CONFIG_SONYPI_COMPAT=y
+CONFIG_SYSTEM76_ACPI=m
+CONFIG_TOPSTAR_LAPTOP=m
+CONFIG_I2C_MULTI_INSTANTIATE=m
+CONFIG_MLX_PLATFORM=m
+CONFIG_TOUCHSCREEN_DMI=y
+CONFIG_FW_ATTR_CLASS=m
+CONFIG_INTEL_IPS=m
+CONFIG_INTEL_SCU_IPC=y
+CONFIG_INTEL_SCU=y
+CONFIG_INTEL_SCU_PCI=y
+CONFIG_INTEL_SCU_PLATFORM=m
+CONFIG_INTEL_SCU_IPC_UTIL=m
+CONFIG_PMC_ATOM=y
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CHROMEOS_LAPTOP=m
+CONFIG_CHROMEOS_PSTORE=m
+CONFIG_CHROMEOS_TBMC=m
+CONFIG_CROS_EC=m
+CONFIG_CROS_EC_I2C=m
+CONFIG_CROS_EC_ISHTP=m
+CONFIG_CROS_EC_SPI=m
+CONFIG_CROS_EC_LPC=m
+CONFIG_CROS_EC_PROTO=y
+CONFIG_CROS_KBD_LED_BACKLIGHT=m
+CONFIG_CROS_EC_CHARDEV=m
+CONFIG_CROS_EC_LIGHTBAR=m
+CONFIG_CROS_EC_DEBUGFS=m
+CONFIG_CROS_EC_SENSORHUB=m
+CONFIG_CROS_EC_SYSFS=m
+CONFIG_CROS_EC_TYPEC=m
+CONFIG_CROS_USBPD_LOGGER=m
+CONFIG_CROS_USBPD_NOTIFY=m
+CONFIG_WILCO_EC=m
+CONFIG_WILCO_EC_DEBUGFS=m
+CONFIG_WILCO_EC_EVENTS=m
+CONFIG_WILCO_EC_TELEMETRY=m
+CONFIG_MELLANOX_PLATFORM=y
+CONFIG_MLXREG_HOTPLUG=m
+CONFIG_MLXREG_IO=m
+CONFIG_SURFACE_PLATFORMS=y
+CONFIG_SURFACE3_WMI=m
+CONFIG_SURFACE_3_BUTTON=m
+CONFIG_SURFACE_3_POWER_OPREGION=m
+CONFIG_SURFACE_ACPI_NOTIFY=m
+CONFIG_SURFACE_AGGREGATOR_CDEV=m
+CONFIG_SURFACE_AGGREGATOR_REGISTRY=m
+CONFIG_SURFACE_DTX=m
+CONFIG_SURFACE_GPE=m
+CONFIG_SURFACE_HOTPLUG=m
+CONFIG_SURFACE_PLATFORM_PROFILE=m
+CONFIG_SURFACE_PRO3_BUTTON=m
+CONFIG_SURFACE_AGGREGATOR=m
+CONFIG_SURFACE_AGGREGATOR_BUS=y
+# CONFIG_SURFACE_AGGREGATOR_ERROR_INJECTION is not set
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_WM831X=m
+
+#
+# Clock driver for ARM Reference designs
+#
+# CONFIG_ICST is not set
+# CONFIG_CLK_SP810 is not set
+# end of Clock driver for ARM Reference designs
+
+CONFIG_LMK04832=m
+CONFIG_COMMON_CLK_MAX9485=m
+CONFIG_COMMON_CLK_SI5341=m
+CONFIG_COMMON_CLK_SI5351=m
+CONFIG_COMMON_CLK_SI544=m
+CONFIG_COMMON_CLK_CDCE706=m
+CONFIG_COMMON_CLK_CS2000_CP=m
+CONFIG_CLK_TWL6040=m
+CONFIG_COMMON_CLK_PALMAS=m
+CONFIG_COMMON_CLK_PWM=m
+CONFIG_XILINX_VCU=m
+CONFIG_HWSPINLOCK=y
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+# end of Clock Source drivers
+
+CONFIG_MAILBOX=y
+CONFIG_PCC=y
+CONFIG_ALTERA_MBOX=m
+CONFIG_IOMMU_IOVA=y
+CONFIG_IOASID=y
+CONFIG_IOMMU_API=y
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Generic IOMMU Pagetable Support
+#
+CONFIG_IOMMU_IO_PGTABLE=y
+# end of Generic IOMMU Pagetable Support
+
+# CONFIG_IOMMU_DEBUGFS is not set
+# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
+CONFIG_IOMMU_DMA=y
+CONFIG_IOMMU_SVA_LIB=y
+CONFIG_AMD_IOMMU=y
+CONFIG_AMD_IOMMU_V2=y
+CONFIG_DMAR_TABLE=y
+CONFIG_INTEL_IOMMU=y
+CONFIG_INTEL_IOMMU_SVM=y
+# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU_FLOPPY_WA=y
+CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON=y
+CONFIG_IRQ_REMAP=y
+CONFIG_HYPERV_IOMMU=y
+CONFIG_VIRTIO_IOMMU=m
+
+#
+# Remoteproc drivers
+#
+CONFIG_REMOTEPROC=y
+CONFIG_REMOTEPROC_CDEV=y
+# end of Remoteproc drivers
+
+#
+# Rpmsg drivers
+#
+CONFIG_RPMSG=m
+CONFIG_RPMSG_CHAR=m
+CONFIG_RPMSG_NS=m
+CONFIG_RPMSG_QCOM_GLINK=m
+CONFIG_RPMSG_QCOM_GLINK_RPM=m
+CONFIG_RPMSG_VIRTIO=m
+# end of Rpmsg drivers
+
+CONFIG_SOUNDWIRE=m
+
+#
+# SoundWire Devices
+#
+CONFIG_SOUNDWIRE_CADENCE=m
+CONFIG_SOUNDWIRE_INTEL=m
+CONFIG_SOUNDWIRE_QCOM=m
+CONFIG_SOUNDWIRE_GENERIC_ALLOCATION=m
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Amlogic SoC drivers
+#
+# end of Amlogic SoC drivers
+
+#
+# Broadcom SoC drivers
+#
+# end of Broadcom SoC drivers
+
+#
+# NXP/Freescale QorIQ SoC drivers
+#
+# end of NXP/Freescale QorIQ SoC drivers
+
+#
+# i.MX SoC drivers
+#
+# end of i.MX SoC drivers
+
+#
+# Enable LiteX SoC Builder specific drivers
+#
+# end of Enable LiteX SoC Builder specific drivers
+
+#
+# Qualcomm SoC drivers
+#
+CONFIG_QCOM_QMI_HELPERS=m
+# end of Qualcomm SoC drivers
+
+CONFIG_SOC_TI=y
+
+#
+# Xilinx SoC drivers
+#
+# end of Xilinx SoC drivers
+# end of SOC (System On Chip) specific Drivers
+
+CONFIG_PM_DEVFREQ=y
+
+#
+# DEVFREQ Governors
+#
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=m
+CONFIG_DEVFREQ_GOV_PERFORMANCE=m
+CONFIG_DEVFREQ_GOV_POWERSAVE=m
+CONFIG_DEVFREQ_GOV_USERSPACE=m
+CONFIG_DEVFREQ_GOV_PASSIVE=m
+
+#
+# DEVFREQ Drivers
+#
+CONFIG_PM_DEVFREQ_EVENT=y
+CONFIG_EXTCON=y
+
+#
+# Extcon Device Drivers
+#
+CONFIG_EXTCON_ADC_JACK=m
+CONFIG_EXTCON_AXP288=m
+CONFIG_EXTCON_FSA9480=m
+CONFIG_EXTCON_GPIO=m
+CONFIG_EXTCON_INTEL_INT3496=m
+CONFIG_EXTCON_INTEL_CHT_WC=m
+CONFIG_EXTCON_INTEL_MRFLD=m
+CONFIG_EXTCON_MAX14577=m
+CONFIG_EXTCON_MAX3355=m
+CONFIG_EXTCON_MAX77693=m
+CONFIG_EXTCON_MAX77843=m
+CONFIG_EXTCON_MAX8997=m
+CONFIG_EXTCON_PALMAS=m
+CONFIG_EXTCON_PTN5150=m
+CONFIG_EXTCON_RT8973A=m
+CONFIG_EXTCON_SM5502=m
+CONFIG_EXTCON_USB_GPIO=m
+CONFIG_EXTCON_USBC_CROS_EC=m
+CONFIG_EXTCON_USBC_TUSB320=m
+CONFIG_MEMORY=y
+CONFIG_FPGA_DFL_EMIF=m
+CONFIG_IIO=m
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_CB=m
+CONFIG_IIO_BUFFER_DMA=m
+CONFIG_IIO_BUFFER_DMAENGINE=m
+CONFIG_IIO_BUFFER_HW_CONSUMER=m
+CONFIG_IIO_KFIFO_BUF=m
+CONFIG_IIO_TRIGGERED_BUFFER=m
+CONFIG_IIO_CONFIGFS=m
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+CONFIG_IIO_SW_DEVICE=m
+CONFIG_IIO_SW_TRIGGER=m
+CONFIG_IIO_TRIGGERED_EVENT=m
+
+#
+# Accelerometers
+#
+CONFIG_ADIS16201=m
+CONFIG_ADIS16209=m
+CONFIG_ADXL372=m
+CONFIG_ADXL372_SPI=m
+CONFIG_ADXL372_I2C=m
+CONFIG_BMA220=m
+CONFIG_BMA400=m
+CONFIG_BMA400_I2C=m
+CONFIG_BMA400_SPI=m
+CONFIG_BMC150_ACCEL=m
+CONFIG_BMC150_ACCEL_I2C=m
+CONFIG_BMC150_ACCEL_SPI=m
+CONFIG_BMI088_ACCEL=m
+CONFIG_BMI088_ACCEL_SPI=m
+CONFIG_DA280=m
+CONFIG_DA311=m
+CONFIG_DMARD09=m
+CONFIG_DMARD10=m
+CONFIG_FXLS8962AF=m
+CONFIG_FXLS8962AF_I2C=m
+CONFIG_FXLS8962AF_SPI=m
+CONFIG_HID_SENSOR_ACCEL_3D=m
+CONFIG_IIO_CROS_EC_ACCEL_LEGACY=m
+CONFIG_IIO_ST_ACCEL_3AXIS=m
+CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m
+CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m
+CONFIG_KXSD9=m
+CONFIG_KXSD9_SPI=m
+CONFIG_KXSD9_I2C=m
+CONFIG_KXCJK1013=m
+CONFIG_MC3230=m
+CONFIG_MMA7455=m
+CONFIG_MMA7455_I2C=m
+CONFIG_MMA7455_SPI=m
+CONFIG_MMA7660=m
+CONFIG_MMA8452=m
+CONFIG_MMA9551_CORE=m
+CONFIG_MMA9551=m
+CONFIG_MMA9553=m
+CONFIG_MXC4005=m
+CONFIG_MXC6255=m
+CONFIG_SCA3000=m
+CONFIG_SCA3300=m
+CONFIG_STK8312=m
+CONFIG_STK8BA50=m
+# end of Accelerometers
+
+#
+# Analog to digital converters
+#
+CONFIG_AD_SIGMA_DELTA=m
+CONFIG_AD7091R5=m
+CONFIG_AD7124=m
+CONFIG_AD7192=m
+CONFIG_AD7266=m
+CONFIG_AD7291=m
+CONFIG_AD7292=m
+CONFIG_AD7298=m
+CONFIG_AD7476=m
+CONFIG_AD7606=m
+CONFIG_AD7606_IFACE_PARALLEL=m
+CONFIG_AD7606_IFACE_SPI=m
+CONFIG_AD7766=m
+CONFIG_AD7768_1=m
+CONFIG_AD7780=m
+CONFIG_AD7791=m
+CONFIG_AD7793=m
+CONFIG_AD7887=m
+CONFIG_AD7923=m
+CONFIG_AD7949=m
+CONFIG_AD799X=m
+CONFIG_AXP20X_ADC=m
+CONFIG_AXP288_ADC=m
+CONFIG_CC10001_ADC=m
+CONFIG_DA9150_GPADC=m
+CONFIG_DLN2_ADC=m
+CONFIG_HI8435=m
+CONFIG_HX711=m
+CONFIG_INA2XX_ADC=m
+CONFIG_INTEL_MRFLD_ADC=m
+CONFIG_LP8788_ADC=m
+CONFIG_LTC2471=m
+CONFIG_LTC2485=m
+CONFIG_LTC2496=m
+CONFIG_LTC2497=m
+CONFIG_MAX1027=m
+CONFIG_MAX11100=m
+CONFIG_MAX1118=m
+CONFIG_MAX1241=m
+CONFIG_MAX1363=m
+CONFIG_MAX9611=m
+CONFIG_MCP320X=m
+CONFIG_MCP3422=m
+CONFIG_MCP3911=m
+CONFIG_MEDIATEK_MT6360_ADC=m
+CONFIG_MEN_Z188_ADC=m
+CONFIG_MP2629_ADC=m
+CONFIG_NAU7802=m
+CONFIG_PALMAS_GPADC=m
+CONFIG_TI_ADC081C=m
+CONFIG_TI_ADC0832=m
+CONFIG_TI_ADC084S021=m
+CONFIG_TI_ADC12138=m
+CONFIG_TI_ADC108S102=m
+CONFIG_TI_ADC128S052=m
+CONFIG_TI_ADC161S626=m
+CONFIG_TI_ADS1015=m
+CONFIG_TI_ADS7950=m
+CONFIG_TI_ADS131E08=m
+CONFIG_TI_AM335X_ADC=m
+CONFIG_TI_TLC4541=m
+CONFIG_TI_TSC2046=m
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL6030_GPADC=m
+CONFIG_VIPERBOARD_ADC=m
+CONFIG_XILINX_XADC=m
+# end of Analog to digital converters
+
+#
+# Analog Front Ends
+#
+# end of Analog Front Ends
+
+#
+# Amplifiers
+#
+CONFIG_AD8366=m
+CONFIG_HMC425=m
+# end of Amplifiers
+
+#
+# Capacitance to digital converters
+#
+CONFIG_AD7150=m
+# end of Capacitance to digital converters
+
+#
+# Chemical Sensors
+#
+CONFIG_ATLAS_PH_SENSOR=m
+CONFIG_ATLAS_EZO_SENSOR=m
+CONFIG_BME680=m
+CONFIG_BME680_I2C=m
+CONFIG_BME680_SPI=m
+CONFIG_CCS811=m
+CONFIG_IAQCORE=m
+CONFIG_PMS7003=m
+CONFIG_SCD30_CORE=m
+CONFIG_SCD30_I2C=m
+CONFIG_SCD30_SERIAL=m
+CONFIG_SENSIRION_SGP30=m
+CONFIG_SENSIRION_SGP40=m
+CONFIG_SPS30=m
+CONFIG_SPS30_I2C=m
+CONFIG_SPS30_SERIAL=m
+CONFIG_VZ89X=m
+# end of Chemical Sensors
+
+CONFIG_IIO_CROS_EC_SENSORS_CORE=m
+CONFIG_IIO_CROS_EC_SENSORS=m
+CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE=m
+
+#
+# Hid Sensor IIO Common
+#
+CONFIG_HID_SENSOR_IIO_COMMON=m
+CONFIG_HID_SENSOR_IIO_TRIGGER=m
+# end of Hid Sensor IIO Common
+
+CONFIG_IIO_MS_SENSORS_I2C=m
+
+#
+# IIO SCMI Sensors
+#
+# end of IIO SCMI Sensors
+
+#
+# SSP Sensor Common
+#
+CONFIG_IIO_SSP_SENSORS_COMMONS=m
+CONFIG_IIO_SSP_SENSORHUB=m
+# end of SSP Sensor Common
+
+CONFIG_IIO_ST_SENSORS_I2C=m
+CONFIG_IIO_ST_SENSORS_SPI=m
+CONFIG_IIO_ST_SENSORS_CORE=m
+
+#
+# Digital to analog converters
+#
+CONFIG_AD5064=m
+CONFIG_AD5360=m
+CONFIG_AD5380=m
+CONFIG_AD5421=m
+CONFIG_AD5446=m
+CONFIG_AD5449=m
+CONFIG_AD5592R_BASE=m
+CONFIG_AD5592R=m
+CONFIG_AD5593R=m
+CONFIG_AD5504=m
+CONFIG_AD5624R_SPI=m
+CONFIG_AD5686=m
+CONFIG_AD5686_SPI=m
+CONFIG_AD5696_I2C=m
+CONFIG_AD5755=m
+CONFIG_AD5758=m
+CONFIG_AD5761=m
+CONFIG_AD5764=m
+CONFIG_AD5766=m
+CONFIG_AD5770R=m
+CONFIG_AD5791=m
+CONFIG_AD7303=m
+CONFIG_AD8801=m
+CONFIG_DS4424=m
+CONFIG_LTC1660=m
+CONFIG_LTC2632=m
+CONFIG_M62332=m
+CONFIG_MAX517=m
+CONFIG_MCP4725=m
+CONFIG_MCP4922=m
+CONFIG_TI_DAC082S085=m
+CONFIG_TI_DAC5571=m
+CONFIG_TI_DAC7311=m
+CONFIG_TI_DAC7612=m
+# end of Digital to analog converters
+
+#
+# IIO dummy driver
+#
+# CONFIG_IIO_SIMPLE_DUMMY is not set
+# end of IIO dummy driver
+
+#
+# Frequency Synthesizers DDS/PLL
+#
+
+#
+# Clock Generator/Distribution
+#
+CONFIG_AD9523=m
+# end of Clock Generator/Distribution
+
+#
+# Phase-Locked Loop (PLL) frequency synthesizers
+#
+CONFIG_ADF4350=m
+CONFIG_ADF4371=m
+# end of Phase-Locked Loop (PLL) frequency synthesizers
+# end of Frequency Synthesizers DDS/PLL
+
+#
+# Digital gyroscope sensors
+#
+CONFIG_ADIS16080=m
+CONFIG_ADIS16130=m
+CONFIG_ADIS16136=m
+CONFIG_ADIS16260=m
+CONFIG_ADXRS290=m
+CONFIG_ADXRS450=m
+CONFIG_BMG160=m
+CONFIG_BMG160_I2C=m
+CONFIG_BMG160_SPI=m
+CONFIG_FXAS21002C=m
+CONFIG_FXAS21002C_I2C=m
+CONFIG_FXAS21002C_SPI=m
+CONFIG_HID_SENSOR_GYRO_3D=m
+CONFIG_MPU3050=m
+CONFIG_MPU3050_I2C=m
+CONFIG_IIO_ST_GYRO_3AXIS=m
+CONFIG_IIO_ST_GYRO_I2C_3AXIS=m
+CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
+CONFIG_ITG3200=m
+# end of Digital gyroscope sensors
+
+#
+# Health Sensors
+#
+
+#
+# Heart Rate Monitors
+#
+CONFIG_AFE4403=m
+CONFIG_AFE4404=m
+CONFIG_MAX30100=m
+CONFIG_MAX30102=m
+# end of Heart Rate Monitors
+# end of Health Sensors
+
+#
+# Humidity sensors
+#
+CONFIG_AM2315=m
+CONFIG_DHT11=m
+CONFIG_HDC100X=m
+CONFIG_HDC2010=m
+CONFIG_HID_SENSOR_HUMIDITY=m
+CONFIG_HTS221=m
+CONFIG_HTS221_I2C=m
+CONFIG_HTS221_SPI=m
+CONFIG_HTU21=m
+CONFIG_SI7005=m
+CONFIG_SI7020=m
+# end of Humidity sensors
+
+#
+# Inertial measurement units
+#
+CONFIG_ADIS16400=m
+CONFIG_ADIS16460=m
+CONFIG_ADIS16475=m
+CONFIG_ADIS16480=m
+CONFIG_BMI160=m
+CONFIG_BMI160_I2C=m
+CONFIG_BMI160_SPI=m
+CONFIG_FXOS8700=m
+CONFIG_FXOS8700_I2C=m
+CONFIG_FXOS8700_SPI=m
+CONFIG_KMX61=m
+CONFIG_INV_ICM42600=m
+CONFIG_INV_ICM42600_I2C=m
+CONFIG_INV_ICM42600_SPI=m
+CONFIG_INV_MPU6050_IIO=m
+CONFIG_INV_MPU6050_I2C=m
+CONFIG_INV_MPU6050_SPI=m
+CONFIG_IIO_ST_LSM6DSX=m
+CONFIG_IIO_ST_LSM6DSX_I2C=m
+CONFIG_IIO_ST_LSM6DSX_SPI=m
+CONFIG_IIO_ST_LSM9DS0=m
+CONFIG_IIO_ST_LSM9DS0_I2C=m
+CONFIG_IIO_ST_LSM9DS0_SPI=m
+# end of Inertial measurement units
+
+CONFIG_IIO_ADIS_LIB=m
+CONFIG_IIO_ADIS_LIB_BUFFER=y
+
+#
+# Light sensors
+#
+CONFIG_ACPI_ALS=m
+CONFIG_ADJD_S311=m
+CONFIG_ADUX1020=m
+CONFIG_AL3010=m
+CONFIG_AL3320A=m
+CONFIG_APDS9300=m
+CONFIG_APDS9960=m
+CONFIG_AS73211=m
+CONFIG_BH1750=m
+CONFIG_BH1780=m
+CONFIG_CM32181=m
+CONFIG_CM3232=m
+CONFIG_CM3323=m
+CONFIG_CM36651=m
+CONFIG_IIO_CROS_EC_LIGHT_PROX=m
+CONFIG_GP2AP002=m
+CONFIG_GP2AP020A00F=m
+CONFIG_IQS621_ALS=m
+CONFIG_SENSORS_ISL29018=m
+CONFIG_SENSORS_ISL29028=m
+CONFIG_ISL29125=m
+CONFIG_HID_SENSOR_ALS=m
+CONFIG_HID_SENSOR_PROX=m
+CONFIG_JSA1212=m
+CONFIG_RPR0521=m
+CONFIG_SENSORS_LM3533=m
+CONFIG_LTR501=m
+CONFIG_LV0104CS=m
+CONFIG_MAX44000=m
+CONFIG_MAX44009=m
+CONFIG_NOA1305=m
+CONFIG_OPT3001=m
+CONFIG_PA12203001=m
+CONFIG_SI1133=m
+CONFIG_SI1145=m
+CONFIG_STK3310=m
+CONFIG_ST_UVIS25=m
+CONFIG_ST_UVIS25_I2C=m
+CONFIG_ST_UVIS25_SPI=m
+CONFIG_TCS3414=m
+CONFIG_TCS3472=m
+CONFIG_SENSORS_TSL2563=m
+CONFIG_TSL2583=m
+CONFIG_TSL2591=m
+CONFIG_TSL2772=m
+CONFIG_TSL4531=m
+CONFIG_US5182D=m
+CONFIG_VCNL4000=m
+CONFIG_VCNL4035=m
+CONFIG_VEML6030=m
+CONFIG_VEML6070=m
+CONFIG_VL6180=m
+CONFIG_ZOPT2201=m
+# end of Light sensors
+
+#
+# Magnetometer sensors
+#
+CONFIG_AK8975=m
+CONFIG_AK09911=m
+CONFIG_BMC150_MAGN=m
+CONFIG_BMC150_MAGN_I2C=m
+CONFIG_BMC150_MAGN_SPI=m
+CONFIG_MAG3110=m
+CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+CONFIG_MMC35240=m
+CONFIG_IIO_ST_MAGN_3AXIS=m
+CONFIG_IIO_ST_MAGN_I2C_3AXIS=m
+CONFIG_IIO_ST_MAGN_SPI_3AXIS=m
+CONFIG_SENSORS_HMC5843=m
+CONFIG_SENSORS_HMC5843_I2C=m
+CONFIG_SENSORS_HMC5843_SPI=m
+CONFIG_SENSORS_RM3100=m
+CONFIG_SENSORS_RM3100_I2C=m
+CONFIG_SENSORS_RM3100_SPI=m
+CONFIG_YAMAHA_YAS530=m
+# end of Magnetometer sensors
+
+#
+# Multiplexers
+#
+# end of Multiplexers
+
+#
+# Inclinometer sensors
+#
+CONFIG_HID_SENSOR_INCLINOMETER_3D=m
+CONFIG_HID_SENSOR_DEVICE_ROTATION=m
+# end of Inclinometer sensors
+
+#
+# Triggers - standalone
+#
+CONFIG_IIO_HRTIMER_TRIGGER=m
+CONFIG_IIO_INTERRUPT_TRIGGER=m
+CONFIG_IIO_TIGHTLOOP_TRIGGER=m
+CONFIG_IIO_SYSFS_TRIGGER=m
+# end of Triggers - standalone
+
+#
+# Linear and angular position sensors
+#
+CONFIG_IQS624_POS=m
+CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE=m
+# end of Linear and angular position sensors
+
+#
+# Digital potentiometers
+#
+CONFIG_AD5110=m
+CONFIG_AD5272=m
+CONFIG_DS1803=m
+CONFIG_MAX5432=m
+CONFIG_MAX5481=m
+CONFIG_MAX5487=m
+CONFIG_MCP4018=m
+CONFIG_MCP4131=m
+CONFIG_MCP4531=m
+CONFIG_MCP41010=m
+CONFIG_TPL0102=m
+# end of Digital potentiometers
+
+#
+# Digital potentiostats
+#
+CONFIG_LMP91000=m
+# end of Digital potentiostats
+
+#
+# Pressure sensors
+#
+CONFIG_ABP060MG=m
+CONFIG_BMP280=m
+CONFIG_BMP280_I2C=m
+CONFIG_BMP280_SPI=m
+CONFIG_IIO_CROS_EC_BARO=m
+CONFIG_DLHL60D=m
+CONFIG_DPS310=m
+CONFIG_HID_SENSOR_PRESS=m
+CONFIG_HP03=m
+CONFIG_ICP10100=m
+CONFIG_MPL115=m
+CONFIG_MPL115_I2C=m
+CONFIG_MPL115_SPI=m
+CONFIG_MPL3115=m
+CONFIG_MS5611=m
+CONFIG_MS5611_I2C=m
+CONFIG_MS5611_SPI=m
+CONFIG_MS5637=m
+CONFIG_IIO_ST_PRESS=m
+CONFIG_IIO_ST_PRESS_I2C=m
+CONFIG_IIO_ST_PRESS_SPI=m
+CONFIG_T5403=m
+CONFIG_HP206C=m
+CONFIG_ZPA2326=m
+CONFIG_ZPA2326_I2C=m
+CONFIG_ZPA2326_SPI=m
+# end of Pressure sensors
+
+#
+# Lightning sensors
+#
+CONFIG_AS3935=m
+# end of Lightning sensors
+
+#
+# Proximity and distance sensors
+#
+CONFIG_CROS_EC_MKBP_PROXIMITY=m
+CONFIG_ISL29501=m
+CONFIG_LIDAR_LITE_V2=m
+CONFIG_MB1232=m
+CONFIG_PING=m
+CONFIG_RFD77402=m
+CONFIG_SRF04=m
+CONFIG_SX9310=m
+CONFIG_SX9500=m
+CONFIG_SRF08=m
+CONFIG_VCNL3020=m
+CONFIG_VL53L0X_I2C=m
+# end of Proximity and distance sensors
+
+#
+# Resolver to digital converters
+#
+CONFIG_AD2S90=m
+CONFIG_AD2S1200=m
+# end of Resolver to digital converters
+
+#
+# Temperature sensors
+#
+CONFIG_IQS620AT_TEMP=m
+CONFIG_LTC2983=m
+CONFIG_MAXIM_THERMOCOUPLE=m
+CONFIG_HID_SENSOR_TEMP=m
+CONFIG_MLX90614=m
+CONFIG_MLX90632=m
+CONFIG_TMP006=m
+CONFIG_TMP007=m
+CONFIG_TMP117=m
+CONFIG_TSYS01=m
+CONFIG_TSYS02D=m
+CONFIG_MAX31856=m
+# end of Temperature sensors
+
+CONFIG_NTB=m
+CONFIG_NTB_MSI=y
+CONFIG_NTB_AMD=m
+CONFIG_NTB_IDT=m
+CONFIG_NTB_INTEL=m
+CONFIG_NTB_EPF=m
+CONFIG_NTB_SWITCHTEC=m
+# CONFIG_NTB_PINGPONG is not set
+# CONFIG_NTB_TOOL is not set
+# CONFIG_NTB_PERF is not set
+# CONFIG_NTB_MSI_TEST is not set
+CONFIG_NTB_TRANSPORT=m
+# CONFIG_VME_BUS is not set
+CONFIG_PWM=y
+CONFIG_PWM_SYSFS=y
+# CONFIG_PWM_DEBUG is not set
+CONFIG_PWM_CRC=y
+CONFIG_PWM_CROS_EC=m
+CONFIG_PWM_DWC=m
+CONFIG_PWM_IQS620A=m
+CONFIG_PWM_LP3943=m
+CONFIG_PWM_LPSS=m
+CONFIG_PWM_LPSS_PCI=m
+CONFIG_PWM_LPSS_PLATFORM=m
+CONFIG_PWM_PCA9685=m
+CONFIG_PWM_TWL=m
+CONFIG_PWM_TWL_LED=m
+
+#
+# IRQ chip support
+#
+CONFIG_MADERA_IRQ=m
+# end of IRQ chip support
+
+CONFIG_IPACK_BUS=m
+CONFIG_BOARD_TPCI200=m
+CONFIG_SERIAL_IPOCTAL=m
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_TI_SYSCON=m
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+CONFIG_USB_LGM_PHY=m
+CONFIG_PHY_CAN_TRANSCEIVER=m
+CONFIG_BCM_KONA_USB2_PHY=m
+CONFIG_PHY_PXA_28NM_HSIC=m
+CONFIG_PHY_PXA_28NM_USB2=m
+CONFIG_PHY_CPCAP_USB=m
+CONFIG_PHY_QCOM_USB_HS=m
+CONFIG_PHY_QCOM_USB_HSIC=m
+CONFIG_PHY_SAMSUNG_USB2=m
+CONFIG_PHY_TUSB1210=m
+CONFIG_PHY_INTEL_LGM_EMMC=m
+# end of PHY Subsystem
+
+CONFIG_POWERCAP=y
+CONFIG_INTEL_RAPL_CORE=m
+CONFIG_INTEL_RAPL=m
+CONFIG_IDLE_INJECT=y
+CONFIG_DTPM=y
+CONFIG_DTPM_CPU=y
+CONFIG_MCB=m
+CONFIG_MCB_PCI=m
+CONFIG_MCB_LPC=m
+
+#
+# Performance monitor support
+#
+# end of Performance monitor support
+
+CONFIG_RAS=y
+CONFIG_RAS_CEC=y
+# CONFIG_RAS_CEC_DEBUG is not set
+CONFIG_USB4=m
+# CONFIG_USB4_DEBUGFS_WRITE is not set
+# CONFIG_USB4_DMA_TEST is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDERFS=y
+CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder"
+# CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set
+# end of Android
+
+CONFIG_LIBNVDIMM=y
+CONFIG_BLK_DEV_PMEM=m
+CONFIG_ND_BLK=m
+CONFIG_ND_CLAIM=y
+CONFIG_ND_BTT=m
+CONFIG_BTT=y
+CONFIG_ND_PFN=m
+CONFIG_NVDIMM_PFN=y
+CONFIG_NVDIMM_DAX=y
+CONFIG_DAX_DRIVER=y
+CONFIG_DAX=y
+CONFIG_DEV_DAX=m
+CONFIG_DEV_DAX_PMEM=m
+CONFIG_DEV_DAX_HMEM=m
+CONFIG_DEV_DAX_HMEM_DEVICES=y
+CONFIG_DEV_DAX_KMEM=m
+CONFIG_DEV_DAX_PMEM_COMPAT=m
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SYSFS=y
+CONFIG_RAVE_SP_EEPROM=m
+CONFIG_NVMEM_RMEM=m
+
+#
+# HW tracing support
+#
+CONFIG_STM=m
+CONFIG_STM_PROTO_BASIC=m
+CONFIG_STM_PROTO_SYS_T=m
+# CONFIG_STM_DUMMY is not set
+CONFIG_STM_SOURCE_CONSOLE=m
+CONFIG_STM_SOURCE_HEARTBEAT=m
+CONFIG_STM_SOURCE_FTRACE=m
+CONFIG_INTEL_TH=m
+CONFIG_INTEL_TH_PCI=m
+CONFIG_INTEL_TH_ACPI=m
+CONFIG_INTEL_TH_GTH=m
+CONFIG_INTEL_TH_STH=m
+CONFIG_INTEL_TH_MSU=m
+CONFIG_INTEL_TH_PTI=m
+# CONFIG_INTEL_TH_DEBUG is not set
+# end of HW tracing support
+
+CONFIG_FPGA=m
+CONFIG_ALTERA_PR_IP_CORE=m
+CONFIG_FPGA_MGR_ALTERA_PS_SPI=m
+CONFIG_FPGA_MGR_ALTERA_CVP=m
+CONFIG_FPGA_MGR_XILINX_SPI=m
+CONFIG_FPGA_MGR_MACHXO2_SPI=m
+CONFIG_FPGA_BRIDGE=m
+CONFIG_ALTERA_FREEZE_BRIDGE=m
+CONFIG_XILINX_PR_DECOUPLER=m
+CONFIG_FPGA_REGION=m
+CONFIG_FPGA_DFL=m
+CONFIG_FPGA_DFL_FME=m
+CONFIG_FPGA_DFL_FME_MGR=m
+CONFIG_FPGA_DFL_FME_BRIDGE=m
+CONFIG_FPGA_DFL_FME_REGION=m
+CONFIG_FPGA_DFL_AFU=m
+CONFIG_FPGA_DFL_NIOS_INTEL_PAC_N3000=m
+CONFIG_FPGA_DFL_PCI=m
+CONFIG_TEE=m
+
+#
+# TEE drivers
+#
+CONFIG_AMDTEE=m
+# end of TEE drivers
+
+CONFIG_MULTIPLEXER=m
+
+#
+# Multiplexer drivers
+#
+CONFIG_MUX_ADG792A=m
+CONFIG_MUX_ADGS1408=m
+CONFIG_MUX_GPIO=m
+# end of Multiplexer drivers
+
+CONFIG_PM_OPP=y
+CONFIG_UNISYS_VISORBUS=m
+CONFIG_SIOX=m
+CONFIG_SIOX_BUS_GPIO=m
+CONFIG_SLIMBUS=m
+CONFIG_SLIM_QCOM_CTRL=m
+CONFIG_INTERCONNECT=y
+CONFIG_COUNTER=m
+CONFIG_INTERRUPT_CNT=m
+CONFIG_INTEL_QEP=m
+CONFIG_MOST=m
+CONFIG_MOST_USB_HDM=m
+CONFIG_MOST_CDEV=m
+CONFIG_MOST_SND=m
+# end of Device Drivers
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_VALIDATE_FS_PARSER=y
+CONFIG_FS_IOMAP=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_USE_FOR_EXT2=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_SUPPORT_V4=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_XFS_ONLINE_SCRUB=y
+CONFIG_XFS_ONLINE_REPAIR=y
+# CONFIG_XFS_WARN is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
+# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set
+# CONFIG_BTRFS_DEBUG is not set
+# CONFIG_BTRFS_ASSERT is not set
+# CONFIG_BTRFS_FS_REF_VERIFY is not set
+CONFIG_NILFS2_FS=m
+CONFIG_F2FS_FS=m
+CONFIG_F2FS_STAT_FS=y
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_FS_POSIX_ACL=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_CHECK_FS=y
+# CONFIG_F2FS_FAULT_INJECTION is not set
+CONFIG_F2FS_FS_COMPRESSION=y
+CONFIG_F2FS_FS_LZO=y
+CONFIG_F2FS_FS_LZORLE=y
+CONFIG_F2FS_FS_LZ4=y
+CONFIG_F2FS_FS_LZ4HC=y
+CONFIG_F2FS_FS_ZSTD=y
+CONFIG_F2FS_IOSTAT=y
+CONFIG_ZONEFS_FS=m
+CONFIG_FS_DAX=y
+CONFIG_FS_DAX_PMD=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION_ALGS=m
+CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
+CONFIG_FS_VERITY=y
+# CONFIG_FS_VERITY_DEBUG is not set
+CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=m
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_VIRTIO_FS=m
+CONFIG_FUSE_DAX=y
+CONFIG_OVERLAY_FS=m
+CONFIG_OVERLAY_FS_REDIRECT_DIR=y
+# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set
+CONFIG_OVERLAY_FS_INDEX=y
+CONFIG_OVERLAY_FS_XINO_AUTO=y
+CONFIG_OVERLAY_FS_METACOPY=y
+
+#
+# Caches
+#
+CONFIG_NETFS_SUPPORT=m
+CONFIG_NETFS_STATS=y
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+# CONFIG_FSCACHE_DEBUG is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# end of Caches
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+# end of CD-ROM/DVD Filesystems
+
+#
+# DOS/FAT/EXFAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_EXFAT_FS=m
+CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8"
+# CONFIG_NTFS_FS is not set
+CONFIG_NTFS3_FS=m
+# CONFIG_NTFS3_64BIT_CLUSTER is not set
+CONFIG_NTFS3_LZX_XPRESS=y
+CONFIG_NTFS3_FS_POSIX_ACL=y
+# end of DOS/FAT/EXFAT/NT Filesystems
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
+CONFIG_PROC_VMCORE_DEVICE_DUMP=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_CHILDREN=y
+CONFIG_PROC_PID_ARCH_STATUS=y
+CONFIG_PROC_CPU_RESCTRL=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_INODE64=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_HUGETLB_PAGE_FREE_VMEMMAP=y
+CONFIG_HUGETLB_PAGE_FREE_VMEMMAP_DEFAULT_ON=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_EFIVAR_FS=y
+# end of Pseudo filesystems
+
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ORANGEFS_FS=m
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+# CONFIG_ECRYPT_FS_MESSAGING is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UBIFS_FS_ZSTD=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_SECURITY=y
+CONFIG_UBIFS_FS_AUTHENTICATION=y
+CONFIG_CRAMFS=m
+CONFIG_CRAMFS_BLOCKDEV=y
+CONFIG_CRAMFS_MTD=y
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_FILE_CACHE is not set
+CONFIG_SQUASHFS_FILE_DIRECT=y
+# CONFIG_SQUASHFS_DECOMP_SINGLE is not set
+# CONFIG_SQUASHFS_DECOMP_MULTI is not set
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_ZLIB=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240
+CONFIG_PSTORE_DEFLATE_COMPRESS=m
+CONFIG_PSTORE_LZO_COMPRESS=m
+CONFIG_PSTORE_LZ4_COMPRESS=m
+CONFIG_PSTORE_LZ4HC_COMPRESS=m
+# CONFIG_PSTORE_842_COMPRESS is not set
+CONFIG_PSTORE_ZSTD_COMPRESS=y
+CONFIG_PSTORE_COMPRESS=y
+# CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT is not set
+# CONFIG_PSTORE_LZO_COMPRESS_DEFAULT is not set
+# CONFIG_PSTORE_LZ4_COMPRESS_DEFAULT is not set
+# CONFIG_PSTORE_LZ4HC_COMPRESS_DEFAULT is not set
+CONFIG_PSTORE_ZSTD_COMPRESS_DEFAULT=y
+CONFIG_PSTORE_COMPRESS_DEFAULT="zstd"
+# CONFIG_PSTORE_CONSOLE is not set
+# CONFIG_PSTORE_PMSG is not set
+# CONFIG_PSTORE_FTRACE is not set
+CONFIG_PSTORE_RAM=m
+# CONFIG_PSTORE_BLK is not set
+# CONFIG_SYSV_FS is not set
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_EROFS_FS=m
+# CONFIG_EROFS_FS_DEBUG is not set
+CONFIG_EROFS_FS_XATTR=y
+CONFIG_EROFS_FS_POSIX_ACL=y
+CONFIG_EROFS_FS_SECURITY=y
+CONFIG_EROFS_FS_ZIP=y
+CONFIG_VBOXSF_FS=m
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V2=m
+CONFIG_NFS_V3=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFS_SWAP=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_PNFS_FILE_LAYOUT=m
+CONFIG_PNFS_BLOCK=m
+CONFIG_PNFS_FLEXFILE_LAYOUT=m
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+CONFIG_NFS_V4_1_MIGRATION=y
+CONFIG_NFS_V4_SECURITY_LABEL=y
+CONFIG_NFS_FSCACHE=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+CONFIG_NFS_DEBUG=y
+# CONFIG_NFS_DISABLE_UDP_SUPPORT is not set
+# CONFIG_NFS_V4_2_READ_PLUS is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_PNFS=y
+CONFIG_NFSD_BLOCKLAYOUT=y
+CONFIG_NFSD_SCSILAYOUT=y
+# CONFIG_NFSD_FLEXFILELAYOUT is not set
+CONFIG_NFSD_V4_2_INTER_SSC=y
+CONFIG_NFSD_V4_SECURITY_LABEL=y
+CONFIG_GRACE_PERIOD=m
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_NFS_V4_2_SSC_HELPER=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_BACKCHANNEL=y
+CONFIG_SUNRPC_SWAP=y
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y
+CONFIG_SUNRPC_DEBUG=y
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_CEPH_FS=m
+CONFIG_CEPH_FSCACHE=y
+CONFIG_CEPH_FS_POSIX_ACL=y
+CONFIG_CEPH_FS_SECURITY_LABEL=y
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DEBUG=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_SWN_UPCALL=y
+# CONFIG_CIFS_SMB_DIRECT is not set
+CONFIG_CIFS_FSCACHE=y
+CONFIG_SMB_SERVER=m
+CONFIG_SMB_SERVER_SMBDIRECT=y
+CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN=y
+CONFIG_SMB_SERVER_KERBEROS5=y
+CONFIG_SMBFS_COMMON=m
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_AFS_FSCACHE=y
+# CONFIG_AFS_DEBUG_CURSOR is not set
+CONFIG_9P_FS=m
+CONFIG_9P_FSCACHE=y
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_9P_FS_SECURITY=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+CONFIG_UNICODE=y
+# CONFIG_UNICODE_NORMALIZATION_SELFTEST is not set
+CONFIG_IO_WQ=y
+# end of File systems
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_REQUEST_CACHE=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_TRUSTED_KEYS=m
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_KEY_DH_OPERATIONS=y
+CONFIG_KEY_NOTIFICATIONS=y
+CONFIG_SECURITY_DMESG_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_PAGE_TABLE_ISOLATION=y
+CONFIG_SECURITY_INFINIBAND=y
+CONFIG_SECURITY_NETWORK_XFRM=y
+CONFIG_SECURITY_PATH=y
+# CONFIG_INTEL_TXT is not set
+CONFIG_LSM_MMAP_MIN_ADDR=65536
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HARDENED_USERCOPY_FALLBACK=y
+CONFIG_FORTIFY_SOURCE=y
+# CONFIG_STATIC_USERMODEHELPER is not set
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+# CONFIG_SECURITY_SELINUX_DISABLE is not set
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0
+CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9
+CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256
+CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_SMACK_BRINGUP=y
+CONFIG_SECURITY_SMACK_NETFILTER=y
+CONFIG_SECURITY_SMACK_APPEND_SIGNALS=y
+CONFIG_SECURITY_TOMOYO=y
+CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=2048
+CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=1024
+# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set
+CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/usr/bin/tomoyo-init"
+CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/usr/lib/systemd/systemd"
+# CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING is not set
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_SECURITY_APPARMOR_HASH=y
+CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y
+# CONFIG_SECURITY_APPARMOR_DEBUG is not set
+CONFIG_SECURITY_LOADPIN=y
+CONFIG_SECURITY_LOADPIN_ENFORCE=y
+CONFIG_SECURITY_YAMA=y
+CONFIG_SECURITY_SAFESETID=y
+CONFIG_SECURITY_LOCKDOWN_LSM=y
+# CONFIG_SECURITY_LOCKDOWN_LSM_EARLY is not set
+CONFIG_LOCK_DOWN_KERNEL_FORCE_NONE=y
+# CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY is not set
+# CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY is not set
+CONFIG_SECURITY_LANDLOCK=y
+# CONFIG_INTEGRITY is not set
+# CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_LSM="lockdown,landlock,yama"
+
+#
+# Kernel hardening options
+#
+CONFIG_GCC_PLUGIN_STRUCTLEAK=y
+
+#
+# Memory initialization
+#
+# CONFIG_INIT_STACK_NONE is not set
+# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set
+# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set
+CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y
+# CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE is not set
+# CONFIG_GCC_PLUGIN_STACKLEAK is not set
+CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
+# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
+CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
+CONFIG_ZERO_CALL_USED_REGS=y
+# end of Memory initialization
+# end of Kernel hardening options
+# end of Security options
+
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SKCIPHER=y
+CONFIG_CRYPTO_SKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_AKCIPHER=y
+CONFIG_CRYPTO_KPP2=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_SIMD=m
+CONFIG_CRYPTO_ENGINE=m
+
+#
+# Public-key cryptography
+#
+CONFIG_CRYPTO_RSA=y
+CONFIG_CRYPTO_DH=y
+CONFIG_CRYPTO_ECC=y
+CONFIG_CRYPTO_ECDH=m
+CONFIG_CRYPTO_ECDSA=y
+CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_SM2=m
+CONFIG_CRYPTO_CURVE25519=m
+CONFIG_CRYPTO_CURVE25519_X86=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_AEGIS128_AESNI_SSE2=m
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_NHPOLY1305=m
+CONFIG_CRYPTO_NHPOLY1305_SSE2=m
+CONFIG_CRYPTO_NHPOLY1305_AVX2=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ESSIV=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_CRC32_PCLMUL=m
+CONFIG_CRYPTO_XXHASH=m
+CONFIG_CRYPTO_BLAKE2B=m
+CONFIG_CRYPTO_BLAKE2S=m
+CONFIG_CRYPTO_BLAKE2S_X86=m
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_CRCT10DIF_PCLMUL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_POLY1305=m
+CONFIG_CRYPTO_POLY1305_X86_64=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_SSSE3=m
+CONFIG_CRYPTO_SHA256_SSSE3=m
+CONFIG_CRYPTO_SHA512_SSSE3=m
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3=m
+CONFIG_CRYPTO_STREEBOG=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_BLOWFISH_X86_64=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAMELLIA_X86_64=m
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=m
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m
+CONFIG_CRYPTO_CAST_COMMON=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST5_AVX_X86_64=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_CAST6_AVX_X86_64=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DES3_EDE_X86_64=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_CHACHA20=m
+CONFIG_CRYPTO_CHACHA20_X86_64=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m
+CONFIG_CRYPTO_SERPENT_AVX_X86_64=m
+CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m
+CONFIG_CRYPTO_SM4=m
+CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64=m
+CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_X86_64=m
+CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m
+CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
+CONFIG_CRYPTO_LZ4=y
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ZSTD=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_HASH=y
+CONFIG_CRYPTO_DRBG_CTR=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+CONFIG_CRYPTO_USER_API=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
+CONFIG_CRYPTO_USER_API_AEAD=m
+# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set
+CONFIG_CRYPTO_STATS=y
+CONFIG_CRYPTO_HASH_INFO=y
+
+#
+# Crypto library routines
+#
+CONFIG_CRYPTO_LIB_AES=y
+CONFIG_CRYPTO_LIB_ARC4=m
+CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S=m
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=m
+CONFIG_CRYPTO_LIB_BLAKE2S=m
+CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA=m
+CONFIG_CRYPTO_LIB_CHACHA_GENERIC=m
+CONFIG_CRYPTO_LIB_CHACHA=m
+CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519=m
+CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=m
+CONFIG_CRYPTO_LIB_CURVE25519=m
+CONFIG_CRYPTO_LIB_DES=m
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11
+CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305=m
+CONFIG_CRYPTO_LIB_POLY1305_GENERIC=m
+CONFIG_CRYPTO_LIB_POLY1305=m
+CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
+CONFIG_CRYPTO_LIB_SHA256=y
+CONFIG_CRYPTO_LIB_SM4=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_ATMEL_I2C=m
+CONFIG_CRYPTO_DEV_ATMEL_ECC=m
+CONFIG_CRYPTO_DEV_ATMEL_SHA204A=m
+CONFIG_CRYPTO_DEV_CCP=y
+CONFIG_CRYPTO_DEV_CCP_DD=m
+CONFIG_CRYPTO_DEV_SP_CCP=y
+CONFIG_CRYPTO_DEV_CCP_CRYPTO=m
+CONFIG_CRYPTO_DEV_SP_PSP=y
+CONFIG_CRYPTO_DEV_CCP_DEBUGFS=y
+CONFIG_CRYPTO_DEV_QAT=m
+CONFIG_CRYPTO_DEV_QAT_DH895xCC=m
+CONFIG_CRYPTO_DEV_QAT_C3XXX=m
+CONFIG_CRYPTO_DEV_QAT_C62X=m
+CONFIG_CRYPTO_DEV_QAT_4XXX=m
+CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=m
+CONFIG_CRYPTO_DEV_QAT_C3XXXVF=m
+CONFIG_CRYPTO_DEV_QAT_C62XVF=m
+CONFIG_CRYPTO_DEV_NITROX=m
+CONFIG_CRYPTO_DEV_NITROX_CNN55XX=m
+CONFIG_CRYPTO_DEV_CHELSIO=m
+CONFIG_CRYPTO_DEV_VIRTIO=m
+CONFIG_CRYPTO_DEV_SAFEXCEL=m
+CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m
+CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG=y
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE=m
+CONFIG_X509_CERTIFICATE_PARSER=y
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=m
+CONFIG_TPM_KEY_PARSER=m
+CONFIG_PKCS7_MESSAGE_PARSER=y
+# CONFIG_PKCS7_TEST_KEY is not set
+CONFIG_SIGNED_PE_FILE_VERIFICATION=y
+
+#
+# Certificates for signature checking
+#
+CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
+# CONFIG_MODULE_SIG_KEY_TYPE_RSA is not set
+CONFIG_MODULE_SIG_KEY_TYPE_ECDSA=y
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_TRUSTED_KEYS=""
+# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
+CONFIG_SECONDARY_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_BLACKLIST_KEYRING=y
+CONFIG_SYSTEM_BLACKLIST_HASH_LIST=""
+CONFIG_SYSTEM_REVOCATION_LIST=y
+CONFIG_SYSTEM_REVOCATION_KEYS=""
+# end of Certificates for signature checking
+
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+# CONFIG_RAID6_PQ_BENCHMARK is not set
+CONFIG_LINEAR_RANGES=y
+CONFIG_PACKING=y
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_CORDIC=m
+# CONFIG_PRIME_NUMBERS is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC64=m
+CONFIG_CRC4=m
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_CRC8=m
+CONFIG_XXHASH=y
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_842_COMPRESS=m
+CONFIG_842_DECOMPRESS=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4HC_COMPRESS=m
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_ZSTD_COMPRESS=y
+CONFIG_ZSTD_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_DECOMPRESS_ZSTD=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_BCH=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_BTREE=y
+CONFIG_INTERVAL_TREE=y
+CONFIG_XARRAY_MULTI=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DMA_OPS=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED=y
+CONFIG_SWIOTLB=y
+CONFIG_DMA_COHERENT_POOL=y
+CONFIG_DMA_CMA=y
+# CONFIG_DMA_PERNUMA_CMA is not set
+
+#
+# Default contiguous memory area size:
+#
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_ALIGNMENT=8
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_DMA_MAP_BENCHMARK is not set
+CONFIG_SGL_ALLOC=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+CONFIG_LRU_CACHE=m
+CONFIG_CLZ_TAB=y
+CONFIG_IRQ_POLL=y
+CONFIG_MPILIB=y
+CONFIG_DIMLIB=y
+CONFIG_OID_REGISTRY=y
+CONFIG_UCS2_STRING=y
+CONFIG_HAVE_GENERIC_VDSO=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_VDSO_TIME_NS=y
+CONFIG_FONT_SUPPORT=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_6x10 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+CONFIG_FONT_TER16x32=y
+# CONFIG_FONT_6x8 is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_PMEM_API=y
+CONFIG_MEMREGION=y
+CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
+CONFIG_ARCH_HAS_COPY_MC=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_SBITMAP=y
+CONFIG_PARMAN=m
+CONFIG_OBJAGG=m
+# end of Library routines
+
+CONFIG_PLDMFW=y
+CONFIG_ASN1_ENCODER=m
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+# CONFIG_PRINTK_CALLER is not set
+CONFIG_STACKTRACE_BUILD_ID=y
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=4
+CONFIG_CONSOLE_LOGLEVEL_QUIET=1
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DYNAMIC_DEBUG_CORE=y
+CONFIG_SYMBOLIC_ERRNAME=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# end of printk and dmesg options
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_INFO_COMPRESSED is not set
+# CONFIG_DEBUG_INFO_SPLIT is not set
+# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_DEBUG_INFO_BTF=y
+CONFIG_PAHOLE_HAS_SPLIT_BTF=y
+CONFIG_DEBUG_INFO_BTF_MODULES=y
+# CONFIG_GDB_SCRIPTS is not set
+CONFIG_FRAME_WARN=2048
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_READABLE_ASM is not set
+# CONFIG_HEADERS_INSTALL is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_STACK_VALIDATION=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# end of Compile-time checks and compiler options
+
+#
+# Generic Kernel Debugging Instruments
+#
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0
+CONFIG_MAGIC_SYSRQ_SERIAL=y
+CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_FS_ALLOW_ALL=y
+# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
+# CONFIG_DEBUG_FS_ALLOW_NONE is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
+# CONFIG_UBSAN is not set
+CONFIG_HAVE_ARCH_KCSAN=y
+CONFIG_HAVE_KCSAN_COMPILER=y
+# CONFIG_KCSAN is not set
+# end of Generic Kernel Debugging Instruments
+
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_MISC is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_OWNER is not set
+CONFIG_PAGE_POISONING=y
+# CONFIG_DEBUG_PAGE_REF is not set
+CONFIG_DEBUG_RODATA_TEST=y
+CONFIG_ARCH_HAS_DEBUG_WX=y
+CONFIG_DEBUG_WX=y
+CONFIG_GENERIC_PTDUMP=y
+CONFIG_PTDUMP_CORE=y
+# CONFIG_PTDUMP_DEBUGFS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VM_PGTABLE is not set
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+# CONFIG_DEBUG_VIRTUAL is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y
+# CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP is not set
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
+CONFIG_CC_HAS_KASAN_GENERIC=y
+CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
+# CONFIG_KASAN is not set
+CONFIG_HAVE_ARCH_KFENCE=y
+CONFIG_KFENCE=y
+CONFIG_KFENCE_SAMPLE_INTERVAL=100
+CONFIG_KFENCE_NUM_OBJECTS=255
+CONFIG_KFENCE_STRESS_TEST_FAULTS=0
+# end of Memory Debugging
+
+CONFIG_DEBUG_SHIRQ=y
+
+#
+# Debug Oops, Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
+CONFIG_HARDLOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_TEST_LOCKUP is not set
+# end of Debug Oops, Lockups and Hangs
+
+#
+# Scheduler Debugging
+#
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
+CONFIG_SCHEDSTATS=y
+# end of Scheduler Debugging
+
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_DEBUG_PREEMPT is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_WW_MUTEX_SELFTEST is not set
+# CONFIG_SCF_TORTURE_TEST is not set
+# CONFIG_CSD_LOCK_WAIT_DEBUG is not set
+# end of Lock Debugging (spinlocks, mutexes, etc...)
+
+# CONFIG_DEBUG_IRQFLAGS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
+# CONFIG_DEBUG_KOBJECT is not set
+
+#
+# Debug kernel data structures
+#
+CONFIG_DEBUG_LIST=y
+# CONFIG_DEBUG_PLIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BUG_ON_DATA_CORRUPTION is not set
+# end of Debug kernel data structures
+
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_RCU_SCALE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_REF_SCALE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# end of RCU Debugging
+
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+CONFIG_LATENCYTOP=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_FENTRY=y
+CONFIG_HAVE_OBJTOOL_MCOUNT=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+CONFIG_BOOTTIME_TRACING=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_FUNCTION_GRAPH_TRACER=y
+CONFIG_DYNAMIC_FTRACE=y
+CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+CONFIG_SCHED_TRACER=y
+CONFIG_HWLAT_TRACER=y
+CONFIG_OSNOISE_TRACER=y
+CONFIG_TIMERLAT_TRACER=y
+CONFIG_MMIOTRACE=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_TRACER_SNAPSHOT=y
+# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_KPROBE_EVENTS=y
+# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set
+CONFIG_UPROBE_EVENTS=y
+CONFIG_BPF_EVENTS=y
+CONFIG_DYNAMIC_EVENTS=y
+CONFIG_PROBE_EVENTS=y
+CONFIG_BPF_KPROBE_OVERRIDE=y
+CONFIG_FTRACE_MCOUNT_RECORD=y
+CONFIG_FTRACE_MCOUNT_USE_CC=y
+CONFIG_TRACING_MAP=y
+CONFIG_SYNTH_EVENTS=y
+CONFIG_HIST_TRIGGERS=y
+# CONFIG_TRACE_EVENT_INJECT is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_TRACE_EVAL_MAP_FILE is not set
+# CONFIG_FTRACE_RECORD_RECURSION is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS is not set
+# CONFIG_MMIOTRACE_TEST is not set
+# CONFIG_PREEMPTIRQ_DELAY_TEST is not set
+# CONFIG_SYNTH_EVENT_GEN_TEST is not set
+# CONFIG_KPROBE_EVENT_GEN_TEST is not set
+# CONFIG_HIST_TRIGGERS_DEBUG is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_SAMPLES is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_IO_STRICT_DEVMEM=y
+
+#
+# x86 Debugging
+#
+CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
+CONFIG_EARLY_PRINTK_USB=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_EARLY_PRINTK_DBGP=y
+CONFIG_EARLY_PRINTK_USB_XDBC=y
+# CONFIG_EFI_PGT_DUMP is not set
+# CONFIG_DEBUG_TLBFLUSH is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_X86_DECODER_SELFTEST=y
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEBUG_BOOT_PARAMS=y
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_DEBUG_ENTRY is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+# CONFIG_X86_DEBUG_FPU is not set
+# CONFIG_PUNIT_ATOM_DEBUG is not set
+CONFIG_UNWINDER_ORC=y
+# CONFIG_UNWINDER_FRAME_POINTER is not set
+# end of x86 Debugging
+
+#
+# Kernel Testing and Coverage
+#
+# CONFIG_KUNIT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+CONFIG_FUNCTION_ERROR_INJECTION=y
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_ARCH_HAS_KCOV=y
+CONFIG_CC_HAS_SANCOV_TRACE_PC=y
+# CONFIG_KCOV is not set
+CONFIG_RUNTIME_TESTING_MENU=y
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_MIN_HEAP is not set
+# CONFIG_TEST_DIV64 is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_REED_SOLOMON_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+CONFIG_ASYNC_RAID6_TEST=m
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_STRING_SELFTEST is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_STRSCPY is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_SCANF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_XARRAY is not set
+# CONFIG_TEST_OVERFLOW is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_TEST_IDA is not set
+# CONFIG_TEST_PARMAN is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_BITOPS is not set
+# CONFIG_TEST_VMALLOC is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_BLACKHOLE_DEV is not set
+# CONFIG_FIND_BIT_BENCHMARK is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_SYSCTL is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_TEST_KMOD is not set
+# CONFIG_TEST_MEMCAT_P is not set
+# CONFIG_TEST_OBJAGG is not set
+# CONFIG_TEST_STACKINIT is not set
+# CONFIG_TEST_MEMINIT is not set
+# CONFIG_TEST_HMM is not set
+# CONFIG_TEST_FREE_PAGES is not set
+# CONFIG_TEST_FPU is not set
+# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set
+CONFIG_ARCH_USE_MEMTEST=y
+# CONFIG_MEMTEST is not set
+# CONFIG_HYPERV_TESTING is not set
+# end of Kernel Testing and Coverage
+# end of Kernel hacking
diff --git a/modules.list b/modules.list
new file mode 100644
index 000000000000..56d170f099ce
--- /dev/null
+++ b/modules.list
@@ -0,0 +1,12 @@
+acpi_call
+bbswitch
+broadcom-wl
+nvidia
+nvidia-390xx
+nvidia-470xx
+r8168
+rtl8723bu
+tp_smapi
+vhba-module
+virtualbox-modules
+zfs