Added
This commit is contained in:
parent
d7173897c4
commit
b248d4ed1b
16
sys-kernel/pinephone-sources/Manifest
Normal file
16
sys-kernel/pinephone-sources/Manifest
Normal file
@ -0,0 +1,16 @@
|
||||
DIST all-5.11.10.patch 15061885 BLAKE2B 8e5c483f90e1d2832dd74f26e8078b91fc16a50a5a2d6970c60760e899ec0bc4b39c9399691b31d9ebabc111878edcd09f2417b269b5379a645c02c0517d1f86 SHA512 c8d3d80b7a087c622863cdd17c88fdaf1b0432fbb91e4e8f36463fdcb038d38c0112c0ef31b6e9f7c6af54b3e8bbb9ccd2bd99354c46a34aaa5606e10d7172df
|
||||
DIST all-5.11.11.patch 15061885 BLAKE2B 8e5c483f90e1d2832dd74f26e8078b91fc16a50a5a2d6970c60760e899ec0bc4b39c9399691b31d9ebabc111878edcd09f2417b269b5379a645c02c0517d1f86 SHA512 c8d3d80b7a087c622863cdd17c88fdaf1b0432fbb91e4e8f36463fdcb038d38c0112c0ef31b6e9f7c6af54b3e8bbb9ccd2bd99354c46a34aaa5606e10d7172df
|
||||
DIST all-5.11.12.patch 15061885 BLAKE2B 8e5c483f90e1d2832dd74f26e8078b91fc16a50a5a2d6970c60760e899ec0bc4b39c9399691b31d9ebabc111878edcd09f2417b269b5379a645c02c0517d1f86 SHA512 c8d3d80b7a087c622863cdd17c88fdaf1b0432fbb91e4e8f36463fdcb038d38c0112c0ef31b6e9f7c6af54b3e8bbb9ccd2bd99354c46a34aaa5606e10d7172df
|
||||
DIST all-5.11.8.patch 15061885 BLAKE2B 8e5c483f90e1d2832dd74f26e8078b91fc16a50a5a2d6970c60760e899ec0bc4b39c9399691b31d9ebabc111878edcd09f2417b269b5379a645c02c0517d1f86 SHA512 c8d3d80b7a087c622863cdd17c88fdaf1b0432fbb91e4e8f36463fdcb038d38c0112c0ef31b6e9f7c6af54b3e8bbb9ccd2bd99354c46a34aaa5606e10d7172df
|
||||
DIST all-5.12_rc3.patch 15033523 BLAKE2B 29ff7d60b71856994d727f36c33c8352c963f8b59befbbef421f6798e5001c601dd2f2080faddf4c4d711931130604665af1e5e7e3bd7c22a84da1a0f198b559 SHA512 a2761ca964ad02b0fab029b6ee2cf84040f5cc86909227dca62255edd33bf49aef167e8ecbc8e899a86daff8d5e5b3814c56b18f4f8e371e2ab85dac7f22de6a
|
||||
DIST all.patch 14517437 BLAKE2B ec81c49d07cf9cf20081050be80ad1bcb5ed5f08b5940a34dcf4156b4eaf260a100d6fe690fc38dc83631862b9177583146ee4b67fcd548b9285bd8f5551c800 SHA512 326898b0bf4f8d737d9e44a45eb6d6bd78f240829c28735b78936823e2031565e11882780389a152889a6b27ff40f789851fe991b5c43e8ecf64f2aa2ced6c49
|
||||
DIST genpatches-5.9-12.base.tar.xz 628408 BLAKE2B 6dbb2c992971cf3ee1c0a0c7a7b70876bcc41e93dd6def0fe87e2a4ddaf62ebfe808487ac117b79eb629c34e66ef1a02bf7adc2191c3273bf77ea384260a5bd3 SHA512 bde0614ff1eb3dc9f681fa8a5f8207c8d2f9a959984fd3a0c8bc4da8ca432d6e1a32992735a8c59074de738a6d1341aa688efc75eaca6cb575f41e694f333d7f
|
||||
DIST genpatches-5.9-12.experimental.tar.xz 6088 BLAKE2B e6773b615967443b961e498e50ce50c48608b71f0373bbf8c68d2aac4906c18dcca3e1578157ab0413c700ac2f67140fc47901c757d8292e1d1051f6ef77c21b SHA512 bf21c813045ecd51d2fef01f15269eb77c9c672e3133dcbb60461190e6c5b5f7f3bacf557b7d48f4bed702ba3135a665d319ed218cce1b8319ee83d93d1eeb19
|
||||
DIST genpatches-5.9-12.extras.tar.xz 1764 BLAKE2B 8bfbde759342d00f10d6fe12e313d449de35aba13a5ba3564043d0489205eafa709a6481e7249bb79f54c84c759f50ca7f630e2e2bbfebc71942f72b3c8ea6e8 SHA512 274a2d2fce2f446503c4540d30daa3c3d6a86e6e6c206f0a2e1e89ee1ebd496f6ce2706add35ca6fc39df2c0758719faf332a230db18dfa9f81dab787f24eb3d
|
||||
DIST linux-5.11.tar.xz 117619104 BLAKE2B 81300c27bd5476387a83123aaeb4163c73eb61e9245806c23660cb5e6a4fa88ffc9def027031335fa0270fc4080506cd415990014364e3a98b9d2e8c58a29524 SHA512 a567ec133018bb5ec00c60281479b466c26e02137a93a9c690e83997947df02b6fd94e76e8df748f6d70ceb58a19bacc3b1467de10b7a1fad2763db32b3f1330
|
||||
DIST linux-5.9.tar.xz 115507140 BLAKE2B e8d11472d63a9f8409ca12a2e8c97c6963a3d4516b5a398b627d6ece565584526f9b5a1377a2fa4bd184c09c7db94c987428bc5d52df0c788464a67e9e8d6dcb SHA512 d3d92ce4246bad74c9a784212f160d98449b1e8793970c2c308276568d852b8effe0528686bdb87d55d691f09a826abf7938d69bdd4759ce65ddd5c05ffe4eca
|
||||
DIST patch-5.11.10.xz 426380 BLAKE2B 434458f668f17e79ebecce4085b027f3485f465efc56d8c3f5c28f30a18937237e39b4f30bcd81e033ea258f37c43dcc38cdb586dbb3983004471c3a6302079b SHA512 5c7a3dc972169363feab6f007af1105a9fb0ad52dbca2cb9d7546ab8bccee28f8faceb443a154a6349b2329400e264e91153d01685e48604dd9cb967eab04e1f
|
||||
DIST patch-5.11.11.xz 497760 BLAKE2B 277e6427be5aefffadf613fcfd4383c8a4e26ddd6e568ed7217453b3592882c90810fce65f475afbb70574767a84deb270d17bc943d04e25d5e2a7d8ebf81477 SHA512 2aed1fb05c93dcb1d8825639c5aba004a16d53af24b278eb036d0b85675e6a5f2738579d35301c9b6624fb7cc16bf3394d4a0e50fcaad5f030c91dd1382777a9
|
||||
DIST patch-5.11.12.xz 540552 BLAKE2B 9056711279a2b1f54b02b13bec3eb870e8369ddef52768ede6d59e8fa3be84110e6d2d2a62e6a2c164e3cd8b4e9252b3da376d9a585ff693c6d94f1a1b8a7fe2 SHA512 feaf70c5d418792d2954ce70e8168397cfb053db4f6c98aa9cd1db935c850cfbe5f75dd23dcfeb5aa1127c63823b2e3ec0393a19a8d253387c6a537c2518f7a4
|
||||
DIST patch-5.11.8.xz 401900 BLAKE2B 0f0a92236328844fd75fe536912195bcad5f7f3c9288b342b84a26702c500df312eb1183fe979cdc286d08dc82527a43d081b3acfe3bafb81a58fa0fd646a312 SHA512 44edcabf7894cbfd32191200fad810141f42cd3cf885a100ce37c796232f2217673c3e407c91132b9ee08741ccc9a53f882b6c86d0a606c4462830799c8f94fb
|
||||
DIST patch-5.12-rc3.patch 38689504 BLAKE2B 25962d05cfd031ea45347f339da8dd206c38ee16c78fd5ff39edb564474b11d4321e450904f9db491f62bb6002e338ef3136327d656c028eaae6f8a3b9207229 SHA512 585a883af66641247e3a44ca56788dc5afe5a2f3a8bd0d9aaabba0324cbbbd4dffdad0d9bc65e30f77903c870985bfbfe1a3283cc709b92417f89d2c94ab8f16
|
@ -0,0 +1,40 @@
|
||||
From 7045054c96224ead00aae09246f475dfe6202def Mon Sep 17 00:00:00 2001
|
||||
From: Danct12 <danct12@disroot.org>
|
||||
Date: Tue, 19 Jan 2021 10:09:01 +0700
|
||||
Subject: [PATCH] arm64: dts: allwinner: pinephone: stop LEDs on suspend
|
||||
|
||||
Signed-off-by: Danct12 <danct12@disroot.org>
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 02d82980c..00ed866ae 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -218,14 +218,12 @@
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
|
||||
- retain-state-suspended;
|
||||
};
|
||||
|
||||
green {
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
gpios = <&pio 3 18 GPIO_ACTIVE_HIGH>; /* PD18 */
|
||||
- retain-state-suspended;
|
||||
};
|
||||
|
||||
red {
|
||||
@@ -233,7 +231,6 @@
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
|
||||
- retain-state-suspended;
|
||||
};
|
||||
};
|
||||
|
||||
--
|
||||
2.30.0
|
||||
|
746
sys-kernel/pinephone-sources/files/0001-bootsplash.patch
Normal file
746
sys-kernel/pinephone-sources/files/0001-bootsplash.patch
Normal file
@ -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
|
@ -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 & 0x10);
|
@ -0,0 +1,67 @@
|
||||
From 27061f0b322a585c30db111719f89c23c15a88b4 Mon Sep 17 00:00:00 2001
|
||||
From: Sathish Narasimman <nsathish41@gmail.com>
|
||||
Date: Thu, 29 Oct 2020 13:18:21 +0530
|
||||
Subject: Bluetooth: Fix: LL PRivacy BLE device fails to connect
|
||||
|
||||
When adding device to white list the device is added to resolving list
|
||||
also. It has to be added only when HCI_ENABLE_LL_PRIVACY flag is set.
|
||||
HCI_ENABLE_LL_PRIVACY flag has to be tested before adding/deleting devices
|
||||
to resolving list. use_ll_privacy macro is used only to check if controller
|
||||
supports LL_Privacy.
|
||||
|
||||
https://bugzilla.kernel.org/show_bug.cgi?id=209745
|
||||
|
||||
Fixes: 0eee35bdfa3b ("Bluetooth: Update resolving list when updating whitelist")
|
||||
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
|
||||
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
|
||||
---
|
||||
net/bluetooth/hci_request.c | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
|
||||
index e0269192f2e5..a565c91b8599 100644
|
||||
--- a/net/bluetooth/hci_request.c
|
||||
+++ b/net/bluetooth/hci_request.c
|
||||
@@ -698,7 +698,8 @@ static void del_from_white_list(struct hci_request *req, bdaddr_t *bdaddr,
|
||||
cp.bdaddr_type);
|
||||
hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, sizeof(cp), &cp);
|
||||
|
||||
- if (use_ll_privacy(req->hdev)) {
|
||||
+ if (use_ll_privacy(req->hdev) &&
|
||||
+ hci_dev_test_flag(req->hdev, HCI_ENABLE_LL_PRIVACY)) {
|
||||
struct smp_irk *irk;
|
||||
|
||||
irk = hci_find_irk_by_addr(req->hdev, bdaddr, bdaddr_type);
|
||||
@@ -732,7 +733,8 @@ static int add_to_white_list(struct hci_request *req,
|
||||
return -1;
|
||||
|
||||
/* White list can not be used with RPAs */
|
||||
- if (!allow_rpa && !use_ll_privacy(hdev) &&
|
||||
+ if (!allow_rpa &&
|
||||
+ !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
|
||||
hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -750,7 +752,8 @@ static int add_to_white_list(struct hci_request *req,
|
||||
cp.bdaddr_type);
|
||||
hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp);
|
||||
|
||||
- if (use_ll_privacy(hdev)) {
|
||||
+ if (use_ll_privacy(hdev) &&
|
||||
+ hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY)) {
|
||||
struct smp_irk *irk;
|
||||
|
||||
irk = hci_find_irk_by_addr(hdev, ¶ms->addr,
|
||||
@@ -812,7 +815,8 @@ static u8 update_white_list(struct hci_request *req)
|
||||
}
|
||||
|
||||
/* White list can not be used with RPAs */
|
||||
- if (!allow_rpa && !use_ll_privacy(hdev) &&
|
||||
+ if (!allow_rpa &&
|
||||
+ !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
|
||||
hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) {
|
||||
return 0x00;
|
||||
}
|
||||
--
|
||||
cgit v1.2.3-1-gf6bb5
|
||||
|
669
sys-kernel/pinephone-sources/files/0002-bootsplash.patch
Normal file
669
sys-kernel/pinephone-sources/files/0002-bootsplash.patch
Normal file
@ -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
|
@ -0,0 +1,61 @@
|
||||
From 33212e529708fd480eaf9cc76579f8e7044c0505 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Braam <martijn@brixit.nl>
|
||||
Date: Tue, 20 Oct 2020 14:42:01 +0200
|
||||
Subject: [PATCH] dts: add pinetab-dev (old display panel)
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/Makefile | 1 +
|
||||
.../dts/allwinner/sun50i-a64-pinetab-dev.dts | 29 +++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
|
||||
index a21cfdd8924d..2936092002b5 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/Makefile
|
||||
+++ b/arch/arm64/boot/dts/allwinner/Makefile
|
||||
@@ -15,6 +15,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.0.dtb
|
||||
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.1.dtb
|
||||
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.2.dtb
|
||||
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinetab.dtb
|
||||
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinetab-dev.dtb
|
||||
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
|
||||
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
|
||||
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts
|
||||
new file mode 100644
|
||||
index 000000000000..1e287f2fb9f3
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts
|
||||
@@ -0,0 +1,29 @@
|
||||
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
+/*
|
||||
+ * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.xyz>
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+/dts-v1/;
|
||||
+
|
||||
+#include "sun50i-a64-pinetab.dts"
|
||||
+
|
||||
+/ {
|
||||
+ model = "PineTab";
|
||||
+ compatible = "pine64,pinetab", "allwinner,sun50i-a64";
|
||||
+};
|
||||
+
|
||||
+&dsi {
|
||||
+ vcc-dsi-supply = <®_dldo1>;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ panel@0 {
|
||||
+ compatible = "feixin,k101-im2ba02";
|
||||
+ reg = <0>;
|
||||
+ avdd-supply = <®_dc1sw>;
|
||||
+ dvdd-supply = <®_dc1sw>;
|
||||
+ cvdd-supply = <®_ldo_io1>;
|
||||
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
+ backlight = <&backlight>;
|
||||
+ };
|
||||
+};
|
||||
--
|
||||
2.25.4
|
||||
|
@ -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,
|
@ -0,0 +1,497 @@
|
||||
--- 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);
|
||||
@@ -1344,8 +1399,16 @@
|
||||
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;
|
||||
+ }
|
||||
|
||||
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
|
||||
- ops->cursor(vc, info, mode, 0, 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;
|
||||
|
@ -0,0 +1,48 @@
|
||||
From 4264c74c96e7907b60ee6ed82670317d19ed7ebe Mon Sep 17 00:00:00 2001
|
||||
From: Edward Vear <edwardvear@gmail.com>
|
||||
Date: Tue, 27 Oct 2020 00:02:03 -0700
|
||||
Subject: Bluetooth: Fix attempting to set RPA timeout when unsupported
|
||||
|
||||
During controller initialization, an LE Set RPA Timeout command is sent
|
||||
to the controller if supported. However, the value checked to determine
|
||||
if the command is supported is incorrect. Page 1921 of the Bluetooth
|
||||
Core Spec v5.2 shows that bit 2 of octet 35 of the Supported_Commands
|
||||
field corresponds to the LE Set RPA Timeout command, but currently
|
||||
bit 6 of octet 35 is checked. This patch checks the correct value
|
||||
instead.
|
||||
|
||||
This issue led to the error seen in the following btmon output during
|
||||
initialization of an adapter (rtl8761b) and prevented initialization
|
||||
from completing.
|
||||
|
||||
< HCI Command: LE Set Resolvable Private Address Timeout (0x08|0x002e) plen 2
|
||||
Timeout: 900 seconds
|
||||
> HCI Event: Command Complete (0x0e) plen 4
|
||||
LE Set Resolvable Private Address Timeout (0x08|0x002e) ncmd 2
|
||||
Status: Unsupported Remote Feature / Unsupported LMP Feature (0x1a)
|
||||
= Close Index: 00:E0:4C:6B:E5:03
|
||||
|
||||
The error did not appear when running with this patch.
|
||||
|
||||
Signed-off-by: Edward Vear <edwardvear@gmail.com>
|
||||
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
|
||||
---
|
||||
net/bluetooth/hci_core.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
|
||||
index be9cdf5dabe5..30a5267af490 100644
|
||||
--- a/net/bluetooth/hci_core.c
|
||||
+++ b/net/bluetooth/hci_core.c
|
||||
@@ -763,7 +763,7 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||
hci_req_add(req, HCI_OP_LE_CLEAR_RESOLV_LIST, 0, NULL);
|
||||
}
|
||||
|
||||
- if (hdev->commands[35] & 0x40) {
|
||||
+ if (hdev->commands[35] & 0x04) {
|
||||
__le16 rpa_timeout = cpu_to_le16(hdev->rpa_timeout);
|
||||
|
||||
/* Set RPA timeout */
|
||||
--
|
||||
cgit v1.2.3-1-gf6bb5
|
||||
|
@ -0,0 +1,40 @@
|
||||
Bluetooth: btusb: Some Qualcomm Bluetooth adapters stop working
|
||||
This issue starts from linux-5.10-rc1, I reproduced this issue on my
|
||||
Dell Inspiron 7447 with BT adapter 0cf3:e005, the kernel will print
|
||||
out: "Bluetooth: hci0: don't support firmware rome 0x31010000", and
|
||||
someone else also reported the similar issue to bugzilla #211571.
|
||||
|
||||
I found this is a regression introduced by 'commit b40f58b97386
|
||||
("Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support"), the
|
||||
patch assumed that if high ROM version is not zero, it is an adapter
|
||||
on WCN6855, but many old adapters don't need to load rampatch or nvm,
|
||||
and they have non-zero high ROM version.
|
||||
|
||||
To fix it, let the driver match the rom_version in the
|
||||
qca_devices_table first, if there is no entry matched, check the
|
||||
high ROM version, if it is not zero, we assume this adapter is ready
|
||||
to work and no need to load rampatch and nvm like previously.
|
||||
|
||||
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=211571
|
||||
Fixes: b40f58b97386 ("Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support")
|
||||
Signed-off-by: Hui Wang <hui.wang@canonical.com>
|
||||
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
|
||||
|
||||
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
||||
index 03b83aa91277..32161dd40ed6 100644
|
||||
--- a/drivers/bluetooth/btusb.c
|
||||
+++ b/drivers/bluetooth/btusb.c
|
||||
@@ -4069,6 +4069,13 @@ static int btusb_setup_qca(struct hci_dev *hdev)
|
||||
info = &qca_devices_table[i];
|
||||
}
|
||||
if (!info) {
|
||||
+ /* If the rom_version is not matched in the qca_devices_table
|
||||
+ * and the high ROM version is not zero, we assume this chip no
|
||||
+ * need to load the rampatch and nvm.
|
||||
+ */
|
||||
+ if (ver_rom & ~0xffffU)
|
||||
+ return 0;
|
||||
+
|
||||
bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
|
||||
return -ENODEV;
|
||||
}
|
66
sys-kernel/pinephone-sources/files/0003-bootsplash.patch
Normal file
66
sys-kernel/pinephone-sources/files/0003-bootsplash.patch
Normal file
@ -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);
|
||||
+ }
|
||||
+}
|
@ -0,0 +1,497 @@
|
||||
--- 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);
|
||||
@@ -1344,8 +1399,16 @@
|
||||
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;
|
||||
+ }
|
||||
|
||||
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
|
||||
- ops->cursor(vc, info, mode, 0, 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;
|
||||
|
215
sys-kernel/pinephone-sources/files/0004-bootsplash.patch
Normal file
215
sys-kernel/pinephone-sources/files/0004-bootsplash.patch
Normal file
@ -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
|
@ -0,0 +1,58 @@
|
||||
From a163474e9b86c2c25f20733385d8b1d6de492a7f Mon Sep 17 00:00:00 2001
|
||||
From: Ard Biesheuvel <ardb@kernel.org>
|
||||
Date: Wed, 25 Nov 2020 08:45:55 +0100
|
||||
Subject: efivarfs: revert "fix memory leak in efivarfs_create()"
|
||||
|
||||
The memory leak addressed by commit fe5186cf12e3 is a false positive:
|
||||
all allocations are recorded in a linked list, and freed when the
|
||||
filesystem is unmounted. This leads to double frees, and as reported
|
||||
by David, leads to crashes if SLUB is configured to self destruct when
|
||||
double frees occur.
|
||||
|
||||
So drop the redundant kfree() again, and instead, mark the offending
|
||||
pointer variable so the allocation is ignored by kmemleak.
|
||||
|
||||
Cc: Vamshi K Sthambamkadi <vamshi.k.sthambamkadi@gmail.com>
|
||||
Fixes: fe5186cf12e3 ("efivarfs: fix memory leak in efivarfs_create()")
|
||||
Reported-by: David Laight <David.Laight@aculab.com>
|
||||
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
|
||||
---
|
||||
fs/efivarfs/inode.c | 2 ++
|
||||
fs/efivarfs/super.c | 1 -
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
|
||||
index 96c0c86f3fff..0297ad95eb5c 100644
|
||||
--- a/fs/efivarfs/inode.c
|
||||
+++ b/fs/efivarfs/inode.c
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/efi.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ctype.h>
|
||||
+#include <linux/kmemleak.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uuid.h>
|
||||
|
||||
@@ -103,6 +104,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
|
||||
var->var.VariableName[i] = '\0';
|
||||
|
||||
inode->i_private = var;
|
||||
+ kmemleak_ignore(var);
|
||||
|
||||
err = efivar_entry_add(var, &efivarfs_list);
|
||||
if (err)
|
||||
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
|
||||
index f943fd0b0699..15880a68faad 100644
|
||||
--- a/fs/efivarfs/super.c
|
||||
+++ b/fs/efivarfs/super.c
|
||||
@@ -21,7 +21,6 @@ LIST_HEAD(efivarfs_list);
|
||||
static void efivarfs_evict_inode(struct inode *inode)
|
||||
{
|
||||
clear_inode(inode);
|
||||
- kfree(inode->i_private);
|
||||
}
|
||||
|
||||
static const struct super_operations efivarfs_ops = {
|
||||
--
|
||||
cgit v1.2.3-1-gf6bb5
|
||||
|
327
sys-kernel/pinephone-sources/files/0005-bootsplash.patch
Normal file
327
sys-kernel/pinephone-sources/files/0005-bootsplash.patch
Normal file
@ -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
|
82
sys-kernel/pinephone-sources/files/0006-bootsplash.patch
Normal file
82
sys-kernel/pinephone-sources/files/0006-bootsplash.patch
Normal file
@ -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()
|
42
sys-kernel/pinephone-sources/files/0007-bootsplash.patch
Normal file
42
sys-kernel/pinephone-sources/files/0007-bootsplash.patch
Normal file
@ -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
|
21
sys-kernel/pinephone-sources/files/0008-bootsplash.patch
Normal file
21
sys-kernel/pinephone-sources/files/0008-bootsplash.patch
Normal file
@ -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,
|
21
sys-kernel/pinephone-sources/files/0009-bootsplash.patch
Normal file
21
sys-kernel/pinephone-sources/files/0009-bootsplash.patch
Normal file
@ -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)
|
321
sys-kernel/pinephone-sources/files/0010-bootsplash.patch
Normal file
321
sys-kernel/pinephone-sources/files/0010-bootsplash.patch
Normal file
@ -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
|
@ -0,0 +1,56 @@
|
||||
From 05044b9e4e4ae03f66e1c504d6fef57a1d135897 Mon Sep 17 00:00:00 2001
|
||||
From: Dylan Van Assche <me@dylanvanassche.be>
|
||||
Date: Thu, 24 Dec 2020 19:57:12 +0100
|
||||
Subject: [PATCH] dts: pinephone: Add 'pine64,pinephone' to compat list
|
||||
|
||||
Indicates that all PinePhone models share most of the hardware with each other.
|
||||
Used for feedbackd configuration when retrieving a device specific config for
|
||||
haptic feedbackd.
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts | 2 +-
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts | 2 +-
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
index 0f6faa44c..2e0892b32 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/ {
|
||||
model = "Pine64 PinePhone Developer Batch (1.0)";
|
||||
- compatible = "pine64,pinephone-1.0", "allwinner,sun50i-a64";
|
||||
+ compatible = "pine64,pinephone-1.0", "pine64,pinephone", "allwinner,sun50i-a64";
|
||||
|
||||
reg_vbus: usb0-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
index 95a880fdc..d6bad0838 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/ {
|
||||
model = "Pine64 PinePhone Braveheart (1.1)";
|
||||
- compatible = "pine64,pinephone-1.1", "allwinner,sun50i-a64";
|
||||
+ compatible = "pine64,pinephone-1.1", "pine64,pinephone", "allwinner,sun50i-a64";
|
||||
|
||||
reg_vbus: usb0-vbus {
|
||||
compatible = "regulator-fixed";
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
index 23ba72508..710493186 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/ {
|
||||
model = "Pine64 PinePhone (1.2)";
|
||||
- compatible = "pine64,pinephone-1.2", "allwinner,sun50i-a64";
|
||||
+ compatible = "pine64,pinephone-1.2", "pine64,pinephone", "allwinner,sun50i-a64";
|
||||
|
||||
wifi_pwrseq: wifi-pwrseq {
|
||||
compatible = "mmc-pwrseq-simple";
|
||||
--
|
||||
2.26.2
|
||||
|
129
sys-kernel/pinephone-sources/files/0011-bootsplash.patch
Normal file
129
sys-kernel/pinephone-sources/files/0011-bootsplash.patch
Normal file
@ -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
|
||||
};
|
||||
|
@ -0,0 +1,29 @@
|
||||
From c965cb8a004c6cc370b4bf297c61fe5ac8ab0583 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Braam <martijn@brixit.nl>
|
||||
Date: Wed, 6 Jan 2021 03:11:17 +0100
|
||||
Subject: [PATCH] arm64: dts: sunxi: Add mmc aliases for the PineTab
|
||||
|
||||
The order for the mmc devices changed in the kernel without this change.
|
||||
|
||||
Signed-off-by: Martijn Braam <martijn@brixit.nl>
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
index a87790df94b3..1cf3c3a9ad7f 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
@@ -18,6 +18,9 @@ / {
|
||||
compatible = "pine64,pinetab", "allwinner,sun50i-a64";
|
||||
|
||||
aliases {
|
||||
+ mmc0 = &mmc0;
|
||||
+ mmc1 = &mmc1;
|
||||
+ mmc2 = &mmc2;
|
||||
serial0 = &uart0;
|
||||
ethernet0 = &rtl8723cs;
|
||||
};
|
||||
--
|
||||
2.29.2
|
||||
|
511
sys-kernel/pinephone-sources/files/0012-bootsplash.patch
Normal file
511
sys-kernel/pinephone-sources/files/0012-bootsplash.patch
Normal file
@ -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;
|
||||
+}
|
@ -0,0 +1,29 @@
|
||||
From d753557c64f6e85f63cffab53496d6271d724074 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Braam <martijn@brixit.nl>
|
||||
Date: Mon, 15 Feb 2021 13:10:37 -0800
|
||||
Subject: [PATCH] pinephone: fix pogopin i2c
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 6 +-----
|
||||
1 file changed, 1 insertion(+), 5 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 39fdf96fe95d..7d0dd52e2f9d 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -635,11 +635,7 @@ &pio {
|
||||
vcc-pb-supply = <®_dcdc1>;
|
||||
vcc-pc-supply = <®_dcdc1>;
|
||||
vcc-pd-supply = <®_dcdc1>;
|
||||
- /* pinctrl would enable this even if no camera is powered,
|
||||
- * which is wrong/not necessary
|
||||
- *
|
||||
- * vcc-pe-supply = <®_aldo1>; (also used by pogo pins i2c)
|
||||
- */
|
||||
+ vcc-pe-supply = <®_aldo1>; /* (also used by pogo pins i2c) */
|
||||
vcc-pf-supply = <®_dcdc1>;
|
||||
vcc-pg-supply = <®_dldo4>;
|
||||
vcc-ph-supply = <®_dcdc1>;
|
||||
--
|
||||
2.30.1
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
From cb408fb65a08bd45543724c1e9b8f38ae1bebc4a Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
|
||||
Date: Tue, 4 Aug 2020 15:12:59 +0200
|
||||
Subject: [PATCH 177/183] leds-gpio: make max_brightness configurable
|
||||
|
||||
---
|
||||
drivers/leds/leds-gpio.c | 4 ++++
|
||||
include/linux/leds.h | 3 ++-
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
|
||||
index 93f5b1b60fde..f8483fab1164 100644
|
||||
--- a/drivers/leds/leds-gpio.c
|
||||
+++ b/drivers/leds/leds-gpio.c
|
||||
@@ -108,6 +108,8 @@ static int create_gpio_led(const struct gpio_led *template,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
+ led_dat->cdev.max_brightness = template->max_brightness;
|
||||
+
|
||||
if (template->name) {
|
||||
led_dat->cdev.name = template->name;
|
||||
ret = devm_led_classdev_register(parent, &led_dat->cdev);
|
||||
@@ -177,6 +179,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
|
||||
if (fwnode_property_present(child, "panic-indicator"))
|
||||
led.panic_indicator = 1;
|
||||
|
||||
+ fwnode_property_read_u32(child, "max-brightness", &led.max_brightness);
|
||||
+
|
||||
ret = create_gpio_led(&led, led_dat, dev, child, NULL);
|
||||
if (ret < 0) {
|
||||
fwnode_handle_put(child);
|
||||
diff --git a/include/linux/leds.h b/include/linux/leds.h
|
||||
index 6a8d6409c993..99a80092114d 100644
|
||||
--- a/include/linux/leds.h
|
||||
+++ b/include/linux/leds.h
|
||||
@@ -513,7 +513,8 @@ typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
|
||||
struct gpio_led {
|
||||
const char *name;
|
||||
const char *default_trigger;
|
||||
- unsigned gpio;
|
||||
+ unsigned gpio;
|
||||
+ unsigned max_brightness;
|
||||
unsigned active_low : 1;
|
||||
unsigned retain_state_suspended : 1;
|
||||
unsigned panic_indicator : 1;
|
||||
--
|
||||
2.30.0
|
||||
|
@ -0,0 +1,25 @@
|
||||
From 2253c0d31cf17debb97db418bec21ad59cd47c14 Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
Date: Tue, 3 Nov 2020 17:04:35 +0100
|
||||
Subject: [PATCH 178/183] sun8i-codec: fix headphone jack pin name
|
||||
|
||||
---
|
||||
sound/soc/sunxi/sun8i-codec.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
|
||||
index 6128d861df90..ab751fd7c426 100644
|
||||
--- a/sound/soc/sunxi/sun8i-codec.c
|
||||
+++ b/sound/soc/sunxi/sun8i-codec.c
|
||||
@@ -1272,7 +1272,7 @@ static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = {
|
||||
|
||||
static struct snd_soc_jack_pin sun8i_codec_jack_pins[] = {
|
||||
{
|
||||
- .pin = "Headphone Jack",
|
||||
+ .pin = "Headphone",
|
||||
.mask = SND_JACK_HEADPHONE,
|
||||
},
|
||||
{
|
||||
--
|
||||
2.30.0
|
||||
|
@ -0,0 +1,130 @@
|
||||
From 465a75a727ae5eb4c94859bfac4742cb14e38b3e Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
Date: Fri, 3 Apr 2020 17:13:55 +0200
|
||||
Subject: [PATCH 179/183] arm64: dts: allwinner: pinephone: improve device tree
|
||||
|
||||
On PinePhone, the headset mic bias resistor isn't populated on the
|
||||
schematics (R811), therefore we need to enable the codec's internal
|
||||
resistor. Additionnally, the jack detection IRQ's are inverted due to the
|
||||
connector wiring, so the necessary property is added to the codec node
|
||||
to made the driver aware of this fact.
|
||||
|
||||
We also stop LEDs during suspend to improve battery life, lower
|
||||
cpu_alert* temperatures so the phone doesn't get too hot and improve the
|
||||
backlight brightness values so we have a wider usable range.
|
||||
|
||||
Finally, the RGB LED max_brightness is set to 1 as it isn't using a PWM
|
||||
output.
|
||||
---
|
||||
.../dts/allwinner/sun50i-a64-pinephone-1.1.dts | 10 +++++-----
|
||||
.../dts/allwinner/sun50i-a64-pinephone-1.2.dts | 13 ++++++-------
|
||||
.../dts/allwinner/sun50i-a64-pinephone.dtsi | 18 +++++++++++++-----
|
||||
3 files changed, 24 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
index f084c4f21f12..573f1929da4f 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
@@ -29,11 +29,11 @@ &backlight {
|
||||
* value here was chosen as a safe default.
|
||||
*/
|
||||
brightness-levels = <
|
||||
- 774 793 814 842
|
||||
- 882 935 1003 1088
|
||||
- 1192 1316 1462 1633
|
||||
- 1830 2054 2309 2596
|
||||
- 2916 3271 3664 4096>;
|
||||
+ 392 413 436 468
|
||||
+ 512 571 647 742
|
||||
+ 857 995 1159 1349
|
||||
+ 1568 1819 2103 2423
|
||||
+ 2779 3176 3614 4096>;
|
||||
num-interpolated-steps = <50>;
|
||||
default-brightness-level = <400>;
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
index bbf64677c22b..6c3922543fec 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
@@ -34,14 +34,13 @@ &backlight {
|
||||
* chosen as a safe default.
|
||||
*/
|
||||
brightness-levels = <
|
||||
- 5000 5248 5506 5858 6345
|
||||
- 6987 7805 8823 10062 11543
|
||||
- 13287 15317 17654 20319 23336
|
||||
- 26724 30505 34702 39335 44427
|
||||
- 50000
|
||||
- >;
|
||||
+ 392 413 436 468
|
||||
+ 512 571 647 742
|
||||
+ 857 995 1159 1349
|
||||
+ 1568 1819 2103 2423
|
||||
+ 2779 3176 3614 4096>;
|
||||
num-interpolated-steps = <50>;
|
||||
- default-brightness-level = <500>;
|
||||
+ default-brightness-level = <400>;
|
||||
};
|
||||
|
||||
&lis3mdl {
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index c55709197804..441358592072 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -80,21 +80,21 @@ blue {
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
|
||||
- retain-state-suspended;
|
||||
+ max-brightness = <1>;
|
||||
};
|
||||
|
||||
green {
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
gpios = <&pio 3 18 GPIO_ACTIVE_HIGH>; /* PD18 */
|
||||
- retain-state-suspended;
|
||||
+ max-brightness = <1>;
|
||||
};
|
||||
|
||||
red {
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
|
||||
- retain-state-suspended;
|
||||
+ max-brightness = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -198,6 +198,14 @@ &cpu3 {
|
||||
cpu-supply = <®_dcdc2>;
|
||||
};
|
||||
|
||||
+&cpu_alert0 {
|
||||
+ temperature = <60000>;
|
||||
+};
|
||||
+
|
||||
+&cpu_alert1 {
|
||||
+ temperature = <80000>;
|
||||
+};
|
||||
+
|
||||
&csi {
|
||||
pinctrl-0 = <&csi_pins>, <&csi_mclk_pin>;
|
||||
status = "okay";
|
||||
@@ -671,11 +679,11 @@ &sound {
|
||||
simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>;
|
||||
simple-audio-card,widgets = "Microphone", "Headset Microphone",
|
||||
"Microphone", "Internal Microphone",
|
||||
- "Headphone", "Headphone Jack",
|
||||
+ "Headphone", "Headphone",
|
||||
"Speaker", "Internal Earpiece",
|
||||
"Speaker", "Internal Speaker";
|
||||
simple-audio-card,routing =
|
||||
- "Headphone Jack", "HP",
|
||||
+ "Headphone", "HP",
|
||||
"Internal Earpiece", "EARPIECE",
|
||||
"Internal Speaker", "Speaker Amp OUTL",
|
||||
"Internal Speaker", "Speaker Amp OUTR",
|
||||
--
|
||||
2.30.0
|
||||
|
31655
sys-kernel/pinephone-sources/files/5.11.3.patch
Normal file
31655
sys-kernel/pinephone-sources/files/5.11.3.patch
Normal file
File diff suppressed because it is too large
Load Diff
1526
sys-kernel/pinephone-sources/files/5.11.5.patch
Normal file
1526
sys-kernel/pinephone-sources/files/5.11.5.patch
Normal file
File diff suppressed because it is too large
Load Diff
12
sys-kernel/pinephone-sources/files/60-linux.hook
Normal file
12
sys-kernel/pinephone-sources/files/60-linux.hook
Normal file
@ -0,0 +1,12 @@
|
||||
[Trigger]
|
||||
Type = File
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Operation = Remove
|
||||
Target = usr/lib/modules/%KERNVER%/*
|
||||
Target = usr/lib/modules/%EXTRAMODULES%/*
|
||||
|
||||
[Action]
|
||||
Description = Updating %PKGBASE% module dependencies...
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/depmod %KERNVER%
|
11
sys-kernel/pinephone-sources/files/90-linux.hook
Normal file
11
sys-kernel/pinephone-sources/files/90-linux.hook
Normal file
@ -0,0 +1,11 @@
|
||||
[Trigger]
|
||||
Type = File
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Target = boot/Image
|
||||
Target = usr/lib/initcpio/*
|
||||
|
||||
[Action]
|
||||
Description = Updating %PKGBASE% initcpios...
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/mkinitcpio -p %PKGBASE%
|
@ -0,0 +1,118 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
|
||||
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
|
||||
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,
|
||||
MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
|
||||
autolearn_force=no version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 30CB3C433DB
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id F053961971
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S230259AbhC0NGA (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:00 -0400
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59650 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S229582AbhC0NFz (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:05:55 -0400
|
||||
Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DAA2C0613B1
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:05:55 -0700 (PDT)
|
||||
Received: by mail-pf1-x435.google.com with SMTP id j25so6773824pfe.2
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:05:55 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=gmail.com; s=20161025;
|
||||
h=from:to:cc:subject:date:message-id:mime-version
|
||||
:content-transfer-encoding;
|
||||
bh=j1vEagJw59z7NUkgTmJto/iZqe4yWAoKFE4cIPL6KSA=;
|
||||
b=W++BsAIwl+3ucDDq6J9gfd2LQIPwdj2biEakUpnxpy/YsK+3iCoF33X3sftQWOxfP7
|
||||
IPnjeO9Rde2kHHrwJMlMu2vkeccABUo1mLD6uTVGrEfxwUsN9YJWo9jUzaSY3cyvbGI2
|
||||
ehpcqqnKgU3Fn5s/X8mIRCamioqbkc4WM23kxCZTaHn+XhPN+SWL6FLKRXDgGS2ivbn1
|
||||
OER7kHG7/pVx6TS91PpzwDFvN3Rnt6x9672uUa2Evpoapzy9P2POwsDV4zxWpGjlEc44
|
||||
x99r44072+JXwATmacsPj8yOAksyAgxYYzYtUqJdpS51qpCmDWMBwE12Glc6HXWJKDrZ
|
||||
V2jw==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version
|
||||
:content-transfer-encoding;
|
||||
bh=j1vEagJw59z7NUkgTmJto/iZqe4yWAoKFE4cIPL6KSA=;
|
||||
b=kBUfAu8SPEqgcOJWgnRXoXkAISBVy5hrC8mdP43B3bJdOtUy3ckGem52OQlxU4JiZ9
|
||||
fRLzgQhtoaEPJwBegty5xhiBi7a9Z8jtP5y9BGPLtHnPY0vj7Q5WoLeJW8VQSdnTfIea
|
||||
LWI0QFW1FPejnWt1OkpKrg23YuIwnAy4JeS4ppYqwxoJLaA2CK49uIgHZvkO/KUWTZ1u
|
||||
H4FTpR1COt4JDajdNEO9PXbgAIn7Zhc84m4BrHeFhPPMguGgiORNl8CiVYnEidYMOYB4
|
||||
xKZysxTMak3CltRje+eBSpYQa9T1mcAv1kMsc7OY2YJYnK7TadU5FcwBnEGYEGtI6pK9
|
||||
kbyg==
|
||||
X-Gm-Message-State: AOAM531ZZkAzAjwe4lLioYqlb3vcaxOF8kBIHnAElR+v7R84d5htjzCI
|
||||
w2CjFLBp7ZYpGnOW93HhwfMMXbvyGk6rb63y
|
||||
X-Google-Smtp-Source: ABdhPJwtfu5Tfa4UYXfW8whmzPPLMc8XbemaxfI6PdBR3nuuwqL4rugT9FibIaSdi/j6K0J4cIJCqg==
|
||||
X-Received: by 2002:a63:e906:: with SMTP id i6mr16394983pgh.132.1616850352891;
|
||||
Sat, 27 Mar 2021 06:05:52 -0700 (PDT)
|
||||
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
|
||||
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.05.51
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Sat, 27 Mar 2021 06:05:52 -0700 (PDT)
|
||||
From: John Chen <johnchen902@gmail.com>
|
||||
To: linux-kernel@vger.kernel.org
|
||||
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
|
||||
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
|
||||
Jiri Kosina <jikos@kernel.org>,
|
||||
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
|
||||
John Chen <johnchen902@gmail.com>
|
||||
Subject: [PATCH 0/4] HID: add Apple Magic Mouse 2 support
|
||||
Date: Sat, 27 Mar 2021 21:05:04 +0800
|
||||
Message-Id: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
X-Mailer: git-send-email 2.31.0
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-1-johnchen902@gmail.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
The HID descriptor of Magic Mouse 2 contains BTN_LEFT, BTN_RIGHT, REL_X,
|
||||
REL_Y, whether it's charging, whether it's fully charged, and battery
|
||||
capacity.
|
||||
|
||||
$ xxd -p report_descriptor
|
||||
05010902a101851205091901290215002501950275018102950175068103
|
||||
05010901a1001601f826ff073601fb46ff046513550d0930093175109502
|
||||
8106750895028101c00602ff09558555150026ff0075089540b1a2c00600
|
||||
ff0914a10185900584750195031500250109610585094409468102950581
|
||||
0175089501150026ff0009658102c000
|
||||
|
||||
As hidinput can handle the BTNs and RELs, the Magic Mouse 2 already
|
||||
functions as a basic mouse. Nevertheless, It should be reasonable to
|
||||
extend hid-magicmouse to support Magic Mouse 2 as well. Furthermore,
|
||||
hidinput is patched to handle the battery capacity.
|
||||
|
||||
This work is based on Recardo's, which is in turned based on Rohitpid's.
|
||||
Their GitHub repositories are linked below:
|
||||
https://github.com/RicardoEPRodrigues/magicmouse-hid
|
||||
https://github.com/rohitpid/Linux-Magic-Trackpad-2-Driver
|
||||
|
||||
John Chen (4):
|
||||
HID: magicmouse: add Apple Magic Mouse 2 support
|
||||
HID: magicmouse: fix 3 button emulation of Mouse 2
|
||||
HID: magicmouse: fix reconnection of Magic Mouse 2
|
||||
HID: input: map battery capacity (00850065)
|
||||
|
||||
drivers/hid/hid-debug.c | 1 +
|
||||
drivers/hid/hid-ids.h | 1 +
|
||||
drivers/hid/hid-input.c | 11 +++
|
||||
drivers/hid/hid-magicmouse.c | 156 ++++++++++++++++++++++++++++-------
|
||||
include/linux/hid.h | 3 +
|
||||
5 files changed, 140 insertions(+), 32 deletions(-)
|
||||
|
||||
--
|
||||
2.31.0
|
||||
|
||||
|
@ -0,0 +1,247 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
|
||||
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
|
||||
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
|
||||
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
|
||||
autolearn_force=no version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 4888EC433C1
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 0E6E861981
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S230295AbhC0NGh (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:37 -0400
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59740 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S229582AbhC0NGT (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:19 -0400
|
||||
Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 82262C0613B1
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:19 -0700 (PDT)
|
||||
Received: by mail-pg1-x529.google.com with SMTP id v10so6405578pgs.12
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:19 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=gmail.com; s=20161025;
|
||||
h=from:to:cc:subject:date:message-id:in-reply-to:references
|
||||
:mime-version:content-transfer-encoding;
|
||||
bh=/43es5lmfTvSMg9V9lh/7OQVghMj1iNxFqwqD88gyCk=;
|
||||
b=JA8+yZao+x/DmyoiRUpwr0wP9XgaNgDVez40dXm+yEd6Wlgs1dQvO3DkU8n7trJWcL
|
||||
TCj7NqBp0z4pf3pSHrTxX7rWZX4yRyZJAXo7fqTPqfN2R0PkRIp5gnvcDv+7/BRM4nqx
|
||||
3pI6ubgKZ+rxYph8XNAuO94/oOjxgItIhOqYGbLPHwa2eoI60mUbrF/ukBsw8OwQ+Vli
|
||||
0siGyaoTCPP/h+9uuHJqQJ1yw6CCkCAxMwZXD79abtLytL6WkhuvoFJ6exRYGHawcHMs
|
||||
bel32ifzIlv+7ULbcTI2uVNhxvdrD51tRSNrAZ77n+Tk8RivXMeSqSzPVngWZCs0uk6s
|
||||
JryA==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
|
||||
:references:mime-version:content-transfer-encoding;
|
||||
bh=/43es5lmfTvSMg9V9lh/7OQVghMj1iNxFqwqD88gyCk=;
|
||||
b=fAhjI90TZfQpcQBqM4rN69d8uN92OH3j+lhm/dYYlmqdchK6ZZsPD3wt6VW8/ObU+0
|
||||
BpTic3inOmn0aVasSmAkbNxaVAUJ339klb/WnO9RfaemBLXDCBMgGjVr+ofhpIbfKxiZ
|
||||
0aBswW4Dc2uY39zmxm7wtJ2sRHHwj/Ltdt7B+NYes7Kzohvfg98YLvm8I5mloimR02U9
|
||||
HRlPKK2YbMcZ5i2Y8Q3faX8356caUUU7l91utK4EXdrVFCbNftXBEmRej6gXSZudCBga
|
||||
7w6Rgymaox0hfMZzYLWtJJp2fo3BcKA4+TD6bJ1yrxIdPmK59QMGoyMUIKqTIZIjN2c/
|
||||
gvpg==
|
||||
X-Gm-Message-State: AOAM531lA6V8bOmQPsuLmZx3iv59gcixbI4HEH5eqWzOJ/N3DRaX/hb9
|
||||
NavPhvckezEkR22O7uWWvZAUxOplQlRwSsX5
|
||||
X-Google-Smtp-Source: ABdhPJyaSIYZWu4pp8j7TnxkxYd0BP77HzgDaIZFIDeoL910Tkv+L4VuoQLEw0GNu+5Zxi80enV/YQ==
|
||||
X-Received: by 2002:a65:498b:: with SMTP id r11mr16491362pgs.364.1616850378733;
|
||||
Sat, 27 Mar 2021 06:06:18 -0700 (PDT)
|
||||
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
|
||||
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.17
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Sat, 27 Mar 2021 06:06:18 -0700 (PDT)
|
||||
From: John Chen <johnchen902@gmail.com>
|
||||
To: linux-kernel@vger.kernel.org
|
||||
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
|
||||
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
|
||||
Jiri Kosina <jikos@kernel.org>,
|
||||
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
|
||||
John Chen <johnchen902@gmail.com>
|
||||
Subject: [PATCH 1/4] HID: magicmouse: add Apple Magic Mouse 2 support
|
||||
Date: Sat, 27 Mar 2021 21:05:05 +0800
|
||||
Message-Id: <20210327130508.24849-2-johnchen902@gmail.com>
|
||||
X-Mailer: git-send-email 2.31.0
|
||||
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
References: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-2-johnchen902@gmail.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Bluetooth device
|
||||
Vendor 004c (Apple)
|
||||
Device 0269 (Magic Mouse 2)
|
||||
|
||||
Add support for Apple Magic Mouse 2, putting the device in multi-touch
|
||||
mode.
|
||||
|
||||
Co-authored-by: Rohit Pidaparthi <rohitpid@gmail.com>
|
||||
Co-authored-by: RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>
|
||||
Signed-off-by: John Chen <johnchen902@gmail.com>
|
||||
---
|
||||
drivers/hid/hid-ids.h | 1 +
|
||||
drivers/hid/hid-magicmouse.c | 53 ++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 49 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||||
index e42aaae3138f..fa0edf03570a 100644
|
||||
--- a/drivers/hid/hid-ids.h
|
||||
+++ b/drivers/hid/hid-ids.h
|
||||
@@ -93,6 +93,7 @@
|
||||
#define BT_VENDOR_ID_APPLE 0x004c
|
||||
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
|
||||
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
|
||||
+#define USB_DEVICE_ID_APPLE_MAGICMOUSE2 0x0269
|
||||
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e
|
||||
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265
|
||||
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
|
||||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
||||
index abd86903875f..7aad6ca56780 100644
|
||||
--- a/drivers/hid/hid-magicmouse.c
|
||||
+++ b/drivers/hid/hid-magicmouse.c
|
||||
@@ -54,6 +54,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
|
||||
#define TRACKPAD2_USB_REPORT_ID 0x02
|
||||
#define TRACKPAD2_BT_REPORT_ID 0x31
|
||||
#define MOUSE_REPORT_ID 0x29
|
||||
+#define MOUSE2_REPORT_ID 0x12
|
||||
#define DOUBLE_REPORT_ID 0xf7
|
||||
/* These definitions are not precise, but they're close enough. (Bits
|
||||
* 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
|
||||
@@ -195,7 +196,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
|
||||
int id, x, y, size, orientation, touch_major, touch_minor, state, down;
|
||||
int pressure = 0;
|
||||
|
||||
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
|
||||
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
|
||||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf;
|
||||
x = (tdata[1] << 28 | tdata[0] << 20) >> 20;
|
||||
y = -((tdata[2] << 24 | tdata[1] << 16) >> 20);
|
||||
@@ -296,7 +298,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
|
||||
input_report_abs(input, ABS_MT_PRESSURE, pressure);
|
||||
|
||||
if (report_undeciphered) {
|
||||
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
|
||||
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
|
||||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2)
|
||||
input_event(input, EV_MSC, MSC_RAW, tdata[7]);
|
||||
else if (input->id.product !=
|
||||
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2)
|
||||
@@ -380,6 +383,34 @@ static int magicmouse_raw_event(struct hid_device *hdev,
|
||||
* ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
|
||||
*/
|
||||
break;
|
||||
+ case MOUSE2_REPORT_ID:
|
||||
+ /* Size is either 8 or (14 + 8 * N) */
|
||||
+ if (size != 8 && (size < 14 || (size - 14) % 8 != 0))
|
||||
+ return 0;
|
||||
+ npoints = (size - 14) / 8;
|
||||
+ if (npoints > 15) {
|
||||
+ hid_warn(hdev, "invalid size value (%d) for MOUSE2_REPORT_ID\n",
|
||||
+ size);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ msc->ntouches = 0;
|
||||
+ for (ii = 0; ii < npoints; ii++)
|
||||
+ magicmouse_emit_touch(msc, ii, data + ii * 8 + 14);
|
||||
+
|
||||
+ /* When emulating three-button mode, it is important
|
||||
+ * to have the current touch information before
|
||||
+ * generating a click event.
|
||||
+ */
|
||||
+ x = (int)((data[3] << 24) | (data[2] << 16)) >> 16;
|
||||
+ y = (int)((data[5] << 24) | (data[4] << 16)) >> 16;
|
||||
+ clicks = data[1];
|
||||
+
|
||||
+ /* The following bits provide a device specific timestamp. They
|
||||
+ * are unused here.
|
||||
+ *
|
||||
+ * ts = data[11] >> 6 | data[12] << 2 | data[13] << 10;
|
||||
+ */
|
||||
+ break;
|
||||
case DOUBLE_REPORT_ID:
|
||||
/* Sometimes the trackpad sends two touch reports in one
|
||||
* packet.
|
||||
@@ -392,7 +423,8 @@ static int magicmouse_raw_event(struct hid_device *hdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
|
||||
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
|
||||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
magicmouse_emit_buttons(msc, clicks & 3);
|
||||
input_report_rel(input, REL_X, x);
|
||||
input_report_rel(input, REL_Y, y);
|
||||
@@ -415,7 +447,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
|
||||
|
||||
__set_bit(EV_KEY, input->evbit);
|
||||
|
||||
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
|
||||
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
|
||||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
__set_bit(BTN_LEFT, input->keybit);
|
||||
__set_bit(BTN_RIGHT, input->keybit);
|
||||
if (emulate_3button)
|
||||
@@ -480,7 +513,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
|
||||
* the origin at the same position, and just uses the additive
|
||||
* inverse of the reported Y.
|
||||
*/
|
||||
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
|
||||
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
|
||||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X,
|
||||
MOUSE_MIN_X, MOUSE_MAX_X, 4, 0);
|
||||
@@ -586,6 +620,7 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
{
|
||||
const u8 *feature;
|
||||
const u8 feature_mt[] = { 0xD7, 0x01 };
|
||||
+ const u8 feature_mt_mouse2[] = { 0xF1, 0x02, 0x01 };
|
||||
const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 };
|
||||
const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 };
|
||||
u8 *buf;
|
||||
@@ -631,6 +666,9 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
|
||||
report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
MOUSE_REPORT_ID, 0);
|
||||
+ else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2)
|
||||
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
+ MOUSE2_REPORT_ID, 0);
|
||||
else if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
|
||||
if (id->vendor == BT_VENDOR_ID_APPLE)
|
||||
report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
@@ -660,6 +698,9 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
feature_size = sizeof(feature_mt_trackpad2_usb);
|
||||
feature = feature_mt_trackpad2_usb;
|
||||
}
|
||||
+ } else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
+ feature_size = sizeof(feature_mt_mouse2);
|
||||
+ feature = feature_mt_mouse2;
|
||||
} else {
|
||||
feature_size = sizeof(feature_mt);
|
||||
feature = feature_mt;
|
||||
@@ -696,6 +737,8 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
static const struct hid_device_id magic_mice[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
|
||||
+ { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 },
|
||||
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
|
||||
--
|
||||
2.31.0
|
||||
|
||||
|
@ -0,0 +1,134 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
|
||||
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
|
||||
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
|
||||
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
|
||||
autolearn_force=no version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 06C18C433E1
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:08 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id D1CE16193D
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S230328AbhC0NGi (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:38 -0400
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59770 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S230266AbhC0NG1 (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:27 -0400
|
||||
Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5086BC0613B1
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:27 -0700 (PDT)
|
||||
Received: by mail-pl1-x634.google.com with SMTP id h8so2235029plt.7
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:27 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=gmail.com; s=20161025;
|
||||
h=from:to:cc:subject:date:message-id:in-reply-to:references
|
||||
:mime-version:content-transfer-encoding;
|
||||
bh=NeWUvZBV3NAy1b0eckELIbBZ7sti/n1sLYnD4r2cjaU=;
|
||||
b=V7uM0AaI1Vy/mmqpuTVu5F6+98YPDzOa3QS6tRkWeJqhrflMONfCXtOxXVR+CeiPil
|
||||
OOfaxOtAMeVEW9wE0EU3U/8aNghtzuUvVN+0Tj57+W+4g0ilQOODiDLDu4ZqAo1Q5eDZ
|
||||
gA+He13KWVwNYaYTNUNParLXG5GYDbblaqABSUDurI1FTjn1US0ZZytlzdZy1GfL9eTj
|
||||
6AiiVM3A4YdUGUWE7qQQE8jI92o4qKYvaNjn1M+d5ypKCue3NJWeRTSPKLu0QD2qL02+
|
||||
QPga2RPtmLpztA8/lPGTRpgVNY3C5jdCBZyWgFtvZg5dNoDfe5bQnAmF2J2ka+A7JBSD
|
||||
VHtw==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
|
||||
:references:mime-version:content-transfer-encoding;
|
||||
bh=NeWUvZBV3NAy1b0eckELIbBZ7sti/n1sLYnD4r2cjaU=;
|
||||
b=OQek2lJ5JINezfYdN/FzSPFL1N9Hrs+KstU7K4gEHavdffvSAOBebg2MG5VSzkf93H
|
||||
o1iOiAOoXY7cx7j7Vx5CFZUuJOLilpC6gPTJpZlaP8YtEFfGkPaUPPh5FSTyM463Sir8
|
||||
n6DupTSrFUI1y44GOBZ2bM2pf9hRN1Yj1oiCT6upmfoHw0/PaKEZt5aOEI8se7HRJp94
|
||||
td6+SEZok3uxKEglKEqAG8cnj7Pt4tKVQlg+MI1AQDLQ/ytdYJlMPmrqVyNpnsv44wYa
|
||||
dxBf0TaMvqn9SYDIDcGct3toAVm5DfVUqXm1nkYcYMOdvPrmLoH52NtCyi5cYC+2TR6i
|
||||
jUpA==
|
||||
X-Gm-Message-State: AOAM532sXgN0NNpKjilSMBewUXwwXz+MOfd7J5FRI6zAWA5st7gy5LmE
|
||||
Sw/QHj4cm3zT07LU1kWYSO9puwFV+yK0Hquf
|
||||
X-Google-Smtp-Source: ABdhPJyDnhcP7BeBHXX2rPqMXwkOQiZdussDPATmYqyQnp7HAsi0OqWSUVIloMNi3QBpMsmjXTtyew==
|
||||
X-Received: by 2002:a17:903:2285:b029:e6:faf5:eaff with SMTP id b5-20020a1709032285b02900e6faf5eaffmr19574014plh.70.1616850386727;
|
||||
Sat, 27 Mar 2021 06:06:26 -0700 (PDT)
|
||||
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
|
||||
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.25
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Sat, 27 Mar 2021 06:06:26 -0700 (PDT)
|
||||
From: John Chen <johnchen902@gmail.com>
|
||||
To: linux-kernel@vger.kernel.org
|
||||
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
|
||||
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
|
||||
Jiri Kosina <jikos@kernel.org>,
|
||||
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
|
||||
John Chen <johnchen902@gmail.com>
|
||||
Subject: [PATCH 2/4] HID: magicmouse: fix 3 button emulation of Mouse 2
|
||||
Date: Sat, 27 Mar 2021 21:05:06 +0800
|
||||
Message-Id: <20210327130508.24849-3-johnchen902@gmail.com>
|
||||
X-Mailer: git-send-email 2.31.0
|
||||
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
References: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-3-johnchen902@gmail.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
It is observed that, with 3 button emulation, when middle button is
|
||||
clicked, either the left button or right button is clicked as well. It
|
||||
is caused by hidinput "correctly" acting on the event, oblivious to the
|
||||
3 button emulation.
|
||||
|
||||
As raw_event has taken care of everything, no further processing is
|
||||
needed. However, the only way to stop at raw_event is to return an error
|
||||
(negative) value. Therefore, the processing is stopped at event instead.
|
||||
|
||||
Signed-off-by: John Chen <johnchen902@gmail.com>
|
||||
---
|
||||
drivers/hid/hid-magicmouse.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
||||
index 7aad6ca56780..c646b4cd3783 100644
|
||||
--- a/drivers/hid/hid-magicmouse.c
|
||||
+++ b/drivers/hid/hid-magicmouse.c
|
||||
@@ -440,6 +440,21 @@ static int magicmouse_raw_event(struct hid_device *hdev,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
|
||||
+ struct hid_usage *usage, __s32 value)
|
||||
+{
|
||||
+ struct magicmouse_sc *msc = hid_get_drvdata(hdev);
|
||||
+ if (msc->input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 &&
|
||||
+ field->report->id == MOUSE2_REPORT_ID) {
|
||||
+ // magic_mouse_raw_event has done all the work. Skip hidinput.
|
||||
+ //
|
||||
+ // Specifically, hidinput may modify BTN_LEFT and BTN_RIGHT,
|
||||
+ // breaking emulate_3button.
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev)
|
||||
{
|
||||
int error;
|
||||
@@ -754,6 +769,7 @@ static struct hid_driver magicmouse_driver = {
|
||||
.id_table = magic_mice,
|
||||
.probe = magicmouse_probe,
|
||||
.raw_event = magicmouse_raw_event,
|
||||
+ .event = magicmouse_event,
|
||||
.input_mapping = magicmouse_input_mapping,
|
||||
.input_configured = magicmouse_input_configured,
|
||||
};
|
||||
--
|
||||
2.31.0
|
||||
|
||||
|
@ -0,0 +1,265 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
|
||||
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
|
||||
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
|
||||
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
|
||||
autolearn_force=no version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 9A212C433DB
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 60FCC61981
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S230394AbhC0NHJ (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:07:09 -0400
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59810 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S230307AbhC0NGi (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:38 -0400
|
||||
Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1EDFCC0613B1
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:38 -0700 (PDT)
|
||||
Received: by mail-pf1-x432.google.com with SMTP id q5so6741894pfh.10
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:38 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=gmail.com; s=20161025;
|
||||
h=from:to:cc:subject:date:message-id:in-reply-to:references
|
||||
:mime-version:content-transfer-encoding;
|
||||
bh=fWEWnDB7IS15Aoqul4RZDergwEtbUe4NAH8lKjv7p/s=;
|
||||
b=CGLrSHoDnG8b5CL6asLWP1Ym/QFl+wtwIF8PhKlW7RJ5IhavVtdO6Fd7/cY/3GQTDa
|
||||
wvX9Q1wfBsakVlG9/sM9CuozOsra6Ec9c1B+0beWTAKj/tBjwvsVHtMoCiqOPL/Vbig6
|
||||
4zkWMb6dwWSzAgmCqPEaYlyJYqBrDLzzXxqGhchwTfcNgNZQGq0xhh7tZsukEPz4XLIC
|
||||
LNCy6+hPSVdRG1ADbyPpOGFn3fSeFs5KAwl3y1Cn0TvTPxgpckTLcFz5TsTF/w7VLGW1
|
||||
bn9Gakn+MaATqxahU0lDwyzI1sMK2er7/ddjV9VugYN4PzgL9DHGu/iGzXGFftDoLdaJ
|
||||
tBIQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
|
||||
:references:mime-version:content-transfer-encoding;
|
||||
bh=fWEWnDB7IS15Aoqul4RZDergwEtbUe4NAH8lKjv7p/s=;
|
||||
b=PQiPlj7RSTzmBU6u/2xzL9qv8jrelC7cJFFiOHjwKfz43PMzm0nEj6PxY5ZFMSjmbs
|
||||
JEfC8iDjJh39FJdthBrvaZX4yuTv4QmOdmRMWrN77sQYbZOaKOhbNrCx2/LdHzAFjLBY
|
||||
qTHW0+siiP/ATBf1M0cSP200UZAjBwU8MRapxAlaIUmlrfr5+oM8ZrL2tMhzDYcn5b51
|
||||
TwXEVVI5Ep0YZxyGYQ04yaMBZxb1hSKev6UhrFpk96Ukg4IY3qBQBRpjWHIWqZY21aUl
|
||||
EeDLmlWZaqDbp6UQQrAd2p1kIVyrxKD2Cf4aPnk2JcvzR9qGfMwV8cpR9rqwrXBEiyLj
|
||||
KZFg==
|
||||
X-Gm-Message-State: AOAM532lFsZyg8BiLek2pS5Ftc0rOopeD1Q9b7d5Lc7gC8pPIjHcnizK
|
||||
2/grg+4GExN9zVerojORiZgGkTwU1/c2DswO
|
||||
X-Google-Smtp-Source: ABdhPJwECFbuV2SwesS0pF6L0s23ghF61g6whXAjcLZpxYe6b6OsgENBMa3gmTj9FFMF+68uJYhPPw==
|
||||
X-Received: by 2002:a63:1d26:: with SMTP id d38mr17032822pgd.385.1616850397389;
|
||||
Sat, 27 Mar 2021 06:06:37 -0700 (PDT)
|
||||
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
|
||||
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.36
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Sat, 27 Mar 2021 06:06:37 -0700 (PDT)
|
||||
From: John Chen <johnchen902@gmail.com>
|
||||
To: linux-kernel@vger.kernel.org
|
||||
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
|
||||
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
|
||||
Jiri Kosina <jikos@kernel.org>,
|
||||
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
|
||||
John Chen <johnchen902@gmail.com>
|
||||
Subject: [PATCH 3/4] HID: magicmouse: fix reconnection of Magic Mouse 2
|
||||
Date: Sat, 27 Mar 2021 21:05:07 +0800
|
||||
Message-Id: <20210327130508.24849-4-johnchen902@gmail.com>
|
||||
X-Mailer: git-send-email 2.31.0
|
||||
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
References: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-4-johnchen902@gmail.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
It is observed that the Magic Mouse 2 would not enter multi-touch mode
|
||||
unless the mouse is connected before loading the module. It seems to be
|
||||
a quirk specific to Magic Mouse 2
|
||||
|
||||
Retrying after 500ms fixes the problem for me. The delay can't be
|
||||
reduced much further --- 300ms didn't work for me. Retrying immediately
|
||||
after receiving an event didn't work either.
|
||||
|
||||
Signed-off-by: John Chen <johnchen902@gmail.com>
|
||||
---
|
||||
drivers/hid/hid-magicmouse.c | 93 ++++++++++++++++++++++++------------
|
||||
1 file changed, 63 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
||||
index c646b4cd3783..69aefef9fe07 100644
|
||||
--- a/drivers/hid/hid-magicmouse.c
|
||||
+++ b/drivers/hid/hid-magicmouse.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/workqueue.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
@@ -128,6 +129,9 @@ struct magicmouse_sc {
|
||||
u8 size;
|
||||
} touches[16];
|
||||
int tracking_ids[16];
|
||||
+
|
||||
+ struct hid_device *hdev;
|
||||
+ struct delayed_work work;
|
||||
};
|
||||
|
||||
static int magicmouse_firm_touch(struct magicmouse_sc *msc)
|
||||
@@ -629,9 +633,7 @@ static int magicmouse_input_configured(struct hid_device *hdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
-static int magicmouse_probe(struct hid_device *hdev,
|
||||
- const struct hid_device_id *id)
|
||||
+static int magicmouse_enable_multitouch(struct hid_device *hdev)
|
||||
{
|
||||
const u8 *feature;
|
||||
const u8 feature_mt[] = { 0xD7, 0x01 };
|
||||
@@ -639,10 +641,52 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 };
|
||||
const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 };
|
||||
u8 *buf;
|
||||
+ int ret;
|
||||
+ int feature_size;
|
||||
+
|
||||
+ if (hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
|
||||
+ if (hdev->vendor == BT_VENDOR_ID_APPLE) {
|
||||
+ feature_size = sizeof(feature_mt_trackpad2_bt);
|
||||
+ feature = feature_mt_trackpad2_bt;
|
||||
+ } else { /* USB_VENDOR_ID_APPLE */
|
||||
+ feature_size = sizeof(feature_mt_trackpad2_usb);
|
||||
+ feature = feature_mt_trackpad2_usb;
|
||||
+ }
|
||||
+ } else if (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
+ feature_size = sizeof(feature_mt_mouse2);
|
||||
+ feature = feature_mt_mouse2;
|
||||
+ } else {
|
||||
+ feature_size = sizeof(feature_mt);
|
||||
+ feature = feature_mt;
|
||||
+ }
|
||||
+
|
||||
+ buf = kmemdup(feature, feature_size, GFP_KERNEL);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size,
|
||||
+ HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||||
+ kfree(buf);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void magicmouse_enable_mt_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct magicmouse_sc *msc =
|
||||
+ container_of(work, struct magicmouse_sc, work.work);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = magicmouse_enable_multitouch(msc->hdev);
|
||||
+ if (ret < 0)
|
||||
+ hid_err(msc->hdev, "unable to request touch data (%d)\n", ret);
|
||||
+}
|
||||
+
|
||||
+static int magicmouse_probe(struct hid_device *hdev,
|
||||
+ const struct hid_device_id *id)
|
||||
+{
|
||||
struct magicmouse_sc *msc;
|
||||
struct hid_report *report;
|
||||
int ret;
|
||||
- int feature_size;
|
||||
|
||||
if (id->vendor == USB_VENDOR_ID_APPLE &&
|
||||
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
|
||||
@@ -656,6 +700,8 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
}
|
||||
|
||||
msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
|
||||
+ msc->hdev = hdev;
|
||||
+ INIT_DEFERRABLE_WORK(&msc->work, magicmouse_enable_mt_work);
|
||||
|
||||
msc->quirks = id->driver_data;
|
||||
hid_set_drvdata(hdev, msc);
|
||||
@@ -705,28 +751,6 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
}
|
||||
report->size = 6;
|
||||
|
||||
- if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
|
||||
- if (id->vendor == BT_VENDOR_ID_APPLE) {
|
||||
- feature_size = sizeof(feature_mt_trackpad2_bt);
|
||||
- feature = feature_mt_trackpad2_bt;
|
||||
- } else { /* USB_VENDOR_ID_APPLE */
|
||||
- feature_size = sizeof(feature_mt_trackpad2_usb);
|
||||
- feature = feature_mt_trackpad2_usb;
|
||||
- }
|
||||
- } else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
- feature_size = sizeof(feature_mt_mouse2);
|
||||
- feature = feature_mt_mouse2;
|
||||
- } else {
|
||||
- feature_size = sizeof(feature_mt);
|
||||
- feature = feature_mt;
|
||||
- }
|
||||
-
|
||||
- buf = kmemdup(feature, feature_size, GFP_KERNEL);
|
||||
- if (!buf) {
|
||||
- ret = -ENOMEM;
|
||||
- goto err_stop_hw;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Some devices repond with 'invalid report id' when feature
|
||||
* report switching it into multitouch mode is sent to it.
|
||||
@@ -735,13 +759,14 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
* but there seems to be no other way of switching the mode.
|
||||
* Thus the super-ugly hacky success check below.
|
||||
*/
|
||||
- ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size,
|
||||
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||||
- kfree(buf);
|
||||
- if (ret != -EIO && ret != feature_size) {
|
||||
+ ret = magicmouse_enable_multitouch(hdev);
|
||||
+ if (ret != -EIO && ret < 0) {
|
||||
hid_err(hdev, "unable to request touch data (%d)\n", ret);
|
||||
goto err_stop_hw;
|
||||
}
|
||||
+ if (ret == -EIO && id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
|
||||
+ schedule_delayed_work(&msc->work, msecs_to_jiffies(500));
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
err_stop_hw:
|
||||
@@ -749,6 +774,13 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void magicmouse_remove(struct hid_device *hdev)
|
||||
+{
|
||||
+ struct magicmouse_sc *msc = hid_get_drvdata(hdev);
|
||||
+ cancel_delayed_work_sync(&msc->work);
|
||||
+ hid_hw_stop(hdev);
|
||||
+}
|
||||
+
|
||||
static const struct hid_device_id magic_mice[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
|
||||
@@ -768,6 +800,7 @@ static struct hid_driver magicmouse_driver = {
|
||||
.name = "magicmouse",
|
||||
.id_table = magic_mice,
|
||||
.probe = magicmouse_probe,
|
||||
+ .remove = magicmouse_remove,
|
||||
.raw_event = magicmouse_raw_event,
|
||||
.event = magicmouse_event,
|
||||
.input_mapping = magicmouse_input_mapping,
|
||||
--
|
||||
2.31.0
|
||||
|
||||
|
@ -0,0 +1,153 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
|
||||
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
|
||||
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
|
||||
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
|
||||
autolearn_force=no version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 9BE24C433E0
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 70E6A61993
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S230334AbhC0NHL (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:07:11 -0400
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59832 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S230347AbhC0NGo (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 27 Mar 2021 09:06:44 -0400
|
||||
Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AAD5C0613B1
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:44 -0700 (PDT)
|
||||
Received: by mail-pg1-x536.google.com with SMTP id 32so6451842pgm.1
|
||||
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:44 -0700 (PDT)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=gmail.com; s=20161025;
|
||||
h=from:to:cc:subject:date:message-id:in-reply-to:references
|
||||
:mime-version:content-transfer-encoding;
|
||||
bh=5GW0J0I07iFc3HTzTSsHG/cnT3ft+pF2eI68TUZquXs=;
|
||||
b=jJACN/frvED8BOFNtDXFShzg5zpUEJjtXdexEk/8uljNrUnW9QBLA5orX/2hdcZdS4
|
||||
9HL492GecBx3KY9Y5P/B3fttZmlHkwWbuUktmVlmaIOZv1jAPTyYz5zJYh0O0ncw9/rk
|
||||
aPvRb4s1NZHByZ4XoCWbWOd98BvgHHQ/m4Zf1zmP5lYjBVMb2r6qSejuJ5ywQOCBKo9x
|
||||
Q8SL42BOWrlNlsWmeP+oDEYWSDARHpKlRqQ63Y4LdvV2uS9IF6+bmHotGSRlHSLuFN1b
|
||||
/PcfuSQynv38/EgH8MeE16VKzAvLXGu/KgcOLLCsSLgPFLqKAk3uQVc5QRLw00niguHp
|
||||
MMUg==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
|
||||
:references:mime-version:content-transfer-encoding;
|
||||
bh=5GW0J0I07iFc3HTzTSsHG/cnT3ft+pF2eI68TUZquXs=;
|
||||
b=AueOy/X73fYr+YShlS2LMp2gWnsgDUIFV7eKHphj6Q1dBTHtj/dxdarFAonoqAtMRD
|
||||
RCpUwakkFtecMcJPGG/2FRZdRmbJg/ksRvalLQhQCN8XYGB4T/o3zmaOUUooitcGC3gj
|
||||
aeCCryhkv9OzDUYTwPsAzTjrDTkTB3Oh8IvWhfEIcb9x8k+J+OLaIrGozUxhtJkepSRc
|
||||
Uswy+MJkcl8KfXiawODwnjX7JmWwm2SdpRbsBKjJjs+rad+ECgYEFyt8aqYbTabFtIuj
|
||||
oaHtcYHS6FLYTFcRbhCcVECQo2OUzvJjPNe5GyHqUxlvmdFI/Wn68/dt5DKSl5CHRjrp
|
||||
qdPA==
|
||||
X-Gm-Message-State: AOAM530Dp411JuLoADUDvvtPhkgbdVcoa5u6Mm4STd67xIRk49ZPXT33
|
||||
uWg1/mAtTfIfNFL2t5NEvBtvsCfrYoBgGzJJ
|
||||
X-Google-Smtp-Source: ABdhPJw4EeRec5E5FY/fifXp32gxWuRl/ThAsWSiEflIS3aALG3LbhZVwkDmQhbhsG3gD8jRMsQIlw==
|
||||
X-Received: by 2002:a62:17c4:0:b029:1f5:7cfe:ebc4 with SMTP id 187-20020a6217c40000b02901f57cfeebc4mr17080244pfx.5.1616850403793;
|
||||
Sat, 27 Mar 2021 06:06:43 -0700 (PDT)
|
||||
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
|
||||
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.42
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Sat, 27 Mar 2021 06:06:43 -0700 (PDT)
|
||||
From: John Chen <johnchen902@gmail.com>
|
||||
To: linux-kernel@vger.kernel.org
|
||||
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
|
||||
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
|
||||
Jiri Kosina <jikos@kernel.org>,
|
||||
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
|
||||
John Chen <johnchen902@gmail.com>
|
||||
Subject: [PATCH 4/4] HID: input: map battery capacity (00850065)
|
||||
Date: Sat, 27 Mar 2021 21:05:08 +0800
|
||||
Message-Id: <20210327130508.24849-5-johnchen902@gmail.com>
|
||||
X-Mailer: git-send-email 2.31.0
|
||||
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
References: <20210327130508.24849-1-johnchen902@gmail.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-5-johnchen902@gmail.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
This is the capacity in percentage, relative to design capacity.
|
||||
Specifically, it is present in Apple Magic Mouse 2.
|
||||
|
||||
In contrast, usage 00850064 is also the capacity in percentage, but is
|
||||
relative to full capacity. It is not mapped here because I don't have
|
||||
such device.
|
||||
|
||||
Signed-off-by: John Chen <johnchen902@gmail.com>
|
||||
---
|
||||
drivers/hid/hid-debug.c | 1 +
|
||||
drivers/hid/hid-input.c | 11 +++++++++++
|
||||
include/linux/hid.h | 3 +++
|
||||
3 files changed, 15 insertions(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
|
||||
index d7eaf9100370..59f8d716d78f 100644
|
||||
--- a/drivers/hid/hid-debug.c
|
||||
+++ b/drivers/hid/hid-debug.c
|
||||
@@ -417,6 +417,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
|
||||
{ 0x85, 0x44, "Charging" },
|
||||
{ 0x85, 0x45, "Discharging" },
|
||||
{ 0x85, 0x4b, "NeedReplacement" },
|
||||
+ { 0x85, 0x65, "AbsoluteStateOfCharge" },
|
||||
{ 0x85, 0x66, "RemainingCapacity" },
|
||||
{ 0x85, 0x68, "RunTimeToEmpty" },
|
||||
{ 0x85, 0x6a, "AverageTimeToFull" },
|
||||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
|
||||
index 236bccd37760..5dea3669a927 100644
|
||||
--- a/drivers/hid/hid-input.c
|
||||
+++ b/drivers/hid/hid-input.c
|
||||
@@ -1074,6 +1074,17 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
}
|
||||
goto unknown;
|
||||
|
||||
+ case HID_UP_BATTERY:
|
||||
+ switch (usage->hid) {
|
||||
+ case HID_BAT_ABSOLUTESTATEOFCHARGE:
|
||||
+ hidinput_setup_battery(device, HID_INPUT_REPORT, field);
|
||||
+ usage->type = EV_PWR;
|
||||
+ return;
|
||||
+ }
|
||||
+ goto unknown;
|
||||
+
|
||||
case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
diff --git a/include/linux/hid.h b/include/linux/hid.h
|
||||
index ef702b3f56e3..b40e1abbe11d 100644
|
||||
--- a/include/linux/hid.h
|
||||
+++ b/include/linux/hid.h
|
||||
@@ -153,6 +153,7 @@ struct hid_item {
|
||||
#define HID_UP_CONSUMER 0x000c0000
|
||||
#define HID_UP_DIGITIZER 0x000d0000
|
||||
#define HID_UP_PID 0x000f0000
|
||||
+#define HID_UP_BATTERY 0x00850000
|
||||
#define HID_UP_HPVENDOR 0xff7f0000
|
||||
#define HID_UP_HPVENDOR2 0xff010000
|
||||
#define HID_UP_MSVENDOR 0xff000000
|
||||
@@ -297,6 +298,8 @@ struct hid_item {
|
||||
#define HID_DG_TOOLSERIALNUMBER 0x000d005b
|
||||
#define HID_DG_LATENCYMODE 0x000d0060
|
||||
|
||||
+#define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065
|
||||
+
|
||||
#define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076
|
||||
/*
|
||||
* HID report types --- Ouch! HID spec says 1 2 3!
|
||||
--
|
||||
2.31.0
|
||||
|
||||
|
@ -0,0 +1,330 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-21.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT,
|
||||
USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 3BECEC433E0
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id E48DB64F1D
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:05 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233163AbhCMH6d (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:33 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58938 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S230309AbhCMH55 (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:57:57 -0500
|
||||
Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 25364C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:57:57 -0800 (PST)
|
||||
Received: by mail-qk1-x74a.google.com with SMTP id k188so1766042qkb.5
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:57:57 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:message-id:mime-version:subject:from:to:cc;
|
||||
bh=Dl/3fLOB0H+oajTIzqKaDQePlH9N08uWOrKgpspO4TI=;
|
||||
b=ZDlp8kO1cOzH9TKK391ns60MA5XH6wAt4WlC5cRspVrndQuLOdzpe4WuBER+H/7iF2
|
||||
P/jJN5bw/W10rtSgEJl+3nFM9KliKjzDKLX1Wjo+FdVZj7lWam1qWgkQTlezZ+NtB7MK
|
||||
cT+C7m++Ac2yj63uufwG9IIyPjtCqwGGHd6caaZjsFdwrZIYl6mprawhmN0ajnA+KxLu
|
||||
3msx/zJkbVaZ75VF4EavCd4hAKjuHACTjU5DSIC+hq9i3Y5TuQGinRu50cx5wXXQqKu+
|
||||
TLyLtiLkTbZaVeLhF0uQooG8E4w+JXFmnfMxWOPsekXQyWZHebj5hpUPJ1nW39iQnMBt
|
||||
NShw==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc;
|
||||
bh=Dl/3fLOB0H+oajTIzqKaDQePlH9N08uWOrKgpspO4TI=;
|
||||
b=XOeOFYm39AC6u/tzgFN40WA+JyClAjJZL1vfB4B2WAz2bh8R5boQeyY2Px52/PXMqe
|
||||
PCZUSDqqa3qe2AL+XMFxSKay7L4rvvcPP294PgvjMTHIci5V4Nvhb2gooGAFYMoxkgvH
|
||||
lEixBlTS6nGyJ8IubphUQVdIAQN9EaHViPwha6EQb3TvAyPjae5NDLVjv32BjQLi8CGw
|
||||
OTubWcbqjEu/b5lo0MSHi/e6RCI3rcUJRFagT567WMEKCRXl9L9lKS2Y/hxoG2vx6f7E
|
||||
NTzYk8hh52IHO/hBULiYGwss1WApIAFZmg6gkNZJQhw3Z7ZYCxHz7oMXAJCzFeOBikcZ
|
||||
lJnw==
|
||||
X-Gm-Message-State: AOAM5315xRkAW2HlZY5TGBhlW7nW/go+xoCYXD97M7G+xWGL5D5tgqcK
|
||||
MXUwE4z8bQg+QCpnSwxROcufEldhmTU=
|
||||
X-Google-Smtp-Source: ABdhPJyxefk+CsNOhJRg0zohX7wmgO41UdqyprhNKHQCCmk9ImMeIO+UNC1eONE3N7hnVkFPu9qRD/MnUEM=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a0c:fc06:: with SMTP id z6mr1801957qvo.25.1615622276103;
|
||||
Fri, 12 Mar 2021 23:57:56 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:33 -0700
|
||||
Message-Id: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 00/14] Multigenerational LRU
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-1-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
TLDR
|
||||
====
|
||||
The current page reclaim is too expensive in terms of CPU usage and
|
||||
often making poor choices about what to evict. We would like to offer
|
||||
a performant, versatile and straightforward augment.
|
||||
|
||||
Repo
|
||||
====
|
||||
git fetch https://linux-mm.googlesource.com/page-reclaim refs/changes/01/1101/1
|
||||
|
||||
Gerrit https://linux-mm-review.googlesource.com/c/page-reclaim/+/1101
|
||||
|
||||
Background
|
||||
==========
|
||||
DRAM is a major factor in total cost of ownership, and improving
|
||||
memory overcommit brings a high return on investment. Over the past
|
||||
decade of research and experimentation in memory overcommit, we
|
||||
observed a distinct trend across millions of servers and clients: the
|
||||
size of page cache has been decreasing because of the growing
|
||||
popularity of cloud storage. Nowadays anon pages account for more than
|
||||
90% of our memory consumption and page cache contains mostly
|
||||
executable pages.
|
||||
|
||||
Problems
|
||||
========
|
||||
Notion of the active/inactive
|
||||
-----------------------------
|
||||
For servers equipped with hundreds of gigabytes of memory, the
|
||||
granularity of the active/inactive is too coarse to be useful for job
|
||||
scheduling. And false active/inactive rates are relatively high. In
|
||||
addition, scans of largely varying numbers of pages are unpredictable
|
||||
because inactive_is_low() is based on magic numbers.
|
||||
|
||||
For phones and laptops, the eviction is biased toward file pages
|
||||
because the selection has to resort to heuristics as direct
|
||||
comparisons between anon and file types are infeasible. On Android and
|
||||
Chrome OS, executable pages are frequently evicted despite the fact
|
||||
that there are many less recently used anon pages. This causes "janks"
|
||||
(slow UI rendering) and negatively impacts user experience.
|
||||
|
||||
For systems with multiple nodes and/or memcgs, it is impossible to
|
||||
compare lruvecs based on the notion of the active/inactive.
|
||||
|
||||
Incremental scans via the rmap
|
||||
------------------------------
|
||||
Each incremental scan picks up at where the last scan left off and
|
||||
stops after it has found a handful of unreferenced pages. For most of
|
||||
the systems running cloud workloads, incremental scans lose the
|
||||
advantage under sustained memory pressure due to high ratios of the
|
||||
number of scanned pages to the number of reclaimed pages. In our case,
|
||||
the average ratio of pgscan to pgsteal is about 7.
|
||||
|
||||
On top of that, the rmap has poor memory locality due to its complex
|
||||
data structures. The combined effects typically result in a high
|
||||
amount of CPU usage in the reclaim path. For example, with zram, a
|
||||
typical kswapd profile on v5.11 looks like:
|
||||
31.03% page_vma_mapped_walk
|
||||
25.59% lzo1x_1_do_compress
|
||||
4.63% do_raw_spin_lock
|
||||
3.89% vma_interval_tree_iter_next
|
||||
3.33% vma_interval_tree_subtree_search
|
||||
|
||||
And with real swap, it looks like:
|
||||
45.16% page_vma_mapped_walk
|
||||
7.61% do_raw_spin_lock
|
||||
5.69% vma_interval_tree_iter_next
|
||||
4.91% vma_interval_tree_subtree_search
|
||||
3.71% page_referenced_one
|
||||
|
||||
Solutions
|
||||
=========
|
||||
Notion of generation numbers
|
||||
----------------------------
|
||||
The notion of generation numbers introduces a quantitative approach to
|
||||
memory overcommit. A larger number of pages can be spread out across
|
||||
configurable generations, and thus they have relatively low false
|
||||
active/inactive rates. Each generation includes all pages that have
|
||||
been referenced since the last generation.
|
||||
|
||||
Given an lruvec, scans and the selections between anon and file types
|
||||
are all based on generation numbers, which are simple and yet
|
||||
effective. For different lruvecs, comparisons are still possible based
|
||||
on birth times of generations.
|
||||
|
||||
Differential scans via page tables
|
||||
----------------------------------
|
||||
Each differential scan discovers all pages that have been referenced
|
||||
since the last scan. Specifically, it walks the mm_struct list
|
||||
associated with an lruvec to scan page tables of processes that have
|
||||
been scheduled since the last scan. The cost of each differential scan
|
||||
is roughly proportional to the number of referenced pages it
|
||||
discovers. Unless address spaces are extremely sparse, page tables
|
||||
usually have better memory locality than the rmap. The end result is
|
||||
generally a significant reduction in CPU usage, for most of the
|
||||
systems running cloud workloads.
|
||||
|
||||
On Chrome OS, our real-world benchmark that browses popular websites
|
||||
in multiple tabs demonstrates 51% less CPU usage from kswapd and 52%
|
||||
(full) less PSI on v5.11. And kswapd profile looks like:
|
||||
49.36% lzo1x_1_do_compress
|
||||
4.54% page_vma_mapped_walk
|
||||
4.45% memset_erms
|
||||
3.47% walk_pte_range
|
||||
2.88% zram_bvec_rw
|
||||
|
||||
In addition, direct reclaim latency is reduced by 22% at 99th
|
||||
percentile and the number of refaults is reduced 7%. These metrics are
|
||||
important to phones and laptops as they are correlated to user
|
||||
experience.
|
||||
|
||||
Workflow
|
||||
========
|
||||
Evictable pages are divided into multiple generations for each lruvec.
|
||||
The youngest generation number is stored in lruvec->evictable.max_seq
|
||||
for both anon and file types as they are aged on an equal footing. The
|
||||
oldest generation numbers are stored in lruvec->evictable.min_seq[2]
|
||||
separately for anon and file types as clean file pages can be evicted
|
||||
regardless of may_swap or may_writepage. Generation numbers are
|
||||
truncated into ilog2(MAX_NR_GENS)+1 bits in order to fit into
|
||||
page->flags. The sliding window technique is used to prevent truncated
|
||||
generation numbers from overlapping. Each truncated generation number
|
||||
is an index to
|
||||
lruvec->evictable.lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES].
|
||||
Evictable pages are added to the per-zone lists indexed by max_seq or
|
||||
min_seq[2] (modulo MAX_NR_GENS), depending on whether they are being
|
||||
faulted in or read ahead. The workflow comprises two conceptually
|
||||
independent functions: the aging and the eviction.
|
||||
|
||||
Aging
|
||||
-----
|
||||
The aging produces young generations. Given an lruvec, the aging scans
|
||||
page tables for referenced pages of this lruvec. Upon finding one, the
|
||||
aging updates its generation number to max_seq. After each round of
|
||||
scan, the aging increments max_seq. The aging maintains either a
|
||||
system-wide mm_struct list or per-memcg mm_struct lists and tracks
|
||||
whether an mm_struct is being used on any CPUs or has been used since
|
||||
the last scan. Multiple threads can concurrently work on the same
|
||||
mm_struct list, and each of them will be given a different mm_struct
|
||||
belonging to a process that has been scheduled since the last scan.
|
||||
|
||||
Eviction
|
||||
--------
|
||||
The eviction consumes old generations. Given an lruvec, the eviction
|
||||
scans the pages on the per-zone lists indexed by either of min_seq[2].
|
||||
It selects a type according to the values of min_seq[2] and
|
||||
swappiness. During a scan, the eviction either sorts or isolates a
|
||||
page, depending on whether the aging has updated its generation
|
||||
number. When it finds all the per-zone lists are empty, the eviction
|
||||
increments min_seq[2] indexed by this selected type. The eviction
|
||||
triggers the aging when both of min_seq[2] reaches max_seq-1, assuming
|
||||
both anon and file types are reclaimable.
|
||||
|
||||
Use cases
|
||||
=========
|
||||
On Android, our most advanced simulation that generates memory
|
||||
pressure from realistic user behavior shows 18% fewer low-memory
|
||||
kills, which in turn reduces cold starts by 16%.
|
||||
|
||||
On Borg, a similar approach enables us to identify jobs that
|
||||
underutilize their memory and downsize them considerably without
|
||||
compromising any of our service level indicators.
|
||||
|
||||
On Chrome OS, our field telemetry reports 96% fewer low-memory tab
|
||||
discards and 59% fewer OOM kills from fully-utilized devices and no UX
|
||||
regressions from underutilized devices.
|
||||
|
||||
For other use cases include working set estimation, proactive reclaim,
|
||||
far memory tiering and NUMA-aware job scheduling, please refer to the
|
||||
documentation included in this series and the following references.
|
||||
|
||||
References
|
||||
==========
|
||||
1. Long-term SLOs for reclaimed cloud computing resources
|
||||
https://research.google/pubs/pub43017/
|
||||
2. Profiling a warehouse-scale computer
|
||||
https://research.google/pubs/pub44271/
|
||||
3. Evaluation of NUMA-Aware Scheduling in Warehouse-Scale Clusters
|
||||
https://research.google/pubs/pub48329/
|
||||
4. Software-defined far memory in warehouse-scale computers
|
||||
https://research.google/pubs/pub48551/
|
||||
5. Borg: the Next Generation
|
||||
https://research.google/pubs/pub49065/
|
||||
|
||||
Yu Zhao (14):
|
||||
include/linux/memcontrol.h: do not warn in page_memcg_rcu() if
|
||||
!CONFIG_MEMCG
|
||||
include/linux/nodemask.h: define next_memory_node() if !CONFIG_NUMA
|
||||
include/linux/huge_mm.h: define is_huge_zero_pmd() if
|
||||
!CONFIG_TRANSPARENT_HUGEPAGE
|
||||
include/linux/cgroup.h: export cgroup_mutex
|
||||
mm/swap.c: export activate_page()
|
||||
mm, x86: support the access bit on non-leaf PMD entries
|
||||
mm/pagewalk.c: add pud_entry_post() for post-order traversals
|
||||
mm/vmscan.c: refactor shrink_node()
|
||||
mm: multigenerational lru: mm_struct list
|
||||
mm: multigenerational lru: core
|
||||
mm: multigenerational lru: page activation
|
||||
mm: multigenerational lru: user space interface
|
||||
mm: multigenerational lru: Kconfig
|
||||
mm: multigenerational lru: documentation
|
||||
|
||||
Documentation/vm/index.rst | 1 +
|
||||
Documentation/vm/multigen_lru.rst | 210 +++
|
||||
arch/Kconfig | 8 +
|
||||
arch/x86/Kconfig | 1 +
|
||||
arch/x86/include/asm/pgtable.h | 2 +-
|
||||
arch/x86/mm/pgtable.c | 5 +-
|
||||
fs/exec.c | 2 +
|
||||
fs/proc/task_mmu.c | 3 +-
|
||||
include/linux/cgroup.h | 15 +-
|
||||
include/linux/huge_mm.h | 5 +
|
||||
include/linux/memcontrol.h | 5 +-
|
||||
include/linux/mm.h | 1 +
|
||||
include/linux/mm_inline.h | 246 ++++
|
||||
include/linux/mm_types.h | 135 ++
|
||||
include/linux/mmzone.h | 62 +-
|
||||
include/linux/nodemask.h | 1 +
|
||||
include/linux/page-flags-layout.h | 20 +-
|
||||
include/linux/pagewalk.h | 4 +
|
||||
include/linux/pgtable.h | 4 +-
|
||||
include/linux/swap.h | 5 +-
|
||||
kernel/events/uprobes.c | 2 +-
|
||||
kernel/exit.c | 1 +
|
||||
kernel/fork.c | 10 +
|
||||
kernel/kthread.c | 1 +
|
||||
kernel/sched/core.c | 2 +
|
||||
mm/Kconfig | 29 +
|
||||
mm/huge_memory.c | 5 +-
|
||||
mm/khugepaged.c | 2 +-
|
||||
mm/memcontrol.c | 28 +
|
||||
mm/memory.c | 14 +-
|
||||
mm/migrate.c | 2 +-
|
||||
mm/mm_init.c | 13 +-
|
||||
mm/mmzone.c | 2 +
|
||||
mm/pagewalk.c | 5 +
|
||||
mm/rmap.c | 6 +
|
||||
mm/swap.c | 58 +-
|
||||
mm/swapfile.c | 6 +-
|
||||
mm/userfaultfd.c | 2 +-
|
||||
mm/vmscan.c | 2091 +++++++++++++++++++++++++++--
|
||||
39 files changed, 2870 insertions(+), 144 deletions(-)
|
||||
create mode 100644 Documentation/vm/multigen_lru.rst
|
||||
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,129 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 42B16C433DB
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 11CED64ECE
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233237AbhCMH6e (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:34 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58944 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S230349AbhCMH56 (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:57:58 -0500
|
||||
Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7B7EAC061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:57:58 -0800 (PST)
|
||||
Received: by mail-yb1-xb49.google.com with SMTP id d8so32058455ybs.11
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:57:58 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=CiMQJrfmhcT/Xw28mTP3VlU5SRPV8bRsC232LNJk7tU=;
|
||||
b=U+bvs2P4aWZrWqfRwrXFunM/l5sWGKqRdiGQFJBSXwSH+vfw4kB3WjkPPQpoUgHwwx
|
||||
+4KITrOtke32as1JFmSOW/QJ8GYL6J2CyqtNZysfNDnr4dUu1eafFf0OU/BN2PlR6TZw
|
||||
u/bOTirXcAreUn8QrcDvxRKbQwugJdk2JWl2TqDc7KAmb0AodFb/pAgQnWip2QOqWta3
|
||||
5ohqe66l196K6u9PNyDcJqEzz4CuJBMkGEAupVYjzX/HNuFZ1kLz2lz2FxSR38TqyX8I
|
||||
aWFk3lMppRkLaWpnC4nC3SQhZcJq9YOxrujTA4BSnsEwscy7qJzgt8w9xEMiwzmAoN1g
|
||||
Bm1Q==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=CiMQJrfmhcT/Xw28mTP3VlU5SRPV8bRsC232LNJk7tU=;
|
||||
b=Qi2PdmMPthJWQMXSQ05Fb8upxFWwOHNAFsy8LixbQ0QGPKWVlwBzQDYwPCpG05WFP8
|
||||
cYIfPhq3nv9++78Y1Pw7Q8oiGEv7KJ0j/sHIaRZGlWZdHWwciPpKdT9M4JVXYhn4NxhF
|
||||
6YrPBHSTOTN7v9fuCOcPqKSOKTBYMF/eETj9XoeqtvetJVZ1i3Dqxu4TawWOlymnTTkh
|
||||
9IQRnTz2ffdTJdBCH6iTA0UfrEDWDnESubVvzuRfmLvCt3b427gwHWXaK/i7F/60+65O
|
||||
8gzoqIJ9gqwTfdGB3vB6HXtbmWosQ39Zy7gnpTpf0CB7afg1Gnx/4Y26GMLjtLkzeviQ
|
||||
6K7w==
|
||||
X-Gm-Message-State: AOAM531kmbzmJE5p9rtDGXbRHYBSsGjPyFJxoBPqsQzAq6DHfRzY/is2
|
||||
Lgnmsa+bse/YLa5M+1JDlGqGCZxMntQ=
|
||||
X-Google-Smtp-Source: ABdhPJxUTV3MKesWpiHjP1OfC2lc1y93+U3j9zDFMK1igY41oF3Fyu2enmEiwR5c1z6fz0Ykw1sgyEJETNk=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a25:dfd1:: with SMTP id w200mr24182984ybg.362.1615622277472;
|
||||
Fri, 12 Mar 2021 23:57:57 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:34 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-2-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 01/14] include/linux/memcontrol.h: do not warn in
|
||||
page_memcg_rcu() if !CONFIG_MEMCG
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-2-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
We want to make sure the rcu lock is held while using
|
||||
page_memcg_rcu(). But having a WARN_ON_ONCE() in page_memcg_rcu() when
|
||||
!CONFIG_MEMCG is superfluous because of the following legit use case:
|
||||
|
||||
memcg = lock_page_memcg(page1)
|
||||
(rcu_read_lock() if CONFIG_MEMCG=y)
|
||||
|
||||
do something to page1
|
||||
|
||||
if (page_memcg_rcu(page2) == memcg)
|
||||
do something to page2 too as it cannot be migrated away from the
|
||||
memcg either.
|
||||
|
||||
unlock_page_memcg(page1)
|
||||
(rcu_read_unlock() if CONFIG_MEMCG=y)
|
||||
|
||||
This patch removes the WARN_ON_ONCE() from page_memcg_rcu() for the
|
||||
!CONFIG_MEMCG case.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
include/linux/memcontrol.h | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
|
||||
index e6dc793d587d..f325aeb4b4e8 100644
|
||||
--- a/include/linux/memcontrol.h
|
||||
+++ b/include/linux/memcontrol.h
|
||||
@@ -1079,7 +1079,6 @@ static inline struct mem_cgroup *page_memcg(struct page *page)
|
||||
|
||||
static inline struct mem_cgroup *page_memcg_rcu(struct page *page)
|
||||
{
|
||||
- WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,113 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 7CAADC433E9
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 4C9E564ECE
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233343AbhCMH6f (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:35 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58950 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S231723AbhCMH57 (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:57:59 -0500
|
||||
Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B79D0C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:57:59 -0800 (PST)
|
||||
Received: by mail-qk1-x74a.google.com with SMTP id k68so19900263qke.2
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:57:59 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=8JNiZUfBDRjXaPYBpQeMTXnhFbhlF+xtdVruxqSh3cA=;
|
||||
b=IxvaJGLX6pUI5R+Y+pYVqc8/0gQYUuErDfxr3dMFZudBUHTyTTMgRdE0XBcCau7R3l
|
||||
WVURZXlPOHDzjeCRAmjp2GkNmw3M99Sx/iwvc+iSD8ohg8gx7Cj3TzTxPdzUCsghnFFL
|
||||
Hv+lIk4SezNfKgceCzGd/c+Rf6ueoDDPEzD62ZXkdDxk/uLmQc4GjBU0Knksz2+dLsVo
|
||||
b2U0CgK0WmdW2qIHy4OyEo2nBB4jmzDFCPxxlIobZYlIAsooUXen6yoe28K/2f1TgtI5
|
||||
p1/lftklJT4PvJibzbIlGo6vGha2wAL2lU0ks0AxI4l1lf/1Bf/PVsGVaXXW7+F/fJFj
|
||||
Y3HQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=8JNiZUfBDRjXaPYBpQeMTXnhFbhlF+xtdVruxqSh3cA=;
|
||||
b=gAD0lTpWpuRmUv2Dlufjuw7ZklBUzo8DSa0cxSlaWPJunVm1RpqFGuQ0dz/Q5SDxC8
|
||||
e2XkyRSyCbrJ2qPrJUA+p5trg9qCQq4i4twAOZW4+6JOmPcDhnjMZ5aZGSzfoiMIRsoT
|
||||
4EV2Q02mcFvf2IuUgWli5WndTXndhzHNpFWCsogvzS+JWqWb6aY+e+5tJWSfWH3kCiDw
|
||||
t8uRvv61lDKzNQeIpa/ZbY8MFF4olHkRwvO5FMf2xUfghMxRoosJSB3DdLIiwC8NEbpr
|
||||
g7dGskt+2tbLFnNCykjqc81I4A/sSyeBg95oUKs9PNAIBgIoAQlvqOizUcVccM9r97dk
|
||||
dPYA==
|
||||
X-Gm-Message-State: AOAM533j3NWtnjtXQODMvkwfUeiEAcpKyeqz3jm23oO6viFDFeKf35BJ
|
||||
zE9lWSBpsopJHLabXkGrebl2ktdd2BY=
|
||||
X-Google-Smtp-Source: ABdhPJwORNu5jWRG63mEkIrwerIFX+r6WsDRo4k6jBRlD+35Q3Ytikr16dVGNSyDCuR7br75GADeWLQhEY0=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:ad4:5ce8:: with SMTP id iv8mr1757086qvb.16.1615622278881;
|
||||
Fri, 12 Mar 2021 23:57:58 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:35 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-3-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 02/14] include/linux/nodemask.h: define next_memory_node()
|
||||
if !CONFIG_NUMA
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-3-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Currently next_memory_node only exists when CONFIG_NUMA=y. This patch
|
||||
defines the macro for the !CONFIG_NUMA case.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
include/linux/nodemask.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
|
||||
index ac398e143c9a..89fe4e3592f9 100644
|
||||
--- a/include/linux/nodemask.h
|
||||
+++ b/include/linux/nodemask.h
|
||||
@@ -486,6 +486,7 @@ static inline int num_node_state(enum node_states state)
|
||||
#define first_online_node 0
|
||||
#define first_memory_node 0
|
||||
#define next_online_node(nid) (MAX_NUMNODES)
|
||||
+#define next_memory_node(nid) (MAX_NUMNODES)
|
||||
#define nr_node_ids 1U
|
||||
#define nr_online_nodes 1U
|
||||
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,118 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 97984C433E6
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 62DCA64F1E
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233389AbhCMH6g (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:36 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58956 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232023AbhCMH6B (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:01 -0500
|
||||
Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 055BEC061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:01 -0800 (PST)
|
||||
Received: by mail-qk1-x74a.google.com with SMTP id u5so19869532qkj.10
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:00 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=BUGHWaLOgbBXMks9MxevCFPE+HJdHu8WtN3Ad5BKa2E=;
|
||||
b=EmtSmNZcxIc0Qq98PvQLlh/Je74+I9pGiId+AoSzt2WN66X/7gqva2AkM1Z6ZrqWlC
|
||||
qMCo9fu+KgWIl13K9lL0hfZkSMTr33It30mFN/3/xwUcpWXiUy2ttup7BflThw89akrm
|
||||
ipCdNg7GP9J1lKGO0+Ae8TZbHboXPO6EU2DcK5O1kt2ZE3NOFthikv0X6/opyUBdeUKR
|
||||
Q3HhM/pgOA+vQ4UMR7hzNtEDZcmVDtrPgTwq9zDoYDV/KHqaCvxRPvrkCfwY3MbDN9Yc
|
||||
Dm0TaDfpoFKrj/syFqJ/83hwIk0G3OPLs6DbY/I2HkHJ6cbjakxVLFDyXybDitO9MyGA
|
||||
/tow==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=BUGHWaLOgbBXMks9MxevCFPE+HJdHu8WtN3Ad5BKa2E=;
|
||||
b=tk+Szu/MRdyl1iY0zpUHO4VtD8YBAHs5CFbud9sFWZl8OIpU011Pd59sKmQkChiEw7
|
||||
YEzG58xR4zAwc8CM8Vd7HuqKhhVUDIqumg0Ntx1KyfQ2QNYcbVSv8oAHuMLxAAembJau
|
||||
D5EsuQjvXjKjroV/zEhusebtXIHZULBN1x9MfQwyikGwihqLhzDwXeUHx2D7JFo7i40J
|
||||
3hvB0UCXdGNVF257C0gUQWS/r0tKshrTyX1i7tyAutY7viCISRQ6FP65DlTjV3PAmmsw
|
||||
VHxDK47EkcJAoat+x24kFd6i44dgww1DGsDCpvBZu8P/V1m2f4keblf2wZMFsVwDhZRU
|
||||
0b/g==
|
||||
X-Gm-Message-State: AOAM5314IBqaZ2bDNgLAPxQ3EGGAGDitVyFeUtt5HNFWNSHljmLCuPyl
|
||||
iPCluBY4dSP0ON55Ckf7BwK1bpQBiw8=
|
||||
X-Google-Smtp-Source: ABdhPJzJJ1SnzBtj3bVJq+tnpS8mvob3Iwgd7McsgFl/pDIRa/R9w7/nQuY0bxlcdhV2mXDJvzzuC77PvVA=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a05:6214:4b3:: with SMTP id
|
||||
w19mr1750690qvz.26.1615622280155; Fri, 12 Mar 2021 23:58:00 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:36 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-4-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 03/14] include/linux/huge_mm.h: define is_huge_zero_pmd()
|
||||
if !CONFIG_TRANSPARENT_HUGEPAGE
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-4-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Currently is_huge_zero_pmd() only exists when
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y. This patch defines the function for the
|
||||
!CONFIG_TRANSPARENT_HUGEPAGE case.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
include/linux/huge_mm.h | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
|
||||
index ba973efcd369..0ba7b3f9029c 100644
|
||||
--- a/include/linux/huge_mm.h
|
||||
+++ b/include/linux/huge_mm.h
|
||||
@@ -443,6 +443,11 @@ static inline bool is_huge_zero_page(struct page *page)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static inline bool is_huge_zero_pmd(pmd_t pmd)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static inline bool is_huge_zero_pud(pud_t pud)
|
||||
{
|
||||
return false;
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,140 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id A8DC7C43381
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 7FA3564F1D
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233409AbhCMH6i (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:38 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58964 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232230AbhCMH6C (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:02 -0500
|
||||
Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 562C3C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:02 -0800 (PST)
|
||||
Received: by mail-qk1-x74a.google.com with SMTP id d137so4579263qkb.18
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:02 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=aLRTkKE+4395hmMwkgIvoFPbmsRrSNB3cb7TyZ2ydVo=;
|
||||
b=RbyWeK4rUqhSF6l4+WOn4bz/6l7Kc8FPXxW3gI+7y8uPJAZ1QX8cf/I1Awt1gV/SbI
|
||||
bjnyW7mGxY1NMOZzzbS/+Pu/wZOk8PcdLyHQjU8FYS7MY3rlxWHPLiUeDkvVnQXqR/vU
|
||||
VjFNQgX24G3KsIyOvy72WKVvMUMe73K7lMeGcaq5JwzYtlJpwJmAq7im1mo7v1rCTUgA
|
||||
0mo4ifiQHDGxfCFwMiqlcmL9XCp3IrCMWE8XU4ROv4uXfZw0LtfhovB0FFVhgU4OaGPo
|
||||
9xkxh+e9HnpJUWha5GVEemFT2phEp+qmiZ0b0RvdNPBXFoxHBjwLSKOp/alc26idQnA2
|
||||
6ehw==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=aLRTkKE+4395hmMwkgIvoFPbmsRrSNB3cb7TyZ2ydVo=;
|
||||
b=sPWOPGHoVohb7G6EOihIswCUjaDOMsg/DvRB2ugPnziQk8PcjMml4kYe8yFsYiBamJ
|
||||
ZBRsKYaIxBbegmcuF2aq6FE8IRzx6eYh8i5L6RQ83/jPcS1VVViz30AEgGo2OR0qlRtK
|
||||
6e9I4lEcrR67MLWdkHooamn5SOvnTfgJcr7FGERX+0O/FzSxT56KcHTaEjHYnS68pxQM
|
||||
cryChrhdy5jpPx9+EiGLdZI95GTYYHE3/TXMlABP1Dv4YEWI93zhR/ePrlm0SjEioKWR
|
||||
PW1K3Blnn4t6EIlzyEcAxmVz7702MA3b1x1hM3iPT6B+pwdovapsNRL+JH3s67twnKUc
|
||||
qBWQ==
|
||||
X-Gm-Message-State: AOAM532W7wUq4pmKjtVvHSPslHZDT9pB3jR1xJmNsJD9ZqrBMl8E+xpH
|
||||
v9xzx/Rcs8diDMvgzLYOU4hfhWFObf4=
|
||||
X-Google-Smtp-Source: ABdhPJwU+Y5hioYI52CJyazw+FjQUFeKf1QbQJTSQIAKTuuIxfYVSs2ErBNlMhmNRx4/c6B7zv8sBwMBzxE=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:ad4:5c87:: with SMTP id o7mr1743197qvh.31.1615622281483;
|
||||
Fri, 12 Mar 2021 23:58:01 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:37 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-5-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 04/14] include/linux/cgroup.h: export cgroup_mutex
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-5-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Export cgroup_mutex so it can be used to synchronize with memcg
|
||||
allocations.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
include/linux/cgroup.h | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
|
||||
index 4f2f79de083e..bd5744360cfa 100644
|
||||
--- a/include/linux/cgroup.h
|
||||
+++ b/include/linux/cgroup.h
|
||||
@@ -432,6 +432,18 @@ static inline void cgroup_put(struct cgroup *cgrp)
|
||||
css_put(&cgrp->self);
|
||||
}
|
||||
|
||||
+extern struct mutex cgroup_mutex;
|
||||
+
|
||||
+static inline void cgroup_lock(void)
|
||||
+{
|
||||
+ mutex_lock(&cgroup_mutex);
|
||||
+}
|
||||
+
|
||||
+static inline void cgroup_unlock(void)
|
||||
+{
|
||||
+ mutex_unlock(&cgroup_mutex);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* task_css_set_check - obtain a task's css_set with extra access conditions
|
||||
* @task: the task to obtain css_set for
|
||||
@@ -446,7 +458,6 @@ static inline void cgroup_put(struct cgroup *cgrp)
|
||||
* as locks used during the cgroup_subsys::attach() methods.
|
||||
*/
|
||||
#ifdef CONFIG_PROVE_RCU
|
||||
-extern struct mutex cgroup_mutex;
|
||||
extern spinlock_t css_set_lock;
|
||||
#define task_css_set_check(task, __c) \
|
||||
rcu_dereference_check((task)->cgroups, \
|
||||
@@ -704,6 +715,8 @@ struct cgroup;
|
||||
static inline u64 cgroup_id(const struct cgroup *cgrp) { return 1; }
|
||||
static inline void css_get(struct cgroup_subsys_state *css) {}
|
||||
static inline void css_put(struct cgroup_subsys_state *css) {}
|
||||
+static inline void cgroup_lock(void) {}
|
||||
+static inline void cgroup_unlock(void) {}
|
||||
static inline int cgroup_attach_task_all(struct task_struct *from,
|
||||
struct task_struct *t) { return 0; }
|
||||
static inline int cgroupstats_build(struct cgroupstats *stats,
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,178 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id C5A9BC4332B
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 90B8C64F1F
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233424AbhCMH6i (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:38 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58970 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232431AbhCMH6D (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:03 -0500
|
||||
Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A425FC061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:03 -0800 (PST)
|
||||
Received: by mail-yb1-xb4a.google.com with SMTP id 194so31802025ybl.5
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:03 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=773qLo/LiVz4n2L5CNuvuPAbdhL5vI+dQXWkGfq22YM=;
|
||||
b=s62F923cqY3HHxlJ4hYL4HxcRTUA1o1Vmr0HgcffuxiRKFFBC1czWP98NMUIxWHBf1
|
||||
ZTyWeNYix1pSuyOzyeK0NFpxLIWOmX10rPMvqWp8DuHg1yJhrNIGNko3fZT0atoX3aT9
|
||||
tvbuoR86gyhnQZ8eh7p7K/l32hNMDiL/9yg2skyWxrtzqXc2LkdkDBaiklyidpzGD9Xo
|
||||
glkEqmmHlh+PbMf1URYMZzEcs1zoLYSWmku5OQ0gpaw9yflCHjp7u8qrrfyCRliYK3I/
|
||||
Tc+BFkGgrB7u8ficVc0QKkIHZrZFoWgOnbQ0s8MxrT5IfVlLG0WbP3MEYNuJZFSmG8zL
|
||||
SKVQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=773qLo/LiVz4n2L5CNuvuPAbdhL5vI+dQXWkGfq22YM=;
|
||||
b=JutL0wSOtSKnXJpfp0Rn/HxX7HIFKRMSUwsEChk8vd4csU2mQte1wA+/+UuChaDIbU
|
||||
LAbDmBYxJhnK4nlISGat+zJubGDWfCTB+UZ0ZMedNwvo4kQ6wCMcrBVBswWbPfpCjDwr
|
||||
A4KWgVBEKj1hggrx43gbsIj1+nseOCIQxhyAyqUZPXMWyh5DbkzFwS/Ofm/k9MlAtqkm
|
||||
kxvprFWjiL/B2UVHRa6QH0Pd81vDVjQVhL1VANnhSRBRqVhMl9CKh6LDeEXIQ/j/SUW1
|
||||
sU5WIzhVZuh5Ce8LmXpg49O0w7XWFKmLxS65P39JtYklewPiPLasFUZmGGQIW0YkgSAb
|
||||
ikpA==
|
||||
X-Gm-Message-State: AOAM531sNbnzQRY0viG10kk0YQk3CPKaMfG7csYITYFCtPUjz1sM9Whr
|
||||
xig3F1mAxIB/3uXuYRA3nVADy29ViV4=
|
||||
X-Google-Smtp-Source: ABdhPJyM3uGtugEuR+BtqyW7Pcf+QxhuRuUSNVC/LK4e6LJubLVomvaz1At1w7Vl14tsop0cWxsmMMW22Kg=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a25:d84b:: with SMTP id p72mr22707445ybg.272.1615622282832;
|
||||
Fri, 12 Mar 2021 23:58:02 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:38 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-6-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 05/14] mm/swap.c: export activate_page()
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-6-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Export activate_page(), which is a merger between the existing
|
||||
activate_page() and __lru_cache_activate_page(), so it can be used to
|
||||
activate pages that are already on lru or queued in lru_pvecs.lru_add.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
include/linux/swap.h | 1 +
|
||||
mm/swap.c | 28 +++++++++++++++-------------
|
||||
2 files changed, 16 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/include/linux/swap.h b/include/linux/swap.h
|
||||
index 4cc6ec3bf0ab..de2bbbf181ba 100644
|
||||
--- a/include/linux/swap.h
|
||||
+++ b/include/linux/swap.h
|
||||
@@ -344,6 +344,7 @@ extern void lru_add_drain_cpu(int cpu);
|
||||
extern void lru_add_drain_cpu_zone(struct zone *zone);
|
||||
extern void lru_add_drain_all(void);
|
||||
extern void rotate_reclaimable_page(struct page *page);
|
||||
+extern void activate_page(struct page *page);
|
||||
extern void deactivate_file_page(struct page *page);
|
||||
extern void deactivate_page(struct page *page);
|
||||
extern void mark_page_lazyfree(struct page *page);
|
||||
diff --git a/mm/swap.c b/mm/swap.c
|
||||
index 31b844d4ed94..f20ed56ebbbf 100644
|
||||
--- a/mm/swap.c
|
||||
+++ b/mm/swap.c
|
||||
@@ -334,7 +334,7 @@ static bool need_activate_page_drain(int cpu)
|
||||
return pagevec_count(&per_cpu(lru_pvecs.activate_page, cpu)) != 0;
|
||||
}
|
||||
|
||||
-static void activate_page(struct page *page)
|
||||
+static void activate_page_on_lru(struct page *page)
|
||||
{
|
||||
page = compound_head(page);
|
||||
if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
|
||||
@@ -354,7 +354,7 @@ static inline void activate_page_drain(int cpu)
|
||||
{
|
||||
}
|
||||
|
||||
-static void activate_page(struct page *page)
|
||||
+static void activate_page_on_lru(struct page *page)
|
||||
{
|
||||
struct lruvec *lruvec;
|
||||
|
||||
@@ -368,11 +368,22 @@ static void activate_page(struct page *page)
|
||||
}
|
||||
#endif
|
||||
|
||||
-static void __lru_cache_activate_page(struct page *page)
|
||||
+/*
|
||||
+ * If the page is on the LRU, queue it for activation via
|
||||
+ * lru_pvecs.activate_page. Otherwise, assume the page is on a
|
||||
+ * pagevec, mark it active and it'll be moved to the active
|
||||
+ * LRU on the next drain.
|
||||
+ */
|
||||
+void activate_page(struct page *page)
|
||||
{
|
||||
struct pagevec *pvec;
|
||||
int i;
|
||||
|
||||
+ if (PageLRU(page)) {
|
||||
+ activate_page_on_lru(page);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
local_lock(&lru_pvecs.lock);
|
||||
pvec = this_cpu_ptr(&lru_pvecs.lru_add);
|
||||
|
||||
@@ -421,16 +432,7 @@ void mark_page_accessed(struct page *page)
|
||||
* evictable page accessed has no effect.
|
||||
*/
|
||||
} else if (!PageActive(page)) {
|
||||
- /*
|
||||
- * If the page is on the LRU, queue it for activation via
|
||||
- * lru_pvecs.activate_page. Otherwise, assume the page is on a
|
||||
- * pagevec, mark it active and it'll be moved to the active
|
||||
- * LRU on the next drain.
|
||||
- */
|
||||
- if (PageLRU(page))
|
||||
- activate_page(page);
|
||||
- else
|
||||
- __lru_cache_activate_page(page);
|
||||
+ activate_page(page);
|
||||
ClearPageReferenced(page);
|
||||
workingset_activation(page);
|
||||
}
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,202 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id CFB78C43331
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id A37AF64F1E
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233446AbhCMH6j (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:39 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58976 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232627AbhCMH6F (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:05 -0500
|
||||
Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF963C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:04 -0800 (PST)
|
||||
Received: by mail-qt1-x84a.google.com with SMTP id a16so3377560qtw.1
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:04 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=9FOrNXENvEBq+xjcXdvWYV76Tj/52PeZfpdHZpBdeTw=;
|
||||
b=CZNFSLn1Vr+7g91u2WdSPY2RASOoMeGVnEu8XS9ogwps7Gq+7F5umE3fWsyowJpBWD
|
||||
/BpSgazEV0uTx/142ccxmLjj6Tc5kR7KGsb79Ptj4azaGNuJBT032A7MXAqita6Xkryl
|
||||
6IanFkwVS4tC+SsZAZtk+kuQzdp1pO5Pnx+cXwdQzEVQmCkWjuUnjKzoEPGf4IlnkcFb
|
||||
QOa5YU3bEwcfmAFIwkc2tWsdZ2h8rKKycxzT/zHBKI265GiGZGNofgaHIdU33DduoJGc
|
||||
Q3y72dvencUMJG5nccrm3sqMC+9s98wb5AiyP7gwQH8cNu/oUBPDF/k1zMnv1QbL0y4q
|
||||
Wkmw==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=9FOrNXENvEBq+xjcXdvWYV76Tj/52PeZfpdHZpBdeTw=;
|
||||
b=dwfL2qqtOLyHknmJLTbNquIIE99M3co4RRcjM8ZHW7E3b22r0qS7/uSdIuLxhwPvQA
|
||||
Y3LL2jZN2S3rNEY31iqcQo0XPmDjtQwb13jd9vmVGL+LLS5tszC4uUapyiV0oPCH5uwL
|
||||
smIUxO+PPvwuZT1NgqDpJ05pyAL6HNc5tjDAhFLsgZFN/eS2938P25wiN4+HDX1vPlLc
|
||||
PXD85IpbqplkrTukFj4waHLj2xp8v/FPA9XzbBiYpaKEr1bL5w6oyKCxl6mnhZr0A9h6
|
||||
m3QW2oQAPQpKG6YqSR4gB8S9wvQ5RcQOj/4jcVgdKH2lIq48/Tc9tYuJNF3HuISISSMR
|
||||
K2Aw==
|
||||
X-Gm-Message-State: AOAM530QAe48ahNQ/TdZi8OsNzl8PRShs8X4B4mC6ejSQSSJgG9mU0dS
|
||||
C8+Z0ZLOLiEDu/n5izcyhgbt0bjgPuM=
|
||||
X-Google-Smtp-Source: ABdhPJx3v9fo9fGIto8kHzW5LTGjVA6UTKRtTeuo4NwnDLlQop9mIBVZK8pHZLGtADbIHe5kSQ6HeS7hVrU=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a0c:cb0c:: with SMTP id o12mr15467752qvk.54.1615622284101;
|
||||
Fri, 12 Mar 2021 23:58:04 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:39 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-7-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 06/14] mm, x86: support the access bit on non-leaf PMD entries
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-7-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Some architectures support the accessed bit on non-leaf PMD entries
|
||||
(parents) in addition to leaf PTE entries (children) where pages are
|
||||
mapped, e.g., x86_64 sets the accessed bit on a parent when using it
|
||||
as part of linear-address translation [1]. Page table walkers who are
|
||||
interested in the accessed bit on children can take advantage of this:
|
||||
they do not need to search the children when the accessed bit is not
|
||||
set on a parent, given that they have previously cleared the accessed
|
||||
bit on this parent in addition to its children.
|
||||
|
||||
[1]: Intel 64 and IA-32 Architectures Software Developer's Manual
|
||||
Volume 3 (October 2019), section 4.8
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
arch/Kconfig | 8 ++++++++
|
||||
arch/x86/Kconfig | 1 +
|
||||
arch/x86/include/asm/pgtable.h | 2 +-
|
||||
arch/x86/mm/pgtable.c | 5 ++++-
|
||||
include/linux/pgtable.h | 4 ++--
|
||||
5 files changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/Kconfig b/arch/Kconfig
|
||||
index 2bb30673d8e6..137446d17732 100644
|
||||
--- a/arch/Kconfig
|
||||
+++ b/arch/Kconfig
|
||||
@@ -783,6 +783,14 @@ config HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
config HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
|
||||
bool
|
||||
|
||||
+config HAVE_ARCH_PARENT_PMD_YOUNG
|
||||
+ bool
|
||||
+ help
|
||||
+ Architectures that select this are able to set the accessed bit on
|
||||
+ non-leaf PMD entries in addition to leaf PTE entries where pages are
|
||||
+ mapped. For them, page table walkers that clear the accessed bit may
|
||||
+ stop at non-leaf PMD entries when they do not see the accessed bit.
|
||||
+
|
||||
config HAVE_ARCH_HUGE_VMAP
|
||||
bool
|
||||
|
||||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
|
||||
index 2792879d398e..b5972eb82337 100644
|
||||
--- a/arch/x86/Kconfig
|
||||
+++ b/arch/x86/Kconfig
|
||||
@@ -163,6 +163,7 @@ config X86
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
|
||||
+ select HAVE_ARCH_PARENT_PMD_YOUNG if X86_64
|
||||
select HAVE_ARCH_USERFAULTFD_WP if X86_64 && USERFAULTFD
|
||||
select HAVE_ARCH_VMAP_STACK if X86_64
|
||||
select HAVE_ARCH_WITHIN_STACK_FRAMES
|
||||
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
|
||||
index a02c67291cfc..a6b5cfe1fc5a 100644
|
||||
--- a/arch/x86/include/asm/pgtable.h
|
||||
+++ b/arch/x86/include/asm/pgtable.h
|
||||
@@ -846,7 +846,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
||||
|
||||
static inline int pmd_bad(pmd_t pmd)
|
||||
{
|
||||
- return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE;
|
||||
+ return ((pmd_flags(pmd) | _PAGE_ACCESSED) & ~_PAGE_USER) != _KERNPG_TABLE;
|
||||
}
|
||||
|
||||
static inline unsigned long pages_to_mb(unsigned long npg)
|
||||
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
|
||||
index f6a9e2e36642..1c27e6f43f80 100644
|
||||
--- a/arch/x86/mm/pgtable.c
|
||||
+++ b/arch/x86/mm/pgtable.c
|
||||
@@ -550,7 +550,7 @@ int ptep_test_and_clear_young(struct vm_area_struct *vma,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HAVE_ARCH_PARENT_PMD_YOUNG)
|
||||
int pmdp_test_and_clear_young(struct vm_area_struct *vma,
|
||||
unsigned long addr, pmd_t *pmdp)
|
||||
{
|
||||
@@ -562,6 +562,9 @@ int pmdp_test_and_clear_young(struct vm_area_struct *vma,
|
||||
|
||||
return ret;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
int pudp_test_and_clear_young(struct vm_area_struct *vma,
|
||||
unsigned long addr, pud_t *pudp)
|
||||
{
|
||||
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
|
||||
index 5e772392a379..08dd9b8c055a 100644
|
||||
--- a/include/linux/pgtable.h
|
||||
+++ b/include/linux/pgtable.h
|
||||
@@ -193,7 +193,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
|
||||
#endif
|
||||
|
||||
#ifndef __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
|
||||
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HAVE_ARCH_PARENT_PMD_YOUNG)
|
||||
static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
|
||||
unsigned long address,
|
||||
pmd_t *pmdp)
|
||||
@@ -214,7 +214,7 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
|
||||
BUILD_BUG();
|
||||
return 0;
|
||||
}
|
||||
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HAVE_ARCH_PARENT_PMD_YOUNG */
|
||||
#endif
|
||||
|
||||
#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,144 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id E3438C43332
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id C990264F1D
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233489AbhCMH6l (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:41 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58984 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232702AbhCMH6G (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:06 -0500
|
||||
Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F2FEC061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:06 -0800 (PST)
|
||||
Received: by mail-yb1-xb49.google.com with SMTP id j4so31727869ybt.23
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:06 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=sM28HXat3Ro78N+fdELj5tA2TTORYcmSJRB7y0xn668=;
|
||||
b=TkMSfULPVVqqEs8nJoS183e8mdw8yepLBTDn2eNINUqggav0COpVRzISc3zd89NvN9
|
||||
G1/R3rFQNbXB4Mc0QhWaGTD1Fq53asLndQ1E2i8CSZ95KHVj8MUNkswp9uk2yDDtfErk
|
||||
Sbw+4/WN0WzNqVfegG6JQMHiPP9iXEqGFYVgSZLK8flNYafDsz7FgT4K+/4AxxZLFwj6
|
||||
mhv5FnKYJxQDSuEX1b3S54OYObhuyWJnGpPGLfPwfJ/quLWGTNO+ZIAeb5KMAmBdnEKV
|
||||
rF1QTgCoPPMsWsShNKe8BsfaSKCMVGiSbi90ZFx8J0HHcn4GpbXrkYUuLSCcm0F4KYI7
|
||||
fQQw==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=sM28HXat3Ro78N+fdELj5tA2TTORYcmSJRB7y0xn668=;
|
||||
b=RiLWz/T/zcexV2Bsbw7YiZb7BINvMGTgl79XdA6B/OHzniNtpaj8nGzPvt6kerrgat
|
||||
ur0TSQPmxqyehHvbKNQ7mbs/PTvniAuwd45+Ub0Vv+9NgoF9uTsNfAK7Vd4jQHOWOvhm
|
||||
m1E6fZ25eW7KaMDTCBmRrCvIXIblvOe8PuRRsZqiT991bZ5mnSFynpVrpRLetwouPyGk
|
||||
pSnxWX8BcM/e6hZIrC3KPP2PeXLt4ehMvZ9h9fIeH0DezONgDMKpjc0TdLhdm0Z+EAPP
|
||||
gLoBDsqcG45NgWLNP2KcFrcDXtjwD+f9JAiMZvrNFb7RI7F78RYvzjAuegAab8YW/u+o
|
||||
Nkzg==
|
||||
X-Gm-Message-State: AOAM530brY8KWy4SQHMkv1r6LKzek0Cq4xuuj7kcDTW0m3zhQz3OLAJt
|
||||
GTHrB+1mfPD6eAMjZFoSYPQ7AwnDTeo=
|
||||
X-Google-Smtp-Source: ABdhPJzZYSt4fmXD7VdJ6T+CnbKC2/TjZT+i4G4gEva1Omiq/qzC/4JrVYLGPq2Q22anUOeAEZWsql+skQ8=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a25:2308:: with SMTP id j8mr24384456ybj.474.1615622285438;
|
||||
Fri, 12 Mar 2021 23:58:05 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:40 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-8-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 07/14] mm/pagewalk.c: add pud_entry_post() for post-order traversals
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-8-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Add a new callback pud_entry_post() to struct mm_walk_ops so that page
|
||||
table walkers can visit the non-leaf PMD entries of a PUD entry after
|
||||
they have visited with the leaf PTE entries. This allows page table
|
||||
walkers who clear the accessed bit to take advantage of the last
|
||||
commit, in a similar way walk_pte_range() works for the PTE entries of
|
||||
a PMD entry: they only need to take PTL once to search all the child
|
||||
entries of a parent entry.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
include/linux/pagewalk.h | 4 ++++
|
||||
mm/pagewalk.c | 5 +++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/include/linux/pagewalk.h b/include/linux/pagewalk.h
|
||||
index b1cb6b753abb..2b68ae9d27d3 100644
|
||||
--- a/include/linux/pagewalk.h
|
||||
+++ b/include/linux/pagewalk.h
|
||||
@@ -11,6 +11,8 @@ struct mm_walk;
|
||||
* @pgd_entry: if set, called for each non-empty PGD (top-level) entry
|
||||
* @p4d_entry: if set, called for each non-empty P4D entry
|
||||
* @pud_entry: if set, called for each non-empty PUD entry
|
||||
+ * @pud_entry_post: if set, called for each non-empty PUD entry after
|
||||
+ * pmd_entry is called, for post-order traversal.
|
||||
* @pmd_entry: if set, called for each non-empty PMD entry
|
||||
* this handler is required to be able to handle
|
||||
* pmd_trans_huge() pmds. They may simply choose to
|
||||
@@ -41,6 +43,8 @@ struct mm_walk_ops {
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
int (*pud_entry)(pud_t *pud, unsigned long addr,
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
+ int (*pud_entry_post)(pud_t *pud, unsigned long addr,
|
||||
+ unsigned long next, struct mm_walk *walk);
|
||||
int (*pmd_entry)(pmd_t *pmd, unsigned long addr,
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
int (*pte_entry)(pte_t *pte, unsigned long addr,
|
||||
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
|
||||
index e81640d9f177..8ed1533f7eda 100644
|
||||
--- a/mm/pagewalk.c
|
||||
+++ b/mm/pagewalk.c
|
||||
@@ -160,6 +160,11 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
|
||||
err = walk_pmd_range(pud, addr, next, walk);
|
||||
if (err)
|
||||
break;
|
||||
+
|
||||
+ if (ops->pud_entry_post)
|
||||
+ err = ops->pud_entry_post(pud, addr, next, walk);
|
||||
+ if (err)
|
||||
+ break;
|
||||
} while (pud++, addr = next, addr != end);
|
||||
|
||||
return err;
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,311 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id CBC4DC4332D
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id B8A3D64ECE
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233468AbhCMH6l (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:41 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58990 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232705AbhCMH6I (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:08 -0500
|
||||
Received: from mail-qk1-x749.google.com (mail-qk1-x749.google.com [IPv6:2607:f8b0:4864:20::749])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5BF1C061761
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:07 -0800 (PST)
|
||||
Received: by mail-qk1-x749.google.com with SMTP id i188so19867209qkd.7
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:07 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=Y7HI6Iu8cEpN4/cKvfcV1g+GhNxN+RuODBCey3P9ub4=;
|
||||
b=Yxxt5mdzkudc9JV5Q09FDlj0cvp1kmfCXxaVjGD5K0eCTz/So1vsV5U0rgmXDgA+oo
|
||||
I0A6T+8UZJmQiHjXDXECTBckUL0jnXMRgRm7XVaG53YB34iWjqO40F4CKKEh9+/OoVRc
|
||||
G0AmzhscUbBJ/kam3+ejsn6XT8HmEmL1E1JV5ccYQd+ZntwFpRDTuwloc8JJwbzlOPz6
|
||||
/TmQCN3DlJawauHo+hK8esqlLBqlUo0Hc3ctZf6lI6jfTJ6xP19kgHg147e6ddt/0Gru
|
||||
4TRJ0LLQctTAhahAckLyUPLY8X0ofJQRXl5IFVx653ZZtEjcg5D9kIYZI+E7lddJGHTM
|
||||
WCSQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=Y7HI6Iu8cEpN4/cKvfcV1g+GhNxN+RuODBCey3P9ub4=;
|
||||
b=IhPlACmRhDBTPdmCHr0Oo1gV9hWUVpXkJQAh9lb+wytYYH7q3Kq7e+gKEZ0WvXAxP5
|
||||
HCkzZEXo0KeDSrSNfpNxh8YUrLoNxRyc67U6jB0GE7MI8jH4hpyANf1w/gGK8VfBJVP6
|
||||
HEd0MgT957tjxC4w5s2bFihlDvVujIJLQPYS+KO24VxvtbXLbjOayAHo8fH37VLxQ9U2
|
||||
nOkP5ADzrpG+7bfsI2JutdLL5J6KjOX/ix5YTdFiiS1XlDgF+UDcwUkwnju04+gULHCK
|
||||
SWuoOrT0DOfqlcQ4ome3RlXCB1UU/RCIPUUA06Y1a7h09m5zX6C1pqv0hnFWEk1Ehj8t
|
||||
sE+g==
|
||||
X-Gm-Message-State: AOAM533FjF5wfsmOCevkWqM2Zy0aRGz/n1+9ldB7hstZ21MlGbAcnU9S
|
||||
iwofL/8D5KT2K6tTLoKvMx4do3+86Ss=
|
||||
X-Google-Smtp-Source: ABdhPJwaHhrMfJqAPFj0pJIH6XbHZzHvvKGA6xcQa4GVhmvHaXMnKKa3+FEHfHSk+8gEmFOMqKskjMN6bjo=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:ad4:50c7:: with SMTP id e7mr1747988qvq.58.1615622286760;
|
||||
Fri, 12 Mar 2021 23:58:06 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:41 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-9-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 08/14] mm/vmscan.c: refactor shrink_node()
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-9-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Heuristics in shrink_node() are rather independent and can be
|
||||
refactored into a separate function to improve readability.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
mm/vmscan.c | 186 +++++++++++++++++++++++++++-------------------------
|
||||
1 file changed, 98 insertions(+), 88 deletions(-)
|
||||
|
||||
diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
index 562e87cbd7a1..1a24d2e0a4cb 100644
|
||||
--- a/mm/vmscan.c
|
||||
+++ b/mm/vmscan.c
|
||||
@@ -2224,6 +2224,103 @@ enum scan_balance {
|
||||
SCAN_FILE,
|
||||
};
|
||||
|
||||
+static void prepare_scan_count(pg_data_t *pgdat, struct scan_control *sc)
|
||||
+{
|
||||
+ unsigned long file;
|
||||
+ struct lruvec *target_lruvec;
|
||||
+
|
||||
+ target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat);
|
||||
+
|
||||
+ /*
|
||||
+ * Determine the scan balance between anon and file LRUs.
|
||||
+ */
|
||||
+ spin_lock_irq(&target_lruvec->lru_lock);
|
||||
+ sc->anon_cost = target_lruvec->anon_cost;
|
||||
+ sc->file_cost = target_lruvec->file_cost;
|
||||
+ spin_unlock_irq(&target_lruvec->lru_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * Target desirable inactive:active list ratios for the anon
|
||||
+ * and file LRU lists.
|
||||
+ */
|
||||
+ if (!sc->force_deactivate) {
|
||||
+ unsigned long refaults;
|
||||
+
|
||||
+ refaults = lruvec_page_state(target_lruvec,
|
||||
+ WORKINGSET_ACTIVATE_ANON);
|
||||
+ if (refaults != target_lruvec->refaults[0] ||
|
||||
+ inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
|
||||
+ sc->may_deactivate |= DEACTIVATE_ANON;
|
||||
+ else
|
||||
+ sc->may_deactivate &= ~DEACTIVATE_ANON;
|
||||
+
|
||||
+ /*
|
||||
+ * When refaults are being observed, it means a new
|
||||
+ * workingset is being established. Deactivate to get
|
||||
+ * rid of any stale active pages quickly.
|
||||
+ */
|
||||
+ refaults = lruvec_page_state(target_lruvec,
|
||||
+ WORKINGSET_ACTIVATE_FILE);
|
||||
+ if (refaults != target_lruvec->refaults[1] ||
|
||||
+ inactive_is_low(target_lruvec, LRU_INACTIVE_FILE))
|
||||
+ sc->may_deactivate |= DEACTIVATE_FILE;
|
||||
+ else
|
||||
+ sc->may_deactivate &= ~DEACTIVATE_FILE;
|
||||
+ } else
|
||||
+ sc->may_deactivate = DEACTIVATE_ANON | DEACTIVATE_FILE;
|
||||
+
|
||||
+ /*
|
||||
+ * If we have plenty of inactive file pages that aren't
|
||||
+ * thrashing, try to reclaim those first before touching
|
||||
+ * anonymous pages.
|
||||
+ */
|
||||
+ file = lruvec_page_state(target_lruvec, NR_INACTIVE_FILE);
|
||||
+ if (file >> sc->priority && !(sc->may_deactivate & DEACTIVATE_FILE))
|
||||
+ sc->cache_trim_mode = 1;
|
||||
+ else
|
||||
+ sc->cache_trim_mode = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Prevent the reclaimer from falling into the cache trap: as
|
||||
+ * cache pages start out inactive, every cache fault will tip
|
||||
+ * the scan balance towards the file LRU. And as the file LRU
|
||||
+ * shrinks, so does the window for rotation from references.
|
||||
+ * This means we have a runaway feedback loop where a tiny
|
||||
+ * thrashing file LRU becomes infinitely more attractive than
|
||||
+ * anon pages. Try to detect this based on file LRU size.
|
||||
+ */
|
||||
+ if (!cgroup_reclaim(sc)) {
|
||||
+ unsigned long total_high_wmark = 0;
|
||||
+ unsigned long free, anon;
|
||||
+ int z;
|
||||
+
|
||||
+ free = sum_zone_node_page_state(pgdat->node_id, NR_FREE_PAGES);
|
||||
+ file = node_page_state(pgdat, NR_ACTIVE_FILE) +
|
||||
+ node_page_state(pgdat, NR_INACTIVE_FILE);
|
||||
+
|
||||
+ for (z = 0; z < MAX_NR_ZONES; z++) {
|
||||
+ struct zone *zone = &pgdat->node_zones[z];
|
||||
+
|
||||
+ if (!managed_zone(zone))
|
||||
+ continue;
|
||||
+
|
||||
+ total_high_wmark += high_wmark_pages(zone);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Consider anon: if that's low too, this isn't a
|
||||
+ * runaway file reclaim problem, but rather just
|
||||
+ * extreme pressure. Reclaim as per usual then.
|
||||
+ */
|
||||
+ anon = node_page_state(pgdat, NR_INACTIVE_ANON);
|
||||
+
|
||||
+ sc->file_is_tiny =
|
||||
+ file + free <= total_high_wmark &&
|
||||
+ !(sc->may_deactivate & DEACTIVATE_ANON) &&
|
||||
+ anon >> sc->priority;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Determine how aggressively the anon and file LRU lists should be
|
||||
* scanned. The relative value of each set of LRU lists is determined
|
||||
@@ -2669,7 +2766,6 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
|
||||
unsigned long nr_reclaimed, nr_scanned;
|
||||
struct lruvec *target_lruvec;
|
||||
bool reclaimable = false;
|
||||
- unsigned long file;
|
||||
|
||||
target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat);
|
||||
|
||||
@@ -2679,93 +2775,7 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
|
||||
nr_reclaimed = sc->nr_reclaimed;
|
||||
nr_scanned = sc->nr_scanned;
|
||||
|
||||
- /*
|
||||
- * Determine the scan balance between anon and file LRUs.
|
||||
- */
|
||||
- spin_lock_irq(&target_lruvec->lru_lock);
|
||||
- sc->anon_cost = target_lruvec->anon_cost;
|
||||
- sc->file_cost = target_lruvec->file_cost;
|
||||
- spin_unlock_irq(&target_lruvec->lru_lock);
|
||||
-
|
||||
- /*
|
||||
- * Target desirable inactive:active list ratios for the anon
|
||||
- * and file LRU lists.
|
||||
- */
|
||||
- if (!sc->force_deactivate) {
|
||||
- unsigned long refaults;
|
||||
-
|
||||
- refaults = lruvec_page_state(target_lruvec,
|
||||
- WORKINGSET_ACTIVATE_ANON);
|
||||
- if (refaults != target_lruvec->refaults[0] ||
|
||||
- inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
|
||||
- sc->may_deactivate |= DEACTIVATE_ANON;
|
||||
- else
|
||||
- sc->may_deactivate &= ~DEACTIVATE_ANON;
|
||||
-
|
||||
- /*
|
||||
- * When refaults are being observed, it means a new
|
||||
- * workingset is being established. Deactivate to get
|
||||
- * rid of any stale active pages quickly.
|
||||
- */
|
||||
- refaults = lruvec_page_state(target_lruvec,
|
||||
- WORKINGSET_ACTIVATE_FILE);
|
||||
- if (refaults != target_lruvec->refaults[1] ||
|
||||
- inactive_is_low(target_lruvec, LRU_INACTIVE_FILE))
|
||||
- sc->may_deactivate |= DEACTIVATE_FILE;
|
||||
- else
|
||||
- sc->may_deactivate &= ~DEACTIVATE_FILE;
|
||||
- } else
|
||||
- sc->may_deactivate = DEACTIVATE_ANON | DEACTIVATE_FILE;
|
||||
-
|
||||
- /*
|
||||
- * If we have plenty of inactive file pages that aren't
|
||||
- * thrashing, try to reclaim those first before touching
|
||||
- * anonymous pages.
|
||||
- */
|
||||
- file = lruvec_page_state(target_lruvec, NR_INACTIVE_FILE);
|
||||
- if (file >> sc->priority && !(sc->may_deactivate & DEACTIVATE_FILE))
|
||||
- sc->cache_trim_mode = 1;
|
||||
- else
|
||||
- sc->cache_trim_mode = 0;
|
||||
-
|
||||
- /*
|
||||
- * Prevent the reclaimer from falling into the cache trap: as
|
||||
- * cache pages start out inactive, every cache fault will tip
|
||||
- * the scan balance towards the file LRU. And as the file LRU
|
||||
- * shrinks, so does the window for rotation from references.
|
||||
- * This means we have a runaway feedback loop where a tiny
|
||||
- * thrashing file LRU becomes infinitely more attractive than
|
||||
- * anon pages. Try to detect this based on file LRU size.
|
||||
- */
|
||||
- if (!cgroup_reclaim(sc)) {
|
||||
- unsigned long total_high_wmark = 0;
|
||||
- unsigned long free, anon;
|
||||
- int z;
|
||||
-
|
||||
- free = sum_zone_node_page_state(pgdat->node_id, NR_FREE_PAGES);
|
||||
- file = node_page_state(pgdat, NR_ACTIVE_FILE) +
|
||||
- node_page_state(pgdat, NR_INACTIVE_FILE);
|
||||
-
|
||||
- for (z = 0; z < MAX_NR_ZONES; z++) {
|
||||
- struct zone *zone = &pgdat->node_zones[z];
|
||||
- if (!managed_zone(zone))
|
||||
- continue;
|
||||
-
|
||||
- total_high_wmark += high_wmark_pages(zone);
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Consider anon: if that's low too, this isn't a
|
||||
- * runaway file reclaim problem, but rather just
|
||||
- * extreme pressure. Reclaim as per usual then.
|
||||
- */
|
||||
- anon = node_page_state(pgdat, NR_INACTIVE_ANON);
|
||||
-
|
||||
- sc->file_is_tiny =
|
||||
- file + free <= total_high_wmark &&
|
||||
- !(sc->may_deactivate & DEACTIVATE_ANON) &&
|
||||
- anon >> sc->priority;
|
||||
- }
|
||||
+ prepare_scan_count(pgdat, sc);
|
||||
|
||||
shrink_node_memcgs(pgdat, sc);
|
||||
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,749 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 0360FC4332E
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id E377164F1E
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:06 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233512AbhCMH6m (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:42 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58996 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232709AbhCMH6J (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:09 -0500
|
||||
Received: from mail-qk1-x749.google.com (mail-qk1-x749.google.com [IPv6:2607:f8b0:4864:20::749])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0386C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:08 -0800 (PST)
|
||||
Received: by mail-qk1-x749.google.com with SMTP id h134so19965073qke.1
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:08 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=7aNjMZwXzkZhXFvRmRWQJ8BQ+8lusUpXBFHauhX2ubg=;
|
||||
b=rXTENBp2Eom7kHIkgQlwaM0zAjOFi5gmzyQ9fUwZQJp4tjb12IZlxofeTMBMfAGa/r
|
||||
L4Ghc3L00KAFuV2LaP7uyJH7AsU4qMsIGq1k1CkPhOMdO7EV4BDTbgd4vEf68FTu94xi
|
||||
vXrlWZYOskUlSCRkRuZtatqD65DIQyZkjMKdk2hKBnk6QJmcpPB6RWsgv88u3qVxEBZx
|
||||
iiEhsjInkvzH6qtUYApIn6cqLI7Fd+8G1HrkDMmx13q4PXkdeunv1Az0GMeKsUNzGYYs
|
||||
e4N6HA5c9v+Un/TrJ4yGhAbzwYgJSTU4Xrzr5/9QWPKNcFUkXgh0KosPnfdwtEviCEBv
|
||||
6pmg==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=7aNjMZwXzkZhXFvRmRWQJ8BQ+8lusUpXBFHauhX2ubg=;
|
||||
b=YWegDePJI84B+MDTMEsT3ncwRQ6xqfLVLoxaVcjlpDCwizTWwtdyaGlleP04JZ5N+5
|
||||
AkfxqK0DQUXAyBBm7v7dckpiAm/jUldpE5n9Uh4ZmUf6oJt35HCt8C2aWgCxnV6YH3xL
|
||||
86xAS1GV/vZb1DaCjG3Fa6mqH6EJPd/c9xZPVGxYnPYoLGKZDyI2j04nHrPyKye2NZMZ
|
||||
HQohID0ijQkEqVBAuj4H9CyNS/XwXkM24UKVFyYk6hKAmmMp/Na4vDYy5LN2rRariQhj
|
||||
uPMou6WiKPb6Ph6mcd35an6LnCUHgzKHE2Tu+AnxXcrqTu9ijLJ5E6/FY2cCcrIEXK7S
|
||||
VoHQ==
|
||||
X-Gm-Message-State: AOAM530An7ZbSyg9gdVA41zNIb/3lnpDD6ALzchYWG8q+sQY4pqkltfs
|
||||
r5qU0vNqoKeYC+YKblti/xtfb5zboKM=
|
||||
X-Google-Smtp-Source: ABdhPJxXAZ3oX16iFANwEv0b7ybctnsmZAK24tAjZNdUXRU2Fm50sCFyGpIqOrn3ll+aJz5mcnB7+tMAtOQ=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a0c:b8a3:: with SMTP id y35mr15828724qvf.23.1615622288067;
|
||||
Fri, 12 Mar 2021 23:58:08 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:42 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-10-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 09/14] mm: multigenerational lru: mm_struct list
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-10-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Add an infrastructure that maintains either a system-wide mm_struct
|
||||
list or per-memcg mm_struct lists. Multiple threads can concurrently
|
||||
work on the same mm_struct list, and each of them will be given a
|
||||
different mm_struct. Those who finish early can optionally wait on the
|
||||
rest after the iterator has reached the end of the list.
|
||||
|
||||
This infrastructure also tracks whether an mm_struct is being used on
|
||||
any CPUs or has been used since the last time a worker looked at it.
|
||||
In other words, workers will not be given an mm_struct that belongs to
|
||||
a process that has been sleeping.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
fs/exec.c | 2 +
|
||||
include/linux/memcontrol.h | 4 +
|
||||
include/linux/mm_types.h | 135 +++++++++++++++++++
|
||||
include/linux/mmzone.h | 2 -
|
||||
kernel/exit.c | 1 +
|
||||
kernel/fork.c | 10 ++
|
||||
kernel/kthread.c | 1 +
|
||||
kernel/sched/core.c | 2 +
|
||||
mm/memcontrol.c | 28 ++++
|
||||
mm/vmscan.c | 263 +++++++++++++++++++++++++++++++++++++
|
||||
10 files changed, 446 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/fs/exec.c b/fs/exec.c
|
||||
index 18594f11c31f..c691d4d7720c 100644
|
||||
--- a/fs/exec.c
|
||||
+++ b/fs/exec.c
|
||||
@@ -1008,6 +1008,7 @@ static int exec_mmap(struct mm_struct *mm)
|
||||
active_mm = tsk->active_mm;
|
||||
tsk->active_mm = mm;
|
||||
tsk->mm = mm;
|
||||
+ lru_gen_add_mm(mm);
|
||||
/*
|
||||
* This prevents preemption while active_mm is being loaded and
|
||||
* it and mm are being updated, which could cause problems for
|
||||
@@ -1018,6 +1019,7 @@ static int exec_mmap(struct mm_struct *mm)
|
||||
if (!IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
|
||||
local_irq_enable();
|
||||
activate_mm(active_mm, mm);
|
||||
+ lru_gen_switch_mm(active_mm, mm);
|
||||
if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
|
||||
local_irq_enable();
|
||||
tsk->mm->vmacache_seqnum = 0;
|
||||
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
|
||||
index f325aeb4b4e8..591557c5b7e2 100644
|
||||
--- a/include/linux/memcontrol.h
|
||||
+++ b/include/linux/memcontrol.h
|
||||
@@ -335,6 +335,10 @@ struct mem_cgroup {
|
||||
struct deferred_split deferred_split_queue;
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_LRU_GEN
|
||||
+ struct lru_gen_mm_list *mm_list;
|
||||
+#endif
|
||||
+
|
||||
struct mem_cgroup_per_node *nodeinfo[0];
|
||||
/* WARNING: nodeinfo must be the last member here */
|
||||
};
|
||||
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
|
||||
index 0974ad501a47..b8a038a016f2 100644
|
||||
--- a/include/linux/mm_types.h
|
||||
+++ b/include/linux/mm_types.h
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <linux/page-flags-layout.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/seqlock.h>
|
||||
+#include <linux/nodemask.h>
|
||||
+#include <linux/mmdebug.h>
|
||||
|
||||
#include <asm/mmu.h>
|
||||
|
||||
@@ -382,6 +384,8 @@ struct core_state {
|
||||
struct completion startup;
|
||||
};
|
||||
|
||||
+#define ANON_AND_FILE 2
|
||||
+
|
||||
struct kioctx_table;
|
||||
struct mm_struct {
|
||||
struct {
|
||||
@@ -560,6 +564,22 @@ struct mm_struct {
|
||||
|
||||
#ifdef CONFIG_IOMMU_SUPPORT
|
||||
u32 pasid;
|
||||
+#endif
|
||||
+#ifdef CONFIG_LRU_GEN
|
||||
+ struct {
|
||||
+ /* node of a global or per-memcg mm list */
|
||||
+ struct list_head list;
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ /* points to memcg of the owner task above */
|
||||
+ struct mem_cgroup *memcg;
|
||||
+#endif
|
||||
+ /* indicates this mm has been used since last walk */
|
||||
+ nodemask_t nodes[ANON_AND_FILE];
|
||||
+#ifndef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
|
||||
+ /* number of cpus that are using this mm */
|
||||
+ atomic_t nr_cpus;
|
||||
+#endif
|
||||
+ } lru_gen;
|
||||
#endif
|
||||
} __randomize_layout;
|
||||
|
||||
@@ -587,6 +607,121 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
|
||||
return (struct cpumask *)&mm->cpu_bitmap;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_LRU_GEN
|
||||
+
|
||||
+struct lru_gen_mm_list {
|
||||
+ /* head of a global or per-memcg mm list */
|
||||
+ struct list_head head;
|
||||
+ /* protects the list */
|
||||
+ spinlock_t lock;
|
||||
+ struct {
|
||||
+ /* set to max_seq after each round of walk */
|
||||
+ unsigned long cur_seq;
|
||||
+ /* next mm on the list to walk */
|
||||
+ struct list_head *iter;
|
||||
+ /* to wait for last worker to finish */
|
||||
+ struct wait_queue_head wait;
|
||||
+ /* number of concurrent workers */
|
||||
+ int nr_workers;
|
||||
+ } nodes[0];
|
||||
+};
|
||||
+
|
||||
+void lru_gen_init_mm(struct mm_struct *mm);
|
||||
+void lru_gen_add_mm(struct mm_struct *mm);
|
||||
+void lru_gen_del_mm(struct mm_struct *mm);
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+int lru_gen_alloc_mm_list(struct mem_cgroup *memcg);
|
||||
+void lru_gen_free_mm_list(struct mem_cgroup *memcg);
|
||||
+void lru_gen_migrate_mm(struct mm_struct *mm);
|
||||
+#endif
|
||||
+
|
||||
+/*
|
||||
+ * Track usage so mms that haven't been used since last walk can be skipped.
|
||||
+ *
|
||||
+ * This function introduces a theoretical overhead for each mm switch, but it
|
||||
+ * hasn't been measurable.
|
||||
+ */
|
||||
+static inline void lru_gen_switch_mm(struct mm_struct *old, struct mm_struct *new)
|
||||
+{
|
||||
+ int file;
|
||||
+
|
||||
+ /* exclude init_mm, efi_mm, etc. */
|
||||
+ if (!core_kernel_data((unsigned long)old)) {
|
||||
+ VM_BUG_ON(old == &init_mm);
|
||||
+
|
||||
+ for (file = 0; file < ANON_AND_FILE; file++)
|
||||
+ nodes_setall(old->lru_gen.nodes[file]);
|
||||
+
|
||||
+#ifndef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
|
||||
+ atomic_dec(&old->lru_gen.nr_cpus);
|
||||
+ VM_BUG_ON_MM(atomic_read(&old->lru_gen.nr_cpus) < 0, old);
|
||||
+#endif
|
||||
+ } else
|
||||
+ VM_BUG_ON_MM(READ_ONCE(old->lru_gen.list.prev) ||
|
||||
+ READ_ONCE(old->lru_gen.list.next), old);
|
||||
+
|
||||
+ if (!core_kernel_data((unsigned long)new)) {
|
||||
+ VM_BUG_ON(new == &init_mm);
|
||||
+
|
||||
+#ifndef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
|
||||
+ atomic_inc(&new->lru_gen.nr_cpus);
|
||||
+ VM_BUG_ON_MM(atomic_read(&new->lru_gen.nr_cpus) < 0, new);
|
||||
+#endif
|
||||
+ } else
|
||||
+ VM_BUG_ON_MM(READ_ONCE(new->lru_gen.list.prev) ||
|
||||
+ READ_ONCE(new->lru_gen.list.next), new);
|
||||
+}
|
||||
+
|
||||
+/* Returns whether the mm is being used on any cpus. */
|
||||
+static inline bool lru_gen_mm_is_active(struct mm_struct *mm)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
|
||||
+ return !cpumask_empty(mm_cpumask(mm));
|
||||
+#else
|
||||
+ return atomic_read(&mm->lru_gen.nr_cpus);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#else /* CONFIG_LRU_GEN */
|
||||
+
|
||||
+static inline void lru_gen_init_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void lru_gen_add_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void lru_gen_del_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+static inline int lru_gen_alloc_mm_list(struct mem_cgroup *memcg)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void lru_gen_free_mm_list(struct mem_cgroup *memcg)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void lru_gen_migrate_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static inline void lru_gen_switch_mm(struct mm_struct *old, struct mm_struct *new)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline bool lru_gen_mm_is_active(struct mm_struct *mm)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+#endif /* CONFIG_LRU_GEN */
|
||||
+
|
||||
struct mmu_gather;
|
||||
extern void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm);
|
||||
extern void tlb_gather_mmu_fullmm(struct mmu_gather *tlb, struct mm_struct *mm);
|
||||
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
|
||||
index 47946cec7584..a99a1050565a 100644
|
||||
--- a/include/linux/mmzone.h
|
||||
+++ b/include/linux/mmzone.h
|
||||
@@ -285,8 +285,6 @@ static inline bool is_active_lru(enum lru_list lru)
|
||||
return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE);
|
||||
}
|
||||
|
||||
-#define ANON_AND_FILE 2
|
||||
-
|
||||
enum lruvec_flags {
|
||||
LRUVEC_CONGESTED, /* lruvec has many dirty pages
|
||||
* backed by a congested BDI
|
||||
diff --git a/kernel/exit.c b/kernel/exit.c
|
||||
index 04029e35e69a..e4292717ce37 100644
|
||||
--- a/kernel/exit.c
|
||||
+++ b/kernel/exit.c
|
||||
@@ -422,6 +422,7 @@ void mm_update_next_owner(struct mm_struct *mm)
|
||||
goto retry;
|
||||
}
|
||||
WRITE_ONCE(mm->owner, c);
|
||||
+ lru_gen_migrate_mm(mm);
|
||||
task_unlock(c);
|
||||
put_task_struct(c);
|
||||
}
|
||||
diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
index d3171e8e88e5..e261b797955d 100644
|
||||
--- a/kernel/fork.c
|
||||
+++ b/kernel/fork.c
|
||||
@@ -665,6 +665,7 @@ static void check_mm(struct mm_struct *mm)
|
||||
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
|
||||
VM_BUG_ON_MM(mm->pmd_huge_pte, mm);
|
||||
#endif
|
||||
+ VM_BUG_ON_MM(lru_gen_mm_is_active(mm), mm);
|
||||
}
|
||||
|
||||
#define allocate_mm() (kmem_cache_alloc(mm_cachep, GFP_KERNEL))
|
||||
@@ -1047,6 +1048,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
|
||||
goto fail_nocontext;
|
||||
|
||||
mm->user_ns = get_user_ns(user_ns);
|
||||
+ lru_gen_init_mm(mm);
|
||||
return mm;
|
||||
|
||||
fail_nocontext:
|
||||
@@ -1089,6 +1091,7 @@ static inline void __mmput(struct mm_struct *mm)
|
||||
}
|
||||
if (mm->binfmt)
|
||||
module_put(mm->binfmt->module);
|
||||
+ lru_gen_del_mm(mm);
|
||||
mmdrop(mm);
|
||||
}
|
||||
|
||||
@@ -2513,6 +2516,13 @@ pid_t kernel_clone(struct kernel_clone_args *args)
|
||||
get_task_struct(p);
|
||||
}
|
||||
|
||||
+ if (IS_ENABLED(CONFIG_LRU_GEN) && !(clone_flags & CLONE_VM)) {
|
||||
+ /* lock p to synchronize with memcg migration */
|
||||
+ task_lock(p);
|
||||
+ lru_gen_add_mm(p->mm);
|
||||
+ task_unlock(p);
|
||||
+ }
|
||||
+
|
||||
wake_up_new_task(p);
|
||||
|
||||
/* forking complete and child started to run, tell ptracer */
|
||||
diff --git a/kernel/kthread.c b/kernel/kthread.c
|
||||
index 1578973c5740..8da7767bb06a 100644
|
||||
--- a/kernel/kthread.c
|
||||
+++ b/kernel/kthread.c
|
||||
@@ -1303,6 +1303,7 @@ void kthread_use_mm(struct mm_struct *mm)
|
||||
tsk->mm = mm;
|
||||
membarrier_update_current_mm(mm);
|
||||
switch_mm_irqs_off(active_mm, mm, tsk);
|
||||
+ lru_gen_switch_mm(active_mm, mm);
|
||||
local_irq_enable();
|
||||
task_unlock(tsk);
|
||||
#ifdef finish_arch_post_lock_switch
|
||||
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
||||
index ca2bb629595f..56274a14ce09 100644
|
||||
--- a/kernel/sched/core.c
|
||||
+++ b/kernel/sched/core.c
|
||||
@@ -4308,6 +4308,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
|
||||
* finish_task_switch()'s mmdrop().
|
||||
*/
|
||||
switch_mm_irqs_off(prev->active_mm, next->mm, next);
|
||||
+ lru_gen_switch_mm(prev->active_mm, next->mm);
|
||||
|
||||
if (!prev->mm) { // from kernel
|
||||
/* will mmdrop() in finish_task_switch(). */
|
||||
@@ -7599,6 +7600,7 @@ void idle_task_exit(void)
|
||||
|
||||
if (mm != &init_mm) {
|
||||
switch_mm(mm, &init_mm, current);
|
||||
+ lru_gen_switch_mm(mm, &init_mm);
|
||||
finish_arch_post_lock_switch();
|
||||
}
|
||||
|
||||
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
|
||||
index 845eec01ef9d..5836780fe138 100644
|
||||
--- a/mm/memcontrol.c
|
||||
+++ b/mm/memcontrol.c
|
||||
@@ -5209,6 +5209,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
|
||||
free_mem_cgroup_per_node_info(memcg, node);
|
||||
free_percpu(memcg->vmstats_percpu);
|
||||
free_percpu(memcg->vmstats_local);
|
||||
+ lru_gen_free_mm_list(memcg);
|
||||
kfree(memcg);
|
||||
}
|
||||
|
||||
@@ -5261,6 +5262,9 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
|
||||
if (alloc_mem_cgroup_per_node_info(memcg, node))
|
||||
goto fail;
|
||||
|
||||
+ if (lru_gen_alloc_mm_list(memcg))
|
||||
+ goto fail;
|
||||
+
|
||||
if (memcg_wb_domain_init(memcg, GFP_KERNEL))
|
||||
goto fail;
|
||||
|
||||
@@ -6165,6 +6169,29 @@ static void mem_cgroup_move_task(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_LRU_GEN
|
||||
+static void mem_cgroup_attach(struct cgroup_taskset *tset)
|
||||
+{
|
||||
+ struct cgroup_subsys_state *css;
|
||||
+ struct task_struct *task = NULL;
|
||||
+
|
||||
+ cgroup_taskset_for_each_leader(task, css, tset)
|
||||
+ ;
|
||||
+
|
||||
+ if (!task)
|
||||
+ return;
|
||||
+
|
||||
+ task_lock(task);
|
||||
+ if (task->mm && task->mm->owner == task)
|
||||
+ lru_gen_migrate_mm(task->mm);
|
||||
+ task_unlock(task);
|
||||
+}
|
||||
+#else
|
||||
+static void mem_cgroup_attach(struct cgroup_taskset *tset)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static int seq_puts_memcg_tunable(struct seq_file *m, unsigned long value)
|
||||
{
|
||||
if (value == PAGE_COUNTER_MAX)
|
||||
@@ -6505,6 +6532,7 @@ struct cgroup_subsys memory_cgrp_subsys = {
|
||||
.css_free = mem_cgroup_css_free,
|
||||
.css_reset = mem_cgroup_css_reset,
|
||||
.can_attach = mem_cgroup_can_attach,
|
||||
+ .attach = mem_cgroup_attach,
|
||||
.cancel_attach = mem_cgroup_cancel_attach,
|
||||
.post_attach = mem_cgroup_move_task,
|
||||
.dfl_cftypes = memory_files,
|
||||
diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
index 1a24d2e0a4cb..f7657ab0d4b7 100644
|
||||
--- a/mm/vmscan.c
|
||||
+++ b/mm/vmscan.c
|
||||
@@ -4314,3 +4314,266 @@ void check_move_unevictable_pages(struct pagevec *pvec)
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(check_move_unevictable_pages);
|
||||
+
|
||||
+#ifdef CONFIG_LRU_GEN
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * global and per-memcg mm list
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+/*
|
||||
+ * After pages are faulted in, they become the youngest generation. They must
|
||||
+ * go through aging process twice before they can be evicted. After first scan,
|
||||
+ * their accessed bit set during initial faults are cleared and they become the
|
||||
+ * second youngest generation. And second scan makes sure they haven't been used
|
||||
+ * since the first.
|
||||
+ */
|
||||
+#define MIN_NR_GENS 2
|
||||
+
|
||||
+static struct lru_gen_mm_list *global_mm_list;
|
||||
+
|
||||
+static struct lru_gen_mm_list *alloc_mm_list(void)
|
||||
+{
|
||||
+ int nid;
|
||||
+ struct lru_gen_mm_list *mm_list;
|
||||
+
|
||||
+ mm_list = kzalloc(struct_size(mm_list, nodes, nr_node_ids), GFP_KERNEL);
|
||||
+ if (!mm_list)
|
||||
+ return NULL;
|
||||
+
|
||||
+ INIT_LIST_HEAD(&mm_list->head);
|
||||
+ spin_lock_init(&mm_list->lock);
|
||||
+
|
||||
+ for_each_node(nid) {
|
||||
+ mm_list->nodes[nid].cur_seq = MIN_NR_GENS - 1;
|
||||
+ mm_list->nodes[nid].iter = &mm_list->head;
|
||||
+ init_waitqueue_head(&mm_list->nodes[nid].wait);
|
||||
+ }
|
||||
+
|
||||
+ return mm_list;
|
||||
+}
|
||||
+
|
||||
+static struct lru_gen_mm_list *get_mm_list(struct mem_cgroup *memcg)
|
||||
+{
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ if (!mem_cgroup_disabled())
|
||||
+ return memcg ? memcg->mm_list : root_mem_cgroup->mm_list;
|
||||
+#endif
|
||||
+ VM_BUG_ON(memcg);
|
||||
+
|
||||
+ return global_mm_list;
|
||||
+}
|
||||
+
|
||||
+void lru_gen_init_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+ int file;
|
||||
+
|
||||
+ INIT_LIST_HEAD(&mm->lru_gen.list);
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ mm->lru_gen.memcg = NULL;
|
||||
+#endif
|
||||
+#ifndef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
|
||||
+ atomic_set(&mm->lru_gen.nr_cpus, 0);
|
||||
+#endif
|
||||
+ for (file = 0; file < ANON_AND_FILE; file++)
|
||||
+ nodes_clear(mm->lru_gen.nodes[file]);
|
||||
+}
|
||||
+
|
||||
+void lru_gen_add_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+ struct mem_cgroup *memcg = get_mem_cgroup_from_mm(mm);
|
||||
+ struct lru_gen_mm_list *mm_list = get_mm_list(memcg);
|
||||
+
|
||||
+ VM_BUG_ON_MM(!list_empty(&mm->lru_gen.list), mm);
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ VM_BUG_ON_MM(mm->lru_gen.memcg, mm);
|
||||
+ WRITE_ONCE(mm->lru_gen.memcg, memcg);
|
||||
+#endif
|
||||
+ spin_lock(&mm_list->lock);
|
||||
+ list_add_tail(&mm->lru_gen.list, &mm_list->head);
|
||||
+ spin_unlock(&mm_list->lock);
|
||||
+}
|
||||
+
|
||||
+void lru_gen_del_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+ int nid;
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ struct lru_gen_mm_list *mm_list = get_mm_list(mm->lru_gen.memcg);
|
||||
+#else
|
||||
+ struct lru_gen_mm_list *mm_list = get_mm_list(NULL);
|
||||
+#endif
|
||||
+
|
||||
+ spin_lock(&mm_list->lock);
|
||||
+
|
||||
+ for_each_node(nid) {
|
||||
+ if (mm_list->nodes[nid].iter != &mm->lru_gen.list)
|
||||
+ continue;
|
||||
+
|
||||
+ mm_list->nodes[nid].iter = mm_list->nodes[nid].iter->next;
|
||||
+ if (mm_list->nodes[nid].iter == &mm_list->head)
|
||||
+ WRITE_ONCE(mm_list->nodes[nid].cur_seq,
|
||||
+ mm_list->nodes[nid].cur_seq + 1);
|
||||
+ }
|
||||
+
|
||||
+ list_del_init(&mm->lru_gen.list);
|
||||
+
|
||||
+ spin_unlock(&mm_list->lock);
|
||||
+
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ mem_cgroup_put(mm->lru_gen.memcg);
|
||||
+ WRITE_ONCE(mm->lru_gen.memcg, NULL);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+int lru_gen_alloc_mm_list(struct mem_cgroup *memcg)
|
||||
+{
|
||||
+ if (mem_cgroup_disabled())
|
||||
+ return 0;
|
||||
+
|
||||
+ memcg->mm_list = alloc_mm_list();
|
||||
+
|
||||
+ return memcg->mm_list ? 0 : -ENOMEM;
|
||||
+}
|
||||
+
|
||||
+void lru_gen_free_mm_list(struct mem_cgroup *memcg)
|
||||
+{
|
||||
+ kfree(memcg->mm_list);
|
||||
+ memcg->mm_list = NULL;
|
||||
+}
|
||||
+
|
||||
+void lru_gen_migrate_mm(struct mm_struct *mm)
|
||||
+{
|
||||
+ struct mem_cgroup *memcg;
|
||||
+
|
||||
+ lockdep_assert_held(&mm->owner->alloc_lock);
|
||||
+
|
||||
+ if (mem_cgroup_disabled())
|
||||
+ return;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ memcg = mem_cgroup_from_task(mm->owner);
|
||||
+ rcu_read_unlock();
|
||||
+ if (memcg == mm->lru_gen.memcg)
|
||||
+ return;
|
||||
+
|
||||
+ VM_BUG_ON_MM(!mm->lru_gen.memcg, mm);
|
||||
+ VM_BUG_ON_MM(list_empty(&mm->lru_gen.list), mm);
|
||||
+
|
||||
+ lru_gen_del_mm(mm);
|
||||
+ lru_gen_add_mm(mm);
|
||||
+}
|
||||
+
|
||||
+static bool mm_has_migrated(struct mm_struct *mm, struct mem_cgroup *memcg)
|
||||
+{
|
||||
+ return READ_ONCE(mm->lru_gen.memcg) != memcg;
|
||||
+}
|
||||
+#else
|
||||
+static bool mm_has_migrated(struct mm_struct *mm, struct mem_cgroup *memcg)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static bool should_skip_mm(struct mm_struct *mm, int nid, int swappiness)
|
||||
+{
|
||||
+ int file;
|
||||
+ unsigned long size = 0;
|
||||
+
|
||||
+ if (mm_is_oom_victim(mm))
|
||||
+ return true;
|
||||
+
|
||||
+ for (file = !swappiness; file < ANON_AND_FILE; file++) {
|
||||
+ if (lru_gen_mm_is_active(mm) || node_isset(nid, mm->lru_gen.nodes[file]))
|
||||
+ size += file ? get_mm_counter(mm, MM_FILEPAGES) :
|
||||
+ get_mm_counter(mm, MM_ANONPAGES) +
|
||||
+ get_mm_counter(mm, MM_SHMEMPAGES);
|
||||
+ }
|
||||
+
|
||||
+ if (size < SWAP_CLUSTER_MAX)
|
||||
+ return true;
|
||||
+
|
||||
+ return !mmget_not_zero(mm);
|
||||
+}
|
||||
+
|
||||
+/* To support multiple workers that concurrently walk mm list. */
|
||||
+static bool get_next_mm(struct lruvec *lruvec, unsigned long next_seq,
|
||||
+ int swappiness, struct mm_struct **iter)
|
||||
+{
|
||||
+ bool last = true;
|
||||
+ struct mm_struct *mm = NULL;
|
||||
+ int nid = lruvec_pgdat(lruvec)->node_id;
|
||||
+ struct mem_cgroup *memcg = lruvec_memcg(lruvec);
|
||||
+ struct lru_gen_mm_list *mm_list = get_mm_list(memcg);
|
||||
+
|
||||
+ if (*iter)
|
||||
+ mmput_async(*iter);
|
||||
+ else if (next_seq <= READ_ONCE(mm_list->nodes[nid].cur_seq))
|
||||
+ return false;
|
||||
+
|
||||
+ spin_lock(&mm_list->lock);
|
||||
+
|
||||
+ VM_BUG_ON(next_seq > mm_list->nodes[nid].cur_seq + 1);
|
||||
+ VM_BUG_ON(*iter && next_seq < mm_list->nodes[nid].cur_seq);
|
||||
+ VM_BUG_ON(*iter && !mm_list->nodes[nid].nr_workers);
|
||||
+
|
||||
+ if (next_seq <= mm_list->nodes[nid].cur_seq) {
|
||||
+ last = *iter;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (mm_list->nodes[nid].iter == &mm_list->head) {
|
||||
+ VM_BUG_ON(*iter || mm_list->nodes[nid].nr_workers);
|
||||
+ mm_list->nodes[nid].iter = mm_list->nodes[nid].iter->next;
|
||||
+ }
|
||||
+
|
||||
+ while (!mm && mm_list->nodes[nid].iter != &mm_list->head) {
|
||||
+ mm = list_entry(mm_list->nodes[nid].iter, struct mm_struct, lru_gen.list);
|
||||
+ mm_list->nodes[nid].iter = mm_list->nodes[nid].iter->next;
|
||||
+ if (should_skip_mm(mm, nid, swappiness))
|
||||
+ mm = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (mm_list->nodes[nid].iter == &mm_list->head)
|
||||
+ WRITE_ONCE(mm_list->nodes[nid].cur_seq,
|
||||
+ mm_list->nodes[nid].cur_seq + 1);
|
||||
+done:
|
||||
+ if (*iter && !mm)
|
||||
+ mm_list->nodes[nid].nr_workers--;
|
||||
+ if (!*iter && mm)
|
||||
+ mm_list->nodes[nid].nr_workers++;
|
||||
+
|
||||
+ last = last && !mm_list->nodes[nid].nr_workers &&
|
||||
+ mm_list->nodes[nid].iter == &mm_list->head;
|
||||
+
|
||||
+ spin_unlock(&mm_list->lock);
|
||||
+
|
||||
+ *iter = mm;
|
||||
+
|
||||
+ return last;
|
||||
+}
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * initialization
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+static int __init init_lru_gen(void)
|
||||
+{
|
||||
+ if (mem_cgroup_disabled()) {
|
||||
+ global_mm_list = alloc_mm_list();
|
||||
+ if (!global_mm_list) {
|
||||
+ pr_err("lru_gen: failed to allocate global mm list\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+};
|
||||
+/*
|
||||
+ * We want to run as early as possible because some debug code, e.g.,
|
||||
+ * dma_resv_lockdep(), calls mm_alloc() and mmput(). We only depend on mm_kobj,
|
||||
+ * which is initialized one stage earlier by postcore_initcall().
|
||||
+ */
|
||||
+arch_initcall(init_lru_gen);
|
||||
+
|
||||
+#endif /* CONFIG_LRU_GEN */
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,612 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 898B5C432C3
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 6BE1864ECE
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233554AbhCMH6p (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:45 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59010 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232974AbhCMH6L (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:11 -0500
|
||||
Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AED49C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:11 -0800 (PST)
|
||||
Received: by mail-qt1-x84a.google.com with SMTP id b21so19336130qtr.8
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:11 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=xqbmxYHaO3cMzT5bj/KOIzl+A4iyODs6ga8GzAKSrkE=;
|
||||
b=aCMPh4sfMlM3e6I+5or6zJlbHk6bJJ366JgVLE0jRyU2R9ZqTAdl/pzm6yajVT6ycB
|
||||
R3xLH3mN1h4Agtzp3ZKjLdBAoR0i0R0R6lzXQljBVIbOuqUZFY+sw3o8WmPkGc03xc2m
|
||||
dr44s/QwksFpUKxra33PNDauwhk0aM45ZbRd238UtPStswmrshOSmIlfZiRKTC4jSk1B
|
||||
IT5xjTbNazZfQOZvoiY7Q3k+uwbArdxbxTXjz8ad9h7O5bQfF9wGt4VgjerJbWQKhTRU
|
||||
zgbLNXljWtIdgOpRYmaNN+huMS6V5KkWhB+tZ5LkJGhbn+JmFhmrfjMn35Xnhql3Eveu
|
||||
q92A==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=xqbmxYHaO3cMzT5bj/KOIzl+A4iyODs6ga8GzAKSrkE=;
|
||||
b=ELwP/ih5rcnRV8ilH4wHoagohM2fYPTmpUPvhQxKwiuGY8hsFrPo23R7PzwR30oiWI
|
||||
VctwtgGSRFQFOyfcWEPNP4SMqwwIk1eu8glqg6CQWKa87rY721qEk0JRsgjewFSqdoTI
|
||||
pKd+k+VBiLUxlIqwPjnBAqVby7cJUv4e/5BOpOxLQJJh+spTjfp7T679SBSky3ro/JqC
|
||||
EID5nP4xORL+8LLUSfsRJn1CTWks+GWRIh0JOE/gxlIb9DhVYxCv8PRv2CA2pjIrDXjk
|
||||
3nxSdtaSAsInb0PAzpAG4+NVKF1suSWoJNb8d7fOob5HfXhA0/1aBLU8JsYpZdHS3oQL
|
||||
ddhw==
|
||||
X-Gm-Message-State: AOAM5319lFA9q7zjycOKH1TFLtjK6rHjUIfzRtUZRSmbTbvpAGZvBnqr
|
||||
cx6R08ZkL0PPGp5qZ/enqEaNYC+EDX8=
|
||||
X-Google-Smtp-Source: ABdhPJx1/5VDYsBrZetaVUsn197WpRCAdLjUCneommYhd37knsedDkkTX9reu4Vy54B+q98cUeZMGTzp9xY=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:ad4:4581:: with SMTP id x1mr1753140qvu.9.1615622290851;
|
||||
Fri, 12 Mar 2021 23:58:10 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:44 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-12-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 11/14] mm: multigenerational lru: page activation
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-12-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
In the page fault path, we want to add pages to the per-zone lists
|
||||
index by max_seq as they cannot be evicted without going through
|
||||
the aging first. For anon pages, we rename
|
||||
lru_cache_add_inactive_or_unevictable() to lru_cache_add_page_vma()
|
||||
and add a new parameter, which is set to true in the page fault path,
|
||||
to indicate whether they should be added to the per-zone lists index
|
||||
by max_seq. For page/swap cache, since we cannot differentiate the
|
||||
page fault path from the read ahead path at the time we call
|
||||
lru_cache_add() in add_to_page_cache_lru() and
|
||||
__read_swap_cache_async(), we have to add a new function
|
||||
lru_gen_activate_page(), which is essentially activate_page(), to move
|
||||
pages to the per-zone lists indexed by max_seq at a later time.
|
||||
Hopefully we would find pages we want to activate in lru_pvecs.lru_add
|
||||
and simply set PageActive() on them without having to actually move
|
||||
them.
|
||||
|
||||
In the reclaim path, pages mapped around a referenced PTE may also
|
||||
have been referenced due to spatial locality. We add a new function
|
||||
lru_gen_scan_around() to scan the vicinity of such a PTE.
|
||||
|
||||
In addition, we add a new function page_is_active() to tell whether a
|
||||
page is active. We cannot use PageActive() because it is only set on
|
||||
active pages while they are not on multigenerational lru. It is
|
||||
cleared while pages are on multigenerational lru, in order to spare
|
||||
the aging the trouble of clearing it when an active generation becomes
|
||||
inactive. Internally, page_is_active() compares the generation number
|
||||
of a page with max_seq and max_seq-1, which are active generations and
|
||||
protected from the eviction. Other generations, which may or may not
|
||||
exist, are inactive.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
fs/proc/task_mmu.c | 3 ++-
|
||||
include/linux/mm_inline.h | 52 ++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/mmzone.h | 6 +++++
|
||||
include/linux/swap.h | 4 +--
|
||||
kernel/events/uprobes.c | 2 +-
|
||||
mm/huge_memory.c | 2 +-
|
||||
mm/khugepaged.c | 2 +-
|
||||
mm/memory.c | 14 +++++++----
|
||||
mm/migrate.c | 2 +-
|
||||
mm/rmap.c | 6 +++++
|
||||
mm/swap.c | 26 +++++++++++--------
|
||||
mm/swapfile.c | 2 +-
|
||||
mm/userfaultfd.c | 2 +-
|
||||
mm/vmscan.c | 53 ++++++++++++++++++++++++++++++++++++++-
|
||||
14 files changed, 150 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
|
||||
index 3cec6fbef725..7cd173710e76 100644
|
||||
--- a/fs/proc/task_mmu.c
|
||||
+++ b/fs/proc/task_mmu.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pkeys.h>
|
||||
+#include <linux/mm_inline.h>
|
||||
|
||||
#include <asm/elf.h>
|
||||
#include <asm/tlb.h>
|
||||
@@ -1720,7 +1721,7 @@ static void gather_stats(struct page *page, struct numa_maps *md, int pte_dirty,
|
||||
if (PageSwapCache(page))
|
||||
md->swapcache += nr_pages;
|
||||
|
||||
- if (PageActive(page) || PageUnevictable(page))
|
||||
+ if (PageUnevictable(page) || page_is_active(compound_head(page), NULL))
|
||||
md->active += nr_pages;
|
||||
|
||||
if (PageWriteback(page))
|
||||
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
|
||||
index 2d306cab36bc..a1a382418fc4 100644
|
||||
--- a/include/linux/mm_inline.h
|
||||
+++ b/include/linux/mm_inline.h
|
||||
@@ -116,6 +116,49 @@ static inline int page_lru_gen(struct page *page)
|
||||
return ((READ_ONCE(page->flags) & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
|
||||
}
|
||||
|
||||
+/* This function works regardless whether multigenerational lru is enabled. */
|
||||
+static inline bool page_is_active(struct page *page, struct lruvec *lruvec)
|
||||
+{
|
||||
+ struct mem_cgroup *memcg;
|
||||
+ int gen = page_lru_gen(page);
|
||||
+ bool active = false;
|
||||
+
|
||||
+ VM_BUG_ON_PAGE(PageTail(page), page);
|
||||
+
|
||||
+ if (gen < 0)
|
||||
+ return PageActive(page);
|
||||
+
|
||||
+ if (lruvec) {
|
||||
+ VM_BUG_ON_PAGE(PageUnevictable(page), page);
|
||||
+ VM_BUG_ON_PAGE(PageActive(page), page);
|
||||
+ lockdep_assert_held(&lruvec->lru_lock);
|
||||
+
|
||||
+ return lru_gen_is_active(lruvec, gen);
|
||||
+ }
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ memcg = page_memcg_rcu(page);
|
||||
+ lruvec = mem_cgroup_lruvec(memcg, page_pgdat(page));
|
||||
+ active = lru_gen_is_active(lruvec, gen);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return active;
|
||||
+}
|
||||
+
|
||||
+/* Activate a page from page cache or swap cache after it's mapped. */
|
||||
+static inline void lru_gen_activate_page(struct page *page, struct vm_area_struct *vma)
|
||||
+{
|
||||
+ if (!lru_gen_enabled() || PageActive(page))
|
||||
+ return;
|
||||
+
|
||||
+ if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL | VM_HUGETLB))
|
||||
+ return;
|
||||
+
|
||||
+ activate_page(page);
|
||||
+}
|
||||
+
|
||||
/* Update multigenerational lru sizes in addition to active/inactive lru sizes. */
|
||||
static inline void lru_gen_update_size(struct page *page, struct lruvec *lruvec,
|
||||
int old_gen, int new_gen)
|
||||
@@ -252,6 +295,15 @@ static inline bool lru_gen_enabled(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static inline bool page_is_active(struct page *page, struct lruvec *lruvec)
|
||||
+{
|
||||
+ return PageActive(page);
|
||||
+}
|
||||
+
|
||||
+static inline void lru_gen_activate_page(struct page *page, struct vm_area_struct *vma)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
static inline bool page_set_lru_gen(struct page *page, struct lruvec *lruvec, bool front)
|
||||
{
|
||||
return false;
|
||||
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
|
||||
index 173083bb846e..99156602cd06 100644
|
||||
--- a/include/linux/mmzone.h
|
||||
+++ b/include/linux/mmzone.h
|
||||
@@ -292,6 +292,7 @@ enum lruvec_flags {
|
||||
};
|
||||
|
||||
struct lruvec;
|
||||
+struct page_vma_mapped_walk;
|
||||
|
||||
#define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF)
|
||||
|
||||
@@ -328,6 +329,7 @@ struct lru_gen {
|
||||
|
||||
void lru_gen_init_lruvec(struct lruvec *lruvec);
|
||||
void lru_gen_set_state(bool enable, bool main, bool swap);
|
||||
+void lru_gen_scan_around(struct page_vma_mapped_walk *pvmw);
|
||||
|
||||
#else /* CONFIG_LRU_GEN */
|
||||
|
||||
@@ -339,6 +341,10 @@ static inline void lru_gen_set_state(bool enable, bool main, bool swap)
|
||||
{
|
||||
}
|
||||
|
||||
+static inline void lru_gen_scan_around(struct page_vma_mapped_walk *pvmw)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
#endif /* CONFIG_LRU_GEN */
|
||||
|
||||
struct lruvec {
|
||||
diff --git a/include/linux/swap.h b/include/linux/swap.h
|
||||
index de2bbbf181ba..0e7532c7db22 100644
|
||||
--- a/include/linux/swap.h
|
||||
+++ b/include/linux/swap.h
|
||||
@@ -350,8 +350,8 @@ extern void deactivate_page(struct page *page);
|
||||
extern void mark_page_lazyfree(struct page *page);
|
||||
extern void swap_setup(void);
|
||||
|
||||
-extern void lru_cache_add_inactive_or_unevictable(struct page *page,
|
||||
- struct vm_area_struct *vma);
|
||||
+extern void lru_cache_add_page_vma(struct page *page, struct vm_area_struct *vma,
|
||||
+ bool faulting);
|
||||
|
||||
/* linux/mm/vmscan.c */
|
||||
extern unsigned long zone_reclaimable_pages(struct zone *zone);
|
||||
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
|
||||
index 6addc9780319..4e93e5602723 100644
|
||||
--- a/kernel/events/uprobes.c
|
||||
+++ b/kernel/events/uprobes.c
|
||||
@@ -184,7 +184,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
|
||||
if (new_page) {
|
||||
get_page(new_page);
|
||||
page_add_new_anon_rmap(new_page, vma, addr, false);
|
||||
- lru_cache_add_inactive_or_unevictable(new_page, vma);
|
||||
+ lru_cache_add_page_vma(new_page, vma, false);
|
||||
} else
|
||||
/* no new page, just dec_mm_counter for old_page */
|
||||
dec_mm_counter(mm, MM_ANONPAGES);
|
||||
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
||||
index be9bf681313c..62e14da5264e 100644
|
||||
--- a/mm/huge_memory.c
|
||||
+++ b/mm/huge_memory.c
|
||||
@@ -637,7 +637,7 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
|
||||
entry = mk_huge_pmd(page, vma->vm_page_prot);
|
||||
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
|
||||
page_add_new_anon_rmap(page, vma, haddr, true);
|
||||
- lru_cache_add_inactive_or_unevictable(page, vma);
|
||||
+ lru_cache_add_page_vma(page, vma, true);
|
||||
pgtable_trans_huge_deposit(vma->vm_mm, vmf->pmd, pgtable);
|
||||
set_pmd_at(vma->vm_mm, haddr, vmf->pmd, entry);
|
||||
update_mmu_cache_pmd(vma, vmf->address, vmf->pmd);
|
||||
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
|
||||
index a7d6cb912b05..08a43910f232 100644
|
||||
--- a/mm/khugepaged.c
|
||||
+++ b/mm/khugepaged.c
|
||||
@@ -1199,7 +1199,7 @@ static void collapse_huge_page(struct mm_struct *mm,
|
||||
spin_lock(pmd_ptl);
|
||||
BUG_ON(!pmd_none(*pmd));
|
||||
page_add_new_anon_rmap(new_page, vma, address, true);
|
||||
- lru_cache_add_inactive_or_unevictable(new_page, vma);
|
||||
+ lru_cache_add_page_vma(new_page, vma, true);
|
||||
pgtable_trans_huge_deposit(mm, pmd, pgtable);
|
||||
set_pmd_at(mm, address, pmd, _pmd);
|
||||
update_mmu_cache_pmd(vma, address, pmd);
|
||||
diff --git a/mm/memory.c b/mm/memory.c
|
||||
index c8e357627318..7188607bddb9 100644
|
||||
--- a/mm/memory.c
|
||||
+++ b/mm/memory.c
|
||||
@@ -73,6 +73,7 @@
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/vmalloc.h>
|
||||
+#include <linux/mm_inline.h>
|
||||
|
||||
#include <trace/events/kmem.h>
|
||||
|
||||
@@ -845,7 +846,7 @@ copy_present_page(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma
|
||||
copy_user_highpage(new_page, page, addr, src_vma);
|
||||
__SetPageUptodate(new_page);
|
||||
page_add_new_anon_rmap(new_page, dst_vma, addr, false);
|
||||
- lru_cache_add_inactive_or_unevictable(new_page, dst_vma);
|
||||
+ lru_cache_add_page_vma(new_page, dst_vma, false);
|
||||
rss[mm_counter(new_page)]++;
|
||||
|
||||
/* All done, just insert the new page copy in the child */
|
||||
@@ -2913,7 +2914,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
|
||||
*/
|
||||
ptep_clear_flush_notify(vma, vmf->address, vmf->pte);
|
||||
page_add_new_anon_rmap(new_page, vma, vmf->address, false);
|
||||
- lru_cache_add_inactive_or_unevictable(new_page, vma);
|
||||
+ lru_cache_add_page_vma(new_page, vma, true);
|
||||
/*
|
||||
* We call the notify macro here because, when using secondary
|
||||
* mmu page tables (such as kvm shadow page tables), we want the
|
||||
@@ -3436,9 +3437,10 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
||||
/* ksm created a completely new copy */
|
||||
if (unlikely(page != swapcache && swapcache)) {
|
||||
page_add_new_anon_rmap(page, vma, vmf->address, false);
|
||||
- lru_cache_add_inactive_or_unevictable(page, vma);
|
||||
+ lru_cache_add_page_vma(page, vma, true);
|
||||
} else {
|
||||
do_page_add_anon_rmap(page, vma, vmf->address, exclusive);
|
||||
+ lru_gen_activate_page(page, vma);
|
||||
}
|
||||
|
||||
swap_free(entry);
|
||||
@@ -3582,7 +3584,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
|
||||
|
||||
inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
|
||||
page_add_new_anon_rmap(page, vma, vmf->address, false);
|
||||
- lru_cache_add_inactive_or_unevictable(page, vma);
|
||||
+ lru_cache_add_page_vma(page, vma, true);
|
||||
setpte:
|
||||
set_pte_at(vma->vm_mm, vmf->address, vmf->pte, entry);
|
||||
|
||||
@@ -3707,6 +3709,7 @@ vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page)
|
||||
|
||||
add_mm_counter(vma->vm_mm, mm_counter_file(page), HPAGE_PMD_NR);
|
||||
page_add_file_rmap(page, true);
|
||||
+ lru_gen_activate_page(page, vma);
|
||||
/*
|
||||
* deposit and withdraw with pmd lock held
|
||||
*/
|
||||
@@ -3750,10 +3753,11 @@ void do_set_pte(struct vm_fault *vmf, struct page *page, unsigned long addr)
|
||||
if (write && !(vma->vm_flags & VM_SHARED)) {
|
||||
inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
|
||||
page_add_new_anon_rmap(page, vma, addr, false);
|
||||
- lru_cache_add_inactive_or_unevictable(page, vma);
|
||||
+ lru_cache_add_page_vma(page, vma, true);
|
||||
} else {
|
||||
inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page));
|
||||
page_add_file_rmap(page, false);
|
||||
+ lru_gen_activate_page(page, vma);
|
||||
}
|
||||
set_pte_at(vma->vm_mm, addr, vmf->pte, entry);
|
||||
}
|
||||
diff --git a/mm/migrate.c b/mm/migrate.c
|
||||
index 62b81d5257aa..1064b03cac33 100644
|
||||
--- a/mm/migrate.c
|
||||
+++ b/mm/migrate.c
|
||||
@@ -3004,7 +3004,7 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate,
|
||||
inc_mm_counter(mm, MM_ANONPAGES);
|
||||
page_add_new_anon_rmap(page, vma, addr, false);
|
||||
if (!is_zone_device_page(page))
|
||||
- lru_cache_add_inactive_or_unevictable(page, vma);
|
||||
+ lru_cache_add_page_vma(page, vma, false);
|
||||
get_page(page);
|
||||
|
||||
if (flush) {
|
||||
diff --git a/mm/rmap.c b/mm/rmap.c
|
||||
index b0fc27e77d6d..a44f9ee74ee1 100644
|
||||
--- a/mm/rmap.c
|
||||
+++ b/mm/rmap.c
|
||||
@@ -72,6 +72,7 @@
|
||||
#include <linux/page_idle.h>
|
||||
#include <linux/memremap.h>
|
||||
#include <linux/userfaultfd_k.h>
|
||||
+#include <linux/mm_inline.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
@@ -792,6 +793,11 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma,
|
||||
}
|
||||
|
||||
if (pvmw.pte) {
|
||||
+ /* multigenerational lru exploits spatial locality */
|
||||
+ if (lru_gen_enabled() && pte_young(*pvmw.pte)) {
|
||||
+ lru_gen_scan_around(&pvmw);
|
||||
+ referenced++;
|
||||
+ }
|
||||
if (ptep_clear_flush_young_notify(vma, address,
|
||||
pvmw.pte)) {
|
||||
/*
|
||||
diff --git a/mm/swap.c b/mm/swap.c
|
||||
index bd10efe00684..7aa85004b490 100644
|
||||
--- a/mm/swap.c
|
||||
+++ b/mm/swap.c
|
||||
@@ -310,7 +310,7 @@ void lru_note_cost_page(struct page *page)
|
||||
|
||||
static void __activate_page(struct page *page, struct lruvec *lruvec)
|
||||
{
|
||||
- if (!PageActive(page) && !PageUnevictable(page)) {
|
||||
+ if (!PageUnevictable(page) && !page_is_active(page, lruvec)) {
|
||||
int nr_pages = thp_nr_pages(page);
|
||||
|
||||
del_page_from_lru_list(page, lruvec);
|
||||
@@ -341,7 +341,7 @@ static bool need_activate_page_drain(int cpu)
|
||||
static void activate_page_on_lru(struct page *page)
|
||||
{
|
||||
page = compound_head(page);
|
||||
- if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
|
||||
+ if (PageLRU(page) && !PageUnevictable(page) && !page_is_active(page, NULL)) {
|
||||
struct pagevec *pvec;
|
||||
|
||||
local_lock(&lru_pvecs.lock);
|
||||
@@ -435,7 +435,7 @@ void mark_page_accessed(struct page *page)
|
||||
* this list is never rotated or maintained, so marking an
|
||||
* evictable page accessed has no effect.
|
||||
*/
|
||||
- } else if (!PageActive(page)) {
|
||||
+ } else if (!page_is_active(page, NULL)) {
|
||||
activate_page(page);
|
||||
ClearPageReferenced(page);
|
||||
workingset_activation(page);
|
||||
@@ -471,15 +471,14 @@ void lru_cache_add(struct page *page)
|
||||
EXPORT_SYMBOL(lru_cache_add);
|
||||
|
||||
/**
|
||||
- * lru_cache_add_inactive_or_unevictable
|
||||
+ * lru_cache_add_page_vma
|
||||
* @page: the page to be added to LRU
|
||||
* @vma: vma in which page is mapped for determining reclaimability
|
||||
*
|
||||
- * Place @page on the inactive or unevictable LRU list, depending on its
|
||||
- * evictability.
|
||||
+ * Place @page on an LRU list, depending on its evictability.
|
||||
*/
|
||||
-void lru_cache_add_inactive_or_unevictable(struct page *page,
|
||||
- struct vm_area_struct *vma)
|
||||
+void lru_cache_add_page_vma(struct page *page, struct vm_area_struct *vma,
|
||||
+ bool faulting)
|
||||
{
|
||||
bool unevictable;
|
||||
|
||||
@@ -496,6 +495,11 @@ void lru_cache_add_inactive_or_unevictable(struct page *page,
|
||||
__mod_zone_page_state(page_zone(page), NR_MLOCK, nr_pages);
|
||||
count_vm_events(UNEVICTABLE_PGMLOCKED, nr_pages);
|
||||
}
|
||||
+
|
||||
+ /* multigenerational lru uses PageActive() to track page faults */
|
||||
+ if (lru_gen_enabled() && !unevictable && faulting)
|
||||
+ SetPageActive(page);
|
||||
+
|
||||
lru_cache_add(page);
|
||||
}
|
||||
|
||||
@@ -522,7 +526,7 @@ void lru_cache_add_inactive_or_unevictable(struct page *page,
|
||||
*/
|
||||
static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec)
|
||||
{
|
||||
- bool active = PageActive(page);
|
||||
+ bool active = page_is_active(page, lruvec);
|
||||
int nr_pages = thp_nr_pages(page);
|
||||
|
||||
if (PageUnevictable(page))
|
||||
@@ -562,7 +566,7 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec)
|
||||
|
||||
static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec)
|
||||
{
|
||||
- if (PageActive(page) && !PageUnevictable(page)) {
|
||||
+ if (!PageUnevictable(page) && page_is_active(page, lruvec)) {
|
||||
int nr_pages = thp_nr_pages(page);
|
||||
|
||||
del_page_from_lru_list(page, lruvec);
|
||||
@@ -676,7 +680,7 @@ void deactivate_file_page(struct page *page)
|
||||
*/
|
||||
void deactivate_page(struct page *page)
|
||||
{
|
||||
- if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) {
|
||||
+ if (PageLRU(page) && !PageUnevictable(page) && page_is_active(page, NULL)) {
|
||||
struct pagevec *pvec;
|
||||
|
||||
local_lock(&lru_pvecs.lock);
|
||||
diff --git a/mm/swapfile.c b/mm/swapfile.c
|
||||
index fe03cfeaa08f..c0956b3bde03 100644
|
||||
--- a/mm/swapfile.c
|
||||
+++ b/mm/swapfile.c
|
||||
@@ -1936,7 +1936,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
page_add_anon_rmap(page, vma, addr, false);
|
||||
} else { /* ksm created a completely new copy */
|
||||
page_add_new_anon_rmap(page, vma, addr, false);
|
||||
- lru_cache_add_inactive_or_unevictable(page, vma);
|
||||
+ lru_cache_add_page_vma(page, vma, false);
|
||||
}
|
||||
swap_free(entry);
|
||||
out:
|
||||
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
|
||||
index 9a3d451402d7..e1d4cd3103b8 100644
|
||||
--- a/mm/userfaultfd.c
|
||||
+++ b/mm/userfaultfd.c
|
||||
@@ -123,7 +123,7 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
|
||||
|
||||
inc_mm_counter(dst_mm, MM_ANONPAGES);
|
||||
page_add_new_anon_rmap(page, dst_vma, dst_addr, false);
|
||||
- lru_cache_add_inactive_or_unevictable(page, dst_vma);
|
||||
+ lru_cache_add_page_vma(page, dst_vma, true);
|
||||
|
||||
set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);
|
||||
|
||||
diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
index fd49a9a5d7f5..ce868d89dc53 100644
|
||||
--- a/mm/vmscan.c
|
||||
+++ b/mm/vmscan.c
|
||||
@@ -1876,7 +1876,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec,
|
||||
add_page_to_lru_list(page, lruvec);
|
||||
nr_pages = thp_nr_pages(page);
|
||||
nr_moved += nr_pages;
|
||||
- if (PageActive(page))
|
||||
+ if (page_is_active(page, lruvec))
|
||||
workingset_age_nonresident(lruvec, nr_pages);
|
||||
}
|
||||
|
||||
@@ -4688,6 +4688,57 @@ static int page_update_lru_gen(struct page *page, int new_gen)
|
||||
return old_gen;
|
||||
}
|
||||
|
||||
+void lru_gen_scan_around(struct page_vma_mapped_walk *pvmw)
|
||||
+{
|
||||
+ pte_t *pte;
|
||||
+ unsigned long start, end;
|
||||
+ int old_gen, new_gen;
|
||||
+ unsigned long flags;
|
||||
+ struct lruvec *lruvec;
|
||||
+ struct mem_cgroup *memcg;
|
||||
+ struct pglist_data *pgdat = page_pgdat(pvmw->page);
|
||||
+
|
||||
+ lockdep_assert_held(pvmw->ptl);
|
||||
+ VM_BUG_ON_VMA(pvmw->address < pvmw->vma->vm_start, pvmw->vma);
|
||||
+
|
||||
+ start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start);
|
||||
+ end = pmd_addr_end(pvmw->address, pvmw->vma->vm_end);
|
||||
+ pte = pvmw->pte - ((pvmw->address - start) >> PAGE_SHIFT);
|
||||
+
|
||||
+ memcg = lock_page_memcg(pvmw->page);
|
||||
+ lruvec = lock_page_lruvec_irqsave(pvmw->page, &flags);
|
||||
+
|
||||
+ new_gen = lru_gen_from_seq(lruvec->evictable.max_seq);
|
||||
+
|
||||
+ for (; start != end; pte++, start += PAGE_SIZE) {
|
||||
+ struct page *page;
|
||||
+ unsigned long pfn = pte_pfn(*pte);
|
||||
+
|
||||
+ if (!pte_present(*pte) || !pte_young(*pte) || is_zero_pfn(pfn))
|
||||
+ continue;
|
||||
+
|
||||
+ if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat))
|
||||
+ continue;
|
||||
+
|
||||
+ page = compound_head(pte_page(*pte));
|
||||
+ if (page_to_nid(page) != pgdat->node_id)
|
||||
+ continue;
|
||||
+ if (page_memcg_rcu(page) != memcg)
|
||||
+ continue;
|
||||
+ /*
|
||||
+ * We may be holding many locks. So try to finish as fast as
|
||||
+ * possible and leave the accessed and the dirty bits to page
|
||||
+ * table walk.
|
||||
+ */
|
||||
+ old_gen = page_update_lru_gen(page, new_gen);
|
||||
+ if (old_gen >= 0 && old_gen != new_gen)
|
||||
+ lru_gen_update_size(page, lruvec, old_gen, new_gen);
|
||||
+ }
|
||||
+
|
||||
+ unlock_page_lruvec_irqrestore(lruvec, flags);
|
||||
+ unlock_page_memcg(pvmw->page);
|
||||
+}
|
||||
+
|
||||
struct mm_walk_args {
|
||||
struct mem_cgroup *memcg;
|
||||
unsigned long max_seq;
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,492 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 29E96C4321A
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 1649264ECE
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233577AbhCMH6q (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:46 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59016 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232992AbhCMH6N (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:13 -0500
|
||||
Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F2926C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:12 -0800 (PST)
|
||||
Received: by mail-yb1-xb49.google.com with SMTP id b127so31851193ybc.13
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:12 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=HpM4Xhq08m+hN0lK+sEgEqrsIbbrPIT86c74gNI/u9w=;
|
||||
b=iZooLRgVq0QKt7uS3ecgWUo9C9cGTHyr/2U5sxKCS6QXN0IgrJO3PAgtZX95WUfwcs
|
||||
ZSAQR6gNrWG+wP3LmXgu+DSkMxuKFw0cNRjKklelEg68uDJJWokPALnGLPA4nMy8dmmL
|
||||
gNmywFSsTBT8s8Opdpx1NmeoX3AoH+b/8wRfOXpwgaGDC+vZ82D7uiEVDdLrnbyopU8f
|
||||
IpPsdEWG/PKjNmqr9aaxr+DYpbpcOwr48yDoUFRDhKXq2kRMLS3q9Cr2+5Aa3cOZI9gL
|
||||
a6NMw3O/GtXpPy+iDG3kH66GA3tICHTkX1Zm9PHqXzTR/dFawFQyNro80/QMStsyVm0P
|
||||
hUPA==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=HpM4Xhq08m+hN0lK+sEgEqrsIbbrPIT86c74gNI/u9w=;
|
||||
b=enhVyxFe4tZkU5M5CCcAvOq7XPOtrI0KR9T9RiANQFtlMzTvtrxKdJw8h9WJfPozxv
|
||||
DODj66oaquifIDjLTzxgHvuElCPtya1VXVDoZr/k/dHc0n6u5v10BW2bAYXIVIBtZgMb
|
||||
WwMcgh3rGt4wsE7QWUeFmRne+9VW55GHi1MtsKV2+fvK2y7UyMEoP6hy3iQbBcTxeLH0
|
||||
F684asdtadbsGGkyGN1KvT5S9l71CJFhEI6Zz6ag4NgojHVz2zN0kv4/qzQCkWhPUHNs
|
||||
Pqv8OmYBrbTHERb8vRmdpXAn8C+qWgQ5PHrVk8OOP3YB1/IBCCwYKqMe/Q7FeRocip4d
|
||||
Q5vw==
|
||||
X-Gm-Message-State: AOAM532t/+vC4rNBlDPUITq8/UGTKPQERiyG/Yu/AZbe1MTxG9Izfw1X
|
||||
ohDrQJQrlikp3FZQGyfgd8ZO5sD99kg=
|
||||
X-Google-Smtp-Source: ABdhPJyqRrRSS1bJd41QeWsraiQMIBjlJledYF/KyYHH/bW9K+768sYy2pOiqW2DerYXRlOndOy2egSD7FE=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a25:1184:: with SMTP id 126mr22571060ybr.430.1615622292183;
|
||||
Fri, 12 Mar 2021 23:58:12 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:45 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-13-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 12/14] mm: multigenerational lru: user space interface
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-13-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Add a sysfs file /sys/kernel/mm/lru_gen/enabled so user space can
|
||||
enable and disable multigenerational lru at runtime.
|
||||
|
||||
Add a sysfs file /sys/kernel/mm/lru_gen/spread so user space can
|
||||
spread pages out across multiple generations. More generations make
|
||||
the background aging more aggressive.
|
||||
|
||||
Add a debugfs file /sys/kernel/debug/lru_gen so user space can monitor
|
||||
multigenerational lru and trigger the aging and the eviction. This
|
||||
file has the following output:
|
||||
memcg memcg_id memcg_path
|
||||
node node_id
|
||||
min_gen birth_time anon_size file_size
|
||||
...
|
||||
max_gen birth_time anon_size file_size
|
||||
|
||||
Given a memcg and a node, "min_gen" is the oldest generation (number)
|
||||
and "max_gen" is the youngest. Birth time is in milliseconds. Anon and
|
||||
file sizes are in pages.
|
||||
|
||||
Write "+ memcg_id node_id gen [swappiness]" to this file to account
|
||||
referenced pages to generation "max_gen" and create next generation
|
||||
"max_gen"+1. "gen" must be equal to "max_gen" in order to avoid races.
|
||||
A swap file and a non-zero swappiness value are required to scan anon
|
||||
pages. If swapping is not desired, set vm.swappiness to 0 and
|
||||
overwrite it with a non-zero "swappiness".
|
||||
|
||||
Write "- memcg_id node_id gen [swappiness] [nr_to_reclaim]" to this
|
||||
file to evict generations less than or equal to "gen". "gen" must be
|
||||
less than "max_gen"-1 as "max_gen" and "max_gen"-1 are active
|
||||
generations and therefore protected from the eviction. "nr_to_reclaim"
|
||||
can be used to limit the number of pages to be evicted.
|
||||
|
||||
Multiple command lines are supported, so does concatenation with
|
||||
delimiters "," and ";".
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
mm/vmscan.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 334 insertions(+)
|
||||
|
||||
diff --git a/mm/vmscan.c b/mm/vmscan.c
|
||||
index ce868d89dc53..b59b556e9587 100644
|
||||
--- a/mm/vmscan.c
|
||||
+++ b/mm/vmscan.c
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <linux/psi.h>
|
||||
#include <linux/pagewalk.h>
|
||||
#include <linux/memory.h>
|
||||
+#include <linux/debugfs.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/div64.h>
|
||||
@@ -5833,6 +5834,334 @@ lru_gen_online_mem(struct notifier_block *self, unsigned long action, void *arg)
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
+/******************************************************************************
|
||||
+ * sysfs interface
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+static ssize_t show_lru_gen_spread(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ return sprintf(buf, "%d\n", READ_ONCE(lru_gen_spread));
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_lru_gen_spread(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
+ const char *buf, size_t len)
|
||||
+{
|
||||
+ int spread;
|
||||
+
|
||||
+ if (kstrtoint(buf, 10, &spread) || spread >= MAX_NR_GENS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ WRITE_ONCE(lru_gen_spread, spread);
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static struct kobj_attribute lru_gen_spread_attr = __ATTR(
|
||||
+ spread, 0644,
|
||||
+ show_lru_gen_spread, store_lru_gen_spread
|
||||
+);
|
||||
+
|
||||
+static ssize_t show_lru_gen_enabled(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ return snprintf(buf, PAGE_SIZE, "%ld\n", lru_gen_enabled());
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_lru_gen_enabled(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
+ const char *buf, size_t len)
|
||||
+{
|
||||
+ int enable;
|
||||
+
|
||||
+ if (kstrtoint(buf, 10, &enable))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ lru_gen_set_state(enable, true, false);
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static struct kobj_attribute lru_gen_enabled_attr = __ATTR(
|
||||
+ enabled, 0644, show_lru_gen_enabled, store_lru_gen_enabled
|
||||
+);
|
||||
+
|
||||
+static struct attribute *lru_gen_attrs[] = {
|
||||
+ &lru_gen_spread_attr.attr,
|
||||
+ &lru_gen_enabled_attr.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group lru_gen_attr_group = {
|
||||
+ .name = "lru_gen",
|
||||
+ .attrs = lru_gen_attrs,
|
||||
+};
|
||||
+
|
||||
+/******************************************************************************
|
||||
+ * debugfs interface
|
||||
+ ******************************************************************************/
|
||||
+
|
||||
+static void *lru_gen_seq_start(struct seq_file *m, loff_t *pos)
|
||||
+{
|
||||
+ struct mem_cgroup *memcg;
|
||||
+ loff_t nr_to_skip = *pos;
|
||||
+
|
||||
+ m->private = kzalloc(PATH_MAX, GFP_KERNEL);
|
||||
+ if (!m->private)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ memcg = mem_cgroup_iter(NULL, NULL, NULL);
|
||||
+ do {
|
||||
+ int nid;
|
||||
+
|
||||
+ for_each_node_state(nid, N_MEMORY) {
|
||||
+ if (!nr_to_skip--)
|
||||
+ return mem_cgroup_lruvec(memcg, NODE_DATA(nid));
|
||||
+ }
|
||||
+ } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)));
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void lru_gen_seq_stop(struct seq_file *m, void *v)
|
||||
+{
|
||||
+ if (!IS_ERR_OR_NULL(v))
|
||||
+ mem_cgroup_iter_break(NULL, lruvec_memcg(v));
|
||||
+
|
||||
+ kfree(m->private);
|
||||
+ m->private = NULL;
|
||||
+}
|
||||
+
|
||||
+static void *lru_gen_seq_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
+{
|
||||
+ int nid = lruvec_pgdat(v)->node_id;
|
||||
+ struct mem_cgroup *memcg = lruvec_memcg(v);
|
||||
+
|
||||
+ ++*pos;
|
||||
+
|
||||
+ nid = next_memory_node(nid);
|
||||
+ if (nid == MAX_NUMNODES) {
|
||||
+ memcg = mem_cgroup_iter(NULL, memcg, NULL);
|
||||
+ if (!memcg)
|
||||
+ return NULL;
|
||||
+
|
||||
+ nid = first_memory_node;
|
||||
+ }
|
||||
+
|
||||
+ return mem_cgroup_lruvec(memcg, NODE_DATA(nid));
|
||||
+}
|
||||
+
|
||||
+static int lru_gen_seq_show(struct seq_file *m, void *v)
|
||||
+{
|
||||
+ unsigned long seq;
|
||||
+ struct lruvec *lruvec = v;
|
||||
+ int nid = lruvec_pgdat(lruvec)->node_id;
|
||||
+ struct mem_cgroup *memcg = lruvec_memcg(lruvec);
|
||||
+ DEFINE_MAX_SEQ(lruvec);
|
||||
+ DEFINE_MIN_SEQ(lruvec);
|
||||
+
|
||||
+ if (nid == first_memory_node) {
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ if (memcg)
|
||||
+ cgroup_path(memcg->css.cgroup, m->private, PATH_MAX);
|
||||
+#endif
|
||||
+ seq_printf(m, "memcg %5hu %s\n",
|
||||
+ mem_cgroup_id(memcg), (char *)m->private);
|
||||
+ }
|
||||
+
|
||||
+ seq_printf(m, " node %4d\n", nid);
|
||||
+
|
||||
+ for (seq = min(min_seq[0], min_seq[1]); seq <= max_seq; seq++) {
|
||||
+ int gen, file, zone;
|
||||
+ unsigned int msecs;
|
||||
+ long sizes[ANON_AND_FILE] = {};
|
||||
+
|
||||
+ gen = lru_gen_from_seq(seq);
|
||||
+
|
||||
+ msecs = jiffies_to_msecs(jiffies - READ_ONCE(
|
||||
+ lruvec->evictable.timestamps[gen]));
|
||||
+
|
||||
+ for_each_type_zone(file, zone)
|
||||
+ sizes[file] += READ_ONCE(
|
||||
+ lruvec->evictable.sizes[gen][file][zone]);
|
||||
+
|
||||
+ sizes[0] = max(sizes[0], 0L);
|
||||
+ sizes[1] = max(sizes[1], 0L);
|
||||
+
|
||||
+ seq_printf(m, "%11lu %9u %9lu %9lu\n",
|
||||
+ seq, msecs, sizes[0], sizes[1]);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct seq_operations lru_gen_seq_ops = {
|
||||
+ .start = lru_gen_seq_start,
|
||||
+ .stop = lru_gen_seq_stop,
|
||||
+ .next = lru_gen_seq_next,
|
||||
+ .show = lru_gen_seq_show,
|
||||
+};
|
||||
+
|
||||
+static int lru_gen_debugfs_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ return seq_open(file, &lru_gen_seq_ops);
|
||||
+}
|
||||
+
|
||||
+static int advance_max_seq(struct lruvec *lruvec, unsigned long seq, int swappiness)
|
||||
+{
|
||||
+ struct scan_control sc = {
|
||||
+ .target_mem_cgroup = lruvec_memcg(lruvec),
|
||||
+ };
|
||||
+ DEFINE_MAX_SEQ(lruvec);
|
||||
+
|
||||
+ if (seq == max_seq)
|
||||
+ walk_mm_list(lruvec, max_seq, &sc, swappiness);
|
||||
+
|
||||
+ return seq > max_seq ? -EINVAL : 0;
|
||||
+}
|
||||
+
|
||||
+static int advance_min_seq(struct lruvec *lruvec, unsigned long seq, int swappiness,
|
||||
+ unsigned long nr_to_reclaim)
|
||||
+{
|
||||
+ struct blk_plug plug;
|
||||
+ int err = -EINTR;
|
||||
+ long nr_to_scan = LONG_MAX;
|
||||
+ struct scan_control sc = {
|
||||
+ .nr_to_reclaim = nr_to_reclaim,
|
||||
+ .target_mem_cgroup = lruvec_memcg(lruvec),
|
||||
+ .may_writepage = 1,
|
||||
+ .may_unmap = 1,
|
||||
+ .may_swap = 1,
|
||||
+ .reclaim_idx = MAX_NR_ZONES - 1,
|
||||
+ .gfp_mask = GFP_KERNEL,
|
||||
+ };
|
||||
+ DEFINE_MAX_SEQ(lruvec);
|
||||
+
|
||||
+ if (seq >= max_seq - 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ blk_start_plug(&plug);
|
||||
+
|
||||
+ while (!signal_pending(current)) {
|
||||
+ DEFINE_MIN_SEQ(lruvec);
|
||||
+
|
||||
+ if (seq < min(min_seq[!swappiness], min_seq[swappiness < 200]) ||
|
||||
+ !evict_lru_gen_pages(lruvec, &sc, swappiness, &nr_to_scan)) {
|
||||
+ err = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ cond_resched();
|
||||
+ }
|
||||
+
|
||||
+ blk_finish_plug(&plug);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int advance_seq(char cmd, int memcg_id, int nid, unsigned long seq,
|
||||
+ int swappiness, unsigned long nr_to_reclaim)
|
||||
+{
|
||||
+ struct lruvec *lruvec;
|
||||
+ int err = -EINVAL;
|
||||
+ struct mem_cgroup *memcg = NULL;
|
||||
+
|
||||
+ if (!mem_cgroup_disabled()) {
|
||||
+ rcu_read_lock();
|
||||
+ memcg = mem_cgroup_from_id(memcg_id);
|
||||
+#ifdef CONFIG_MEMCG
|
||||
+ if (memcg && !css_tryget(&memcg->css))
|
||||
+ memcg = NULL;
|
||||
+#endif
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ if (!memcg)
|
||||
+ goto done;
|
||||
+ }
|
||||
+ if (memcg_id != mem_cgroup_id(memcg))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (nid < 0 || nid >= MAX_NUMNODES || !node_state(nid, N_MEMORY))
|
||||
+ goto done;
|
||||
+
|
||||
+ lruvec = mem_cgroup_lruvec(memcg, NODE_DATA(nid));
|
||||
+
|
||||
+ if (swappiness == -1)
|
||||
+ swappiness = get_swappiness(lruvec);
|
||||
+ else if (swappiness > 200U)
|
||||
+ goto done;
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case '+':
|
||||
+ err = advance_max_seq(lruvec, seq, swappiness);
|
||||
+ break;
|
||||
+ case '-':
|
||||
+ err = advance_min_seq(lruvec, seq, swappiness, nr_to_reclaim);
|
||||
+ break;
|
||||
+ }
|
||||
+done:
|
||||
+ mem_cgroup_put(memcg);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static ssize_t lru_gen_debugfs_write(struct file *file, const char __user *src,
|
||||
+ size_t len, loff_t *pos)
|
||||
+{
|
||||
+ void *buf;
|
||||
+ char *cur, *next;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ buf = kvmalloc(len + 1, GFP_USER);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (copy_from_user(buf, src, len)) {
|
||||
+ kvfree(buf);
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+
|
||||
+ next = buf;
|
||||
+ next[len] = '\0';
|
||||
+
|
||||
+ while ((cur = strsep(&next, ",;\n"))) {
|
||||
+ int n;
|
||||
+ int end;
|
||||
+ char cmd;
|
||||
+ int memcg_id;
|
||||
+ int nid;
|
||||
+ unsigned long seq;
|
||||
+ int swappiness = -1;
|
||||
+ unsigned long nr_to_reclaim = -1;
|
||||
+
|
||||
+ cur = skip_spaces(cur);
|
||||
+ if (!*cur)
|
||||
+ continue;
|
||||
+
|
||||
+ n = sscanf(cur, "%c %u %u %lu %n %u %n %lu %n", &cmd, &memcg_id, &nid,
|
||||
+ &seq, &end, &swappiness, &end, &nr_to_reclaim, &end);
|
||||
+ if (n < 4 || cur[end]) {
|
||||
+ err = -EINVAL;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ err = advance_seq(cmd, memcg_id, nid, seq, swappiness, nr_to_reclaim);
|
||||
+ if (err)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ kvfree(buf);
|
||||
+
|
||||
+ return err ? : len;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations lru_gen_debugfs_ops = {
|
||||
+ .open = lru_gen_debugfs_open,
|
||||
+ .read = seq_read,
|
||||
+ .write = lru_gen_debugfs_write,
|
||||
+ .llseek = seq_lseek,
|
||||
+ .release = seq_release,
|
||||
+};
|
||||
+
|
||||
/******************************************************************************
|
||||
* initialization
|
||||
******************************************************************************/
|
||||
@@ -5873,6 +6202,11 @@ static int __init init_lru_gen(void)
|
||||
if (hotplug_memory_notifier(lru_gen_online_mem, 0))
|
||||
pr_err("lru_gen: failed to subscribe hotplug notifications\n");
|
||||
|
||||
+ if (sysfs_create_group(mm_kobj, &lru_gen_attr_group))
|
||||
+ pr_err("lru_gen: failed to create sysfs group\n");
|
||||
+
|
||||
+ debugfs_create_file("lru_gen", 0644, NULL, NULL, &lru_gen_debugfs_ops);
|
||||
+
|
||||
return 0;
|
||||
};
|
||||
/*
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,137 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 9E997C43619
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 8CDE364F1F
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233595AbhCMH6r (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:47 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59028 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S232999AbhCMH6P (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:15 -0500
|
||||
Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7BED3C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:14 -0800 (PST)
|
||||
Received: by mail-qk1-x74a.google.com with SMTP id c1so19954167qke.8
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:14 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=uE7IkUDVFpC8s1yHDZEBmC5mjUj6EJwbkUDWk669ASY=;
|
||||
b=uXhx05PdjRvuFkUcjNWapddDUcA7Q5UwyJE/THSSQbBgSLQkmn7ajsUcb7ZmUjhauR
|
||||
/jgBj7/Odh6Ngd12GetPXsZawVQtDY3F/Xog0R3yIye6citJOlL5TJ+2wwf2gcYmueuQ
|
||||
WYDJiJoxC2qvezUikRORLJGGQFEDfwGtR7lOiuTnagaswHyGlY8OAHiBnbM2NFrUlS9F
|
||||
wuwz3bRewUhC6hOmirv0YN+eR4e/S0TxFsdjMMf1mOQtK0M77IA18i0YjomUSsNcZo01
|
||||
GPjHMp59Yr0/XsqaDXOK5S+CA6611MojOlFbWTfafAQpXFIKwJXgkzUeIs9A5goZIWHY
|
||||
WCzQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=uE7IkUDVFpC8s1yHDZEBmC5mjUj6EJwbkUDWk669ASY=;
|
||||
b=bLNHbmZfUarHE/zKcwTOEXRDaaA3M3Wb9opsS8eMo1jlzRy67SWU0QGKWyLhaQIUuj
|
||||
jYh9cCeQdHC6qIfno1lltA2+v9qIhbWTkQq8IDWpy+DqlnHKeJ9+XXBQRQaso3znd4ai
|
||||
nPcd4O7/NtulCEnPJS2gjxYdwdJpTRn7zQmPaq7GzeKJRU9mvdhcR8zfovaRnZIIgwNw
|
||||
Ek53R7AbW1KCHAQtw9b0DwJz5OUi6Uqj50tx1chZcH3FUwhFwZUE2dqTAAbpx8adie8Y
|
||||
0NBJ8v2hnoSoCSy2gxlP1J+gN0mEx5Qn0C5zIt7OKkWf4Sh01kTSKIDwmcQsD0ghz6hu
|
||||
7qiQ==
|
||||
X-Gm-Message-State: AOAM5339O1/TQ9+FOQ9m7N+jX6OVojHsWyNTehwokZ5ewkZ6BLvWDrEp
|
||||
OjNCxrW3VzSi1/zx5w0Sch6pYeFtRCc=
|
||||
X-Google-Smtp-Source: ABdhPJz7oVSCBhnoApkNm1wW85JMl4kSXploQGL6Mdvavu7deAd9Mg85kMswIg+jCkfg3Z/h90N99XOQmFk=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a05:6214:1909:: with SMTP id
|
||||
er9mr1749542qvb.5.1615622293640; Fri, 12 Mar 2021 23:58:13 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:46 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-14-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 13/14] mm: multigenerational lru: Kconfig
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-14-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Add configuration options for multigenerational lru.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
mm/Kconfig | 29 +++++++++++++++++++++++++++++
|
||||
1 file changed, 29 insertions(+)
|
||||
|
||||
diff --git a/mm/Kconfig b/mm/Kconfig
|
||||
index 24c045b24b95..3a5bcc2d7a45 100644
|
||||
--- a/mm/Kconfig
|
||||
+++ b/mm/Kconfig
|
||||
@@ -872,4 +872,33 @@ config MAPPING_DIRTY_HELPERS
|
||||
config KMAP_LOCAL
|
||||
bool
|
||||
|
||||
+config LRU_GEN
|
||||
+ bool "Multigenerational LRU"
|
||||
+ depends on MMU
|
||||
+ help
|
||||
+ High performance multigenerational LRU to heavily overcommit workloads
|
||||
+ that are not IO bound. See Documentation/vm/multigen_lru.rst for
|
||||
+ details.
|
||||
+
|
||||
+ Warning: do not enable this option unless you plan to use it because
|
||||
+ it introduces a small per-process memory overhead.
|
||||
+
|
||||
+config NR_LRU_GENS
|
||||
+ int "Max number of generations"
|
||||
+ depends on LRU_GEN
|
||||
+ range 4 63
|
||||
+ default 7
|
||||
+ help
|
||||
+ This will use ilog2(N)+1 spare bits from page flags.
|
||||
+
|
||||
+ Warning: do not use numbers larger than necessary because each
|
||||
+ generation introduces a small per-node and per-memcg memory overhead.
|
||||
+
|
||||
+config LRU_GEN_ENABLED
|
||||
+ bool "Turn on by default"
|
||||
+ depends on LRU_GEN
|
||||
+ help
|
||||
+ The default value of /sys/kernel/mm/lru_gen/enabled is 0. This option
|
||||
+ changes it to 1.
|
||||
+
|
||||
endmenu
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
@ -0,0 +1,329 @@
|
||||
From mboxrd@z Thu Jan 1 00:00:00 1970
|
||||
Return-Path: <linux-kernel-owner@kernel.org>
|
||||
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
|
||||
aws-us-west-2-korg-lkml-1.web.codeaurora.org
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED,
|
||||
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,
|
||||
INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,
|
||||
USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no
|
||||
version=3.4.0
|
||||
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
|
||||
by smtp.lore.kernel.org (Postfix) with ESMTP id 99A73C4360C
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
|
||||
by mail.kernel.org (Postfix) with ESMTP id 7C9EA64F1E
|
||||
for <linux-kernel@archiver.kernel.org>; Sat, 13 Mar 2021 07:59:07 +0000 (UTC)
|
||||
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
|
||||
id S233629AbhCMH6s (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:48 -0500
|
||||
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59030 "EHLO
|
||||
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
|
||||
with ESMTP id S233011AbhCMH6Q (ORCPT
|
||||
<rfc822;linux-kernel@vger.kernel.org>);
|
||||
Sat, 13 Mar 2021 02:58:16 -0500
|
||||
Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49])
|
||||
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3F77C061574
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:15 -0800 (PST)
|
||||
Received: by mail-yb1-xb49.google.com with SMTP id y7so31766185ybh.20
|
||||
for <linux-kernel@vger.kernel.org>; Fri, 12 Mar 2021 23:58:15 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=google.com; s=20161025;
|
||||
h=date:in-reply-to:message-id:mime-version:references:subject:from:to
|
||||
:cc;
|
||||
bh=b33M625vmeFm8iJFKYIy9IbS+yyXzJHrz2YlprWAE88=;
|
||||
b=qyBWCu6iSCz/+GOTBSyjEGx0UNh3wx8I4EpB+DGhW3FtbTsYmoVsgkJK7K9lMib92D
|
||||
8UESs064HgmPaCcFC9wummpEDT04EZB57UgnWkSzwsmT8q8yKbsLNsdnaqxDho13rxSL
|
||||
l1lhvY8XggaGyQS76caURzCZzmuuIb31yoMyJa36cSNEQIIGzS/Qm0HS9FQ4Sslqjhio
|
||||
7G+7M9RsfMDtCuFijNWCkO0VasJ5hLLwIPnUW2My7qRxlwAQoGToYUEA5ipkn9Ckz+I1
|
||||
ZZZL32LyYugyxj8DFHGhkOK2vtm0J8rqvkbb7eJOL7RwHttQzqGHotvqWMTx+tw95ZXr
|
||||
O2hQ==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:date:in-reply-to:message-id:mime-version
|
||||
:references:subject:from:to:cc;
|
||||
bh=b33M625vmeFm8iJFKYIy9IbS+yyXzJHrz2YlprWAE88=;
|
||||
b=c/gz9vPAEJyp/EJn3y5EFyXbzSo7i/3uPaPFgvAuDmTSD+ba6y1WjRuclOCOCm5zrN
|
||||
rzU2v5yfzmo6p+fXYM+C5uFH8SqC+cMK+bYnZUuNl3OwvgwL3kofqlcrnKaQQMqRRSey
|
||||
lrW47VbiLF0IySg6AM605BkxEjKxVIkdnWAS+bqXtQVym74gxHHOHwX5tGuCn/7Bs/c4
|
||||
cekamb+2vIeO+6/P0YD1ZdLO9LS1OwgxSor5cocBSXXW7J7bBLCGKAyU++NrNnahjJs1
|
||||
8ckqrHiqFC1mEWFcs+VBQ9/NCeVfcAfMGRtsMsljI5kll/myniTnSrETf49UyjrcTk87
|
||||
zwYQ==
|
||||
X-Gm-Message-State: AOAM531AI2qRYUeaR85JEsd20wl4qCSV4g5Qpav0tPw9JXRAxcdYk9S4
|
||||
AlH8Rls2BT9Ub2LGipv5Jfv5X2rI3ho=
|
||||
X-Google-Smtp-Source: ABdhPJwyYS+6AjG1nAXtEYBKUiLdJ5mAmkUQWOq9ngRJz7So3XTjiRhhO4QmZvWvkKbzXQ7oleb6ep4AFYs=
|
||||
X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:f931:d3e4:faa0:4f74])
|
||||
(user=yuzhao job=sendgmr) by 2002:a25:8003:: with SMTP id m3mr24313264ybk.452.1615622295044;
|
||||
Fri, 12 Mar 2021 23:58:15 -0800 (PST)
|
||||
Date: Sat, 13 Mar 2021 00:57:47 -0700
|
||||
In-Reply-To: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
Message-Id: <20210313075747.3781593-15-yuzhao@google.com>
|
||||
Mime-Version: 1.0
|
||||
References: <20210313075747.3781593-1-yuzhao@google.com>
|
||||
X-Mailer: git-send-email 2.31.0.rc2.261.g7f71774620-goog
|
||||
Subject: [PATCH v1 14/14] mm: multigenerational lru: documentation
|
||||
From: Yu Zhao <yuzhao@google.com>
|
||||
To: linux-mm@kvack.org
|
||||
Cc: Alex Shi <alex.shi@linux.alibaba.com>,
|
||||
Andrew Morton <akpm@linux-foundation.org>,
|
||||
Dave Hansen <dave.hansen@linux.intel.com>,
|
||||
Hillf Danton <hdanton@sina.com>,
|
||||
Johannes Weiner <hannes@cmpxchg.org>,
|
||||
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
|
||||
Matthew Wilcox <willy@infradead.org>,
|
||||
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@suse.com>,
|
||||
Roman Gushchin <guro@fb.com>, Vlastimil Babka <vbabka@suse.cz>,
|
||||
Wei Yang <richard.weiyang@linux.alibaba.com>,
|
||||
Yang Shi <shy828301@gmail.com>,
|
||||
Ying Huang <ying.huang@intel.com>,
|
||||
linux-kernel@vger.kernel.org, page-reclaim@google.com,
|
||||
Yu Zhao <yuzhao@google.com>
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Precedence: bulk
|
||||
List-ID: <linux-kernel.vger.kernel.org>
|
||||
X-Mailing-List: linux-kernel@vger.kernel.org
|
||||
Archived-At: <https://lore.kernel.org/lkml/20210313075747.3781593-15-yuzhao@google.com/>
|
||||
List-Archive: <https://lore.kernel.org/lkml/>
|
||||
List-Post: <mailto:linux-kernel@vger.kernel.org>
|
||||
|
||||
Add Documentation/vm/multigen_lru.rst.
|
||||
|
||||
Signed-off-by: Yu Zhao <yuzhao@google.com>
|
||||
---
|
||||
Documentation/vm/index.rst | 1 +
|
||||
Documentation/vm/multigen_lru.rst | 210 ++++++++++++++++++++++++++++++
|
||||
2 files changed, 211 insertions(+)
|
||||
create mode 100644 Documentation/vm/multigen_lru.rst
|
||||
|
||||
diff --git a/Documentation/vm/index.rst b/Documentation/vm/index.rst
|
||||
index eff5fbd492d0..c353b3f55924 100644
|
||||
--- a/Documentation/vm/index.rst
|
||||
+++ b/Documentation/vm/index.rst
|
||||
@@ -17,6 +17,7 @@ various features of the Linux memory management
|
||||
|
||||
swap_numa
|
||||
zswap
|
||||
+ multigen_lru
|
||||
|
||||
Kernel developers MM documentation
|
||||
==================================
|
||||
diff --git a/Documentation/vm/multigen_lru.rst b/Documentation/vm/multigen_lru.rst
|
||||
new file mode 100644
|
||||
index 000000000000..fea927da2572
|
||||
--- /dev/null
|
||||
+++ b/Documentation/vm/multigen_lru.rst
|
||||
@@ -0,0 +1,210 @@
|
||||
+=====================
|
||||
+Multigenerational LRU
|
||||
+=====================
|
||||
+
|
||||
+Quick Start
|
||||
+===========
|
||||
+Build Options
|
||||
+-------------
|
||||
+:Required: Set ``CONFIG_LRU_GEN=y``.
|
||||
+
|
||||
+:Optional: Change ``CONFIG_NR_LRU_GENS`` to a number ``X`` to support
|
||||
+ a maximum of ``X`` generations.
|
||||
+
|
||||
+:Optional: Set ``CONFIG_LRU_GEN_ENABLED=y`` to turn the feature on by
|
||||
+ default.
|
||||
+
|
||||
+Runtime Options
|
||||
+---------------
|
||||
+:Required: Write ``1`` to ``/sys/kernel/mm/lru_gen/enable`` if the
|
||||
+ feature was not turned on by default.
|
||||
+
|
||||
+:Optional: Change ``/sys/kernel/mm/lru_gen/spread`` to a number ``N``
|
||||
+ to spread pages out across ``N+1`` generations. ``N`` must be less
|
||||
+ than ``X``. Larger values make the background aging more aggressive.
|
||||
+
|
||||
+:Optional: Read ``/sys/kernel/debug/lru_gen`` to verify the feature.
|
||||
+ This file has the following output:
|
||||
+
|
||||
+::
|
||||
+
|
||||
+ memcg memcg_id memcg_path
|
||||
+ node node_id
|
||||
+ min_gen birth_time anon_size file_size
|
||||
+ ...
|
||||
+ max_gen birth_time anon_size file_size
|
||||
+
|
||||
+Given a memcg and a node, ``min_gen`` is the oldest generation
|
||||
+(number) and ``max_gen`` is the youngest. Birth time is in
|
||||
+milliseconds. Anon and file sizes are in pages.
|
||||
+
|
||||
+Recipes
|
||||
+-------
|
||||
+:Android on ARMv8.1+: ``X=4``, ``N=0``
|
||||
+
|
||||
+:Android on pre-ARMv8.1 CPUs: Not recommended due to the lack of
|
||||
+ ``ARM64_HW_AFDBM``
|
||||
+
|
||||
+:Laptops running Chrome on x86_64: ``X=7``, ``N=2``
|
||||
+
|
||||
+:Working set estimation: Write ``+ memcg_id node_id gen [swappiness]``
|
||||
+ to ``/sys/kernel/debug/lru_gen`` to account referenced pages to
|
||||
+ generation ``max_gen`` and create the next generation ``max_gen+1``.
|
||||
+ ``gen`` must be equal to ``max_gen`` in order to avoid races. A swap
|
||||
+ file and a non-zero swappiness value are required to scan anon pages.
|
||||
+ If swapping is not desired, set ``vm.swappiness`` to ``0`` and
|
||||
+ overwrite it with a non-zero ``swappiness``.
|
||||
+
|
||||
+:Proactive reclaim: Write ``- memcg_id node_id gen [swappiness]
|
||||
+ [nr_to_reclaim]`` to ``/sys/kernel/debug/lru_gen`` to evict
|
||||
+ generations less than or equal to ``gen``. ``gen`` must be less than
|
||||
+ ``max_gen-1`` as ``max_gen`` and ``max_gen-1`` are active generations
|
||||
+ and therefore protected from the eviction. ``nr_to_reclaim`` can be
|
||||
+ used to limit the number of pages to be evicted. Multiple command
|
||||
+ lines are supported, so does concatenation with delimiters ``,`` and
|
||||
+ ``;``.
|
||||
+
|
||||
+Workflow
|
||||
+========
|
||||
+Evictable pages are divided into multiple generations for each
|
||||
+``lruvec``. The youngest generation number is stored in ``max_seq``
|
||||
+for both anon and file types as they are aged on an equal footing. The
|
||||
+oldest generation numbers are stored in ``min_seq[2]`` separately for
|
||||
+anon and file types as clean file pages can be evicted regardless of
|
||||
+swap and write-back constraints. Generation numbers are truncated into
|
||||
+``ilog2(CONFIG_NR_LRU_GENS)+1`` bits in order to fit into
|
||||
+``page->flags``. The sliding window technique is used to prevent
|
||||
+truncated generation numbers from overlapping. Each truncated
|
||||
+generation number is an index to an array of per-type and per-zone
|
||||
+lists. Evictable pages are added to the per-zone lists indexed by
|
||||
+``max_seq`` or ``min_seq[2]`` (modulo ``CONFIG_NR_LRU_GENS``),
|
||||
+depending on whether they are being faulted in or read ahead. The
|
||||
+workflow comprises two conceptually independent functions: the aging
|
||||
+and the eviction.
|
||||
+
|
||||
+Aging
|
||||
+-----
|
||||
+The aging produces young generations. Given an ``lruvec``, the aging
|
||||
+scans page tables for referenced pages of this ``lruvec``. Upon
|
||||
+finding one, the aging updates its generation number to ``max_seq``.
|
||||
+After each round of scan, the aging increments ``max_seq``. The aging
|
||||
+maintains either a system-wide ``mm_struct`` list or per-memcg
|
||||
+``mm_struct`` lists, and it only scans page tables of processes that
|
||||
+have been scheduled since the last scan. Since scans are differential
|
||||
+with respect to referenced pages, the cost is roughly proportional to
|
||||
+their number.
|
||||
+
|
||||
+Eviction
|
||||
+--------
|
||||
+The eviction consumes old generations. Given an ``lruvec``, the
|
||||
+eviction scans the pages on the per-zone lists indexed by either of
|
||||
+``min_seq[2]``. It selects a type according to the values of
|
||||
+``min_seq[2]`` and swappiness. During a scan, the eviction either
|
||||
+sorts or isolates a page, depending on whether the aging has updated
|
||||
+its generation number. When it finds all the per-zone lists are empty,
|
||||
+the eviction increments ``min_seq[2]`` indexed by this selected type.
|
||||
+The eviction triggers the aging when both of ``min_seq[2]`` reaches
|
||||
+``max_seq-1``, assuming both anon and file types are reclaimable.
|
||||
+
|
||||
+Rationale
|
||||
+=========
|
||||
+Characteristics of cloud workloads
|
||||
+----------------------------------
|
||||
+With cloud storage gone mainstream, the role of local storage has
|
||||
+diminished. For most of the systems running cloud workloads, anon
|
||||
+pages account for the majority of memory consumption and page cache
|
||||
+contains mostly executable pages. Notably, the portion of the unmapped
|
||||
+is negligible.
|
||||
+
|
||||
+As a result, swapping is necessary to achieve substantial memory
|
||||
+overcommit. And the ``rmap`` is the hottest in the reclaim path
|
||||
+because its usage is proportional to the number of scanned pages,
|
||||
+which on average is many times the number of reclaimed pages.
|
||||
+
|
||||
+With ``zram``, a typical ``kswapd`` profile on v5.11 looks like:
|
||||
+
|
||||
+::
|
||||
+
|
||||
+ 31.03% page_vma_mapped_walk
|
||||
+ 25.59% lzo1x_1_do_compress
|
||||
+ 4.63% do_raw_spin_lock
|
||||
+ 3.89% vma_interval_tree_iter_next
|
||||
+ 3.33% vma_interval_tree_subtree_search
|
||||
+
|
||||
+And with real swap, it looks like:
|
||||
+
|
||||
+::
|
||||
+
|
||||
+ 45.16% page_vma_mapped_walk
|
||||
+ 7.61% do_raw_spin_lock
|
||||
+ 5.69% vma_interval_tree_iter_next
|
||||
+ 4.91% vma_interval_tree_subtree_search
|
||||
+ 3.71% page_referenced_one
|
||||
+
|
||||
+Limitations of the Current Implementation
|
||||
+-----------------------------------------
|
||||
+Notion of the Active/Inactive
|
||||
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+For servers equipped with hundreds of gigabytes of memory, the
|
||||
+granularity of the active/inactive is too coarse to be useful for job
|
||||
+scheduling. And false active/inactive rates are relatively high.
|
||||
+
|
||||
+For phones and laptops, the eviction is biased toward file pages
|
||||
+because the selection has to resort to heuristics as direct
|
||||
+comparisons between anon and file types are infeasible.
|
||||
+
|
||||
+For systems with multiple nodes and/or memcgs, it is impossible to
|
||||
+compare ``lruvec``\s based on the notion of the active/inactive.
|
||||
+
|
||||
+Incremental Scans via the ``rmap``
|
||||
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+Each incremental scan picks up at where the last scan left off and
|
||||
+stops after it has found a handful of unreferenced pages. For most of
|
||||
+the systems running cloud workloads, incremental scans lose the
|
||||
+advantage under sustained memory pressure due to high ratios of the
|
||||
+number of scanned pages to the number of reclaimed pages. On top of
|
||||
+that, the ``rmap`` has poor memory locality due to its complex data
|
||||
+structures. The combined effects typically result in a high amount of
|
||||
+CPU usage in the reclaim path.
|
||||
+
|
||||
+Benefits of the Multigenerational LRU
|
||||
+-------------------------------------
|
||||
+Notion of Generation Numbers
|
||||
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+The notion of generation numbers introduces a quantitative approach to
|
||||
+memory overcommit. A larger number of pages can be spread out across
|
||||
+configurable generations, and thus they have relatively low false
|
||||
+active/inactive rates. Each generation includes all pages that have
|
||||
+been referenced since the last generation.
|
||||
+
|
||||
+Given an ``lruvec``, scans and the selections between anon and file
|
||||
+types are all based on generation numbers, which are simple and yet
|
||||
+effective. For different ``lruvec``\s, comparisons are still possible
|
||||
+based on birth times of generations.
|
||||
+
|
||||
+Differential Scans via Page Tables
|
||||
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+Each differential scan discovers all pages that have been referenced
|
||||
+since the last scan. Specifically, it walks the ``mm_struct`` list
|
||||
+associated with an ``lruvec`` to scan page tables of processes that
|
||||
+have been scheduled since the last scan. The cost of each differential
|
||||
+scan is roughly proportional to the number of referenced pages it
|
||||
+discovers. Unless address spaces are extremely sparse, page tables
|
||||
+usually have better memory locality than the ``rmap``. The end result
|
||||
+is generally a significant reduction in CPU usage, for most of the
|
||||
+systems running cloud workloads.
|
||||
+
|
||||
+To-do List
|
||||
+==========
|
||||
+KVM Optimization
|
||||
+----------------
|
||||
+Support shadow page table walk.
|
||||
+
|
||||
+NUMA Optimization
|
||||
+-----------------
|
||||
+Add per-node RSS for ``should_skip_mm()``.
|
||||
+
|
||||
+Refault Tracking Optimization
|
||||
+-----------------------------
|
||||
+Use generation numbers rather than LRU positions in
|
||||
+``workingset_eviction()`` and ``workingset_refault()``.
|
||||
--
|
||||
2.31.0.rc2.261.g7f71774620-goog
|
||||
|
||||
|
475856
sys-kernel/pinephone-sources/files/all-5.11.4.patch
Normal file
475856
sys-kernel/pinephone-sources/files/all-5.11.4.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
From 298c18c5bdc5f1ff302e6c83d642a7ce6307c921 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Braam <martijn@brixit.nl>
|
||||
Date: Fri, 4 Sep 2020 17:35:39 +0200
|
||||
Subject: [PATCH] media: gc2145: Added BGGR bayer mode
|
||||
|
||||
Not all raw bayer modes from the sensor match up with the ones defined
|
||||
in v4l, mostly because they're mirrored.
|
||||
---
|
||||
drivers/media/i2c/gc2145.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c
|
||||
index 40a50ee17fd3..bed611045de9 100644
|
||||
--- a/drivers/media/i2c/gc2145.c
|
||||
+++ b/drivers/media/i2c/gc2145.c
|
||||
@@ -187,6 +187,11 @@ static const struct gc2145_pixfmt gc2145_formats[] = {
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.fmt_setup = 0x06,
|
||||
},
|
||||
+ {
|
||||
+ .code = MEDIA_BUS_FMT_SBGGR8_1X8,
|
||||
+ .colorspace = V4L2_COLORSPACE_RAW,
|
||||
+ .fmt_setup = 0x17,
|
||||
+ },
|
||||
};
|
||||
|
||||
static const struct gc2145_pixfmt *gc2145_find_format(u32 code)
|
||||
--
|
||||
GitLab
|
||||
|
390
sys-kernel/pinephone-sources/files/camera-autofocus.patch
Normal file
390
sys-kernel/pinephone-sources/files/camera-autofocus.patch
Normal file
@ -0,0 +1,390 @@
|
||||
From c2ea6ff2636e4e2bc88244c57197318b3d9d806b Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Braam <martijn@brixit.nl>
|
||||
Date: Mon, 28 Sep 2020 14:26:11 +0200
|
||||
Subject: [PATCH] media: ov5640: Implement autofocus
|
||||
|
||||
The autofocus functionality needs a firmware blob loaded into the
|
||||
internal microcontroller.
|
||||
|
||||
V4L2 doesn't have an api to control all autofocus functionality, but
|
||||
this at least makes it possible to focus on the center of the sensor.
|
||||
|
||||
Signed-off-by: Martijn Braam <martijn@brixit.nl>
|
||||
---
|
||||
drivers/media/i2c/ov5640.c | 254 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 254 insertions(+)
|
||||
|
||||
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
||||
index 16ecde24a192..d90fc35e8503 100644
|
||||
--- a/drivers/media/i2c/ov5640.c
|
||||
+++ b/drivers/media/i2c/ov5640.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
+#include <linux/firmware.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -31,7 +32,11 @@
|
||||
|
||||
#define OV5640_DEFAULT_SLAVE_ID 0x3c
|
||||
|
||||
+#define OV5640_REG_SYS_RESET00 0x3000
|
||||
+#define OV5640_REG_SYS_RESET01 0x3001
|
||||
#define OV5640_REG_SYS_RESET02 0x3002
|
||||
+#define OV5640_REG_SYS_CLOCK_ENABLE00 0x3004
|
||||
+#define OV5640_REG_SYS_CLOCK_ENABLE01 0x3005
|
||||
#define OV5640_REG_SYS_CLOCK_ENABLE02 0x3006
|
||||
#define OV5640_REG_SYS_CTRL0 0x3008
|
||||
#define OV5640_REG_CHIP_ID 0x300a
|
||||
@@ -39,6 +44,14 @@
|
||||
#define OV5640_REG_PAD_OUTPUT_ENABLE01 0x3017
|
||||
#define OV5640_REG_PAD_OUTPUT_ENABLE02 0x3018
|
||||
#define OV5640_REG_PAD_OUTPUT00 0x3019
|
||||
+#define OV5640_REG_FW_CMD_MAIN 0x3022
|
||||
+#define OV5640_REG_FW_CMD_ACK 0x3023
|
||||
+#define OV5640_REG_FW_CMD_PARA0 0x3024
|
||||
+#define OV5640_REG_FW_CMD_PARA1 0x3025
|
||||
+#define OV5640_REG_FW_CMD_PARA2 0x3026
|
||||
+#define OV5640_REG_FW_CMD_PARA3 0x3027
|
||||
+#define OV5640_REG_FW_CMD_PARA4 0x3028
|
||||
+#define OV5640_REG_FW_STATUS 0x3029
|
||||
#define OV5640_REG_SYSTEM_CONTROL1 0x302e
|
||||
#define OV5640_REG_SC_PLL_CTRL0 0x3034
|
||||
#define OV5640_REG_SC_PLL_CTRL1 0x3035
|
||||
@@ -57,6 +70,7 @@
|
||||
#define OV5640_REG_AEC_PK_MANUAL 0x3503
|
||||
#define OV5640_REG_AEC_PK_REAL_GAIN 0x350a
|
||||
#define OV5640_REG_AEC_PK_VTS 0x350c
|
||||
+#define OV5640_REG_VCM_CONTROL4 0x3606
|
||||
#define OV5640_REG_TIMING_DVPHO 0x3808
|
||||
#define OV5640_REG_TIMING_DVPVO 0x380a
|
||||
#define OV5640_REG_TIMING_HTS 0x380c
|
||||
@@ -93,6 +107,20 @@
|
||||
#define OV5640_REG_SDE_CTRL4 0x5584
|
||||
#define OV5640_REG_SDE_CTRL5 0x5585
|
||||
#define OV5640_REG_AVG_READOUT 0x56a1
|
||||
+#define OV5640_REG_FIRMWARE_BASE 0x8000
|
||||
+
|
||||
+#define OV5640_FW_STATUS_S_FIRMWARE 0x7f
|
||||
+#define OV5640_FW_STATUS_S_STARTUP 0x7e
|
||||
+#define OV5640_FW_STATUS_S_IDLE 0x70
|
||||
+#define OV5640_FW_STATUS_S_FOCUSING 0x00
|
||||
+#define OV5640_FW_STATUS_S_FOCUSED 0x10
|
||||
+
|
||||
+#define OV5640_FW_CMD_TRIGGER_FOCUS 0x03
|
||||
+#define OV5640_FW_CMD_CONTINUOUS_FOCUS 0x04
|
||||
+#define OV5640_FW_CMD_GET_FOCUS_RESULT 0x07
|
||||
+#define OV5640_FW_CMD_RELEASE_FOCUS 0x08
|
||||
+#define OV5640_FW_CMD_ZONE_CONFIG 0x12
|
||||
+#define OV5640_FW_CMD_DEFAULT_ZONES 0x80
|
||||
|
||||
enum ov5640_mode_id {
|
||||
OV5640_MODE_QCIF_176_144 = 0,
|
||||
@@ -216,6 +244,12 @@ struct ov5640_ctrls {
|
||||
struct v4l2_ctrl *auto_gain;
|
||||
struct v4l2_ctrl *gain;
|
||||
};
|
||||
+ struct {
|
||||
+ struct v4l2_ctrl *focus_auto;
|
||||
+ struct v4l2_ctrl *af_start;
|
||||
+ struct v4l2_ctrl *af_stop;
|
||||
+ struct v4l2_ctrl *af_status;
|
||||
+ };
|
||||
struct v4l2_ctrl *brightness;
|
||||
struct v4l2_ctrl *light_freq;
|
||||
struct v4l2_ctrl *saturation;
|
||||
@@ -259,6 +293,8 @@ struct ov5640_dev {
|
||||
|
||||
bool pending_mode_change;
|
||||
bool streaming;
|
||||
+
|
||||
+ bool af_initialized;
|
||||
};
|
||||
|
||||
static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd)
|
||||
@@ -1982,6 +2018,99 @@ static void ov5640_reset(struct ov5640_dev *sensor)
|
||||
usleep_range(20000, 25000);
|
||||
}
|
||||
|
||||
+static int ov5640_copy_fw_to_device(struct ov5640_dev *sensor,
|
||||
+ const struct firmware *fw)
|
||||
+{
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ const u8 *data = (const u8 *)fw->data;
|
||||
+ u8 fw_status;
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ // Putting MCU in reset state
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x20);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Write firmware
|
||||
+ for (i = 0; i < fw->size / sizeof(u8); i++)
|
||||
+ ov5640_write_reg(sensor,
|
||||
+ OV5640_REG_FIRMWARE_BASE + i,
|
||||
+ data[i]);
|
||||
+
|
||||
+ // Reset MCU state
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_MAIN, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_ACK, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA0, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA1, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA2, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA3, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA4, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_STATUS, 0x7f);
|
||||
+
|
||||
+ // Start AF MCU
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x00);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_info(&client->dev, "firmware upload success\n");
|
||||
+
|
||||
+ // Wait for firmware to be ready
|
||||
+ for (i = 0; i < 100; i++) {
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status);
|
||||
+ if (fw_status == OV5640_FW_STATUS_S_IDLE) {
|
||||
+ dev_info(&client->dev, "fw started after %d ms\n", i * 50);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+ dev_err(&client->dev, "uploaded firmware didn't start, got to 0x%x\n", fw_status);
|
||||
+ return -ETIMEDOUT;
|
||||
+}
|
||||
+
|
||||
+static int ov5640_af_init(struct ov5640_dev *sensor)
|
||||
+{
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ const char* fwname = "ov5640_af.bin";
|
||||
+ const struct firmware *fw;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (sensor->af_initialized) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (firmware_request_nowarn(&fw, fwname, &client->dev) == 0) {
|
||||
+ ret = ov5640_copy_fw_to_device(sensor, fw);
|
||||
+ if (ret == 0)
|
||||
+ sensor->af_initialized = 1;
|
||||
+ } else {
|
||||
+ dev_warn(&client->dev, "%s: no autofocus firmware available (%s)\n",
|
||||
+ __func__, fwname);
|
||||
+ ret = -1;
|
||||
+ }
|
||||
+ release_firmware(fw);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Enable AF systems
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE00,
|
||||
+ (BIT(6) | BIT(5)), (BIT(6) | BIT(5)));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE01,
|
||||
+ BIT(6), BIT(6));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Set lens focus driver on
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_VCM_CONTROL4, 0x3f);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int ov5640_set_power_on(struct ov5640_dev *sensor)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
@@ -2003,6 +2132,8 @@ static int ov5640_set_power_on(struct ov5640_dev *sensor)
|
||||
goto xclk_off;
|
||||
}
|
||||
|
||||
+ sensor->af_initialized = 0;
|
||||
+
|
||||
ov5640_reset(sensor);
|
||||
ov5640_power(sensor, true);
|
||||
|
||||
@@ -2392,6 +2523,35 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
|
||||
is_jpeg ? (BIT(5) | BIT(3)) : 0);
|
||||
}
|
||||
|
||||
+static int ov5640_fw_command(struct ov5640_dev *sensor, int command)
|
||||
+{
|
||||
+ u8 fw_ack;
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_FW_CMD_ACK, 0x01);
|
||||
+ if(ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_FW_CMD_MAIN, command);
|
||||
+ if(ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < 100; i++) {
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_CMD_ACK, &fw_ack);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (fw_ack == 0){
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+ return -ETIMEDOUT;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/*
|
||||
* Sensor Controls.
|
||||
*/
|
||||
@@ -2508,6 +2668,41 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int ov5640_set_ctrl_focus(struct ov5640_dev *sensor, int command)
|
||||
+{
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ov5640_af_init(sensor);
|
||||
+ if (ret) {
|
||||
+ dev_err(&client->dev, "%s: no autofocus firmware loaded\n",
|
||||
+ __func__);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (command == OV5640_FW_CMD_RELEASE_FOCUS) {
|
||||
+ dev_dbg(&client->dev, "%s: Releasing autofocus\n",
|
||||
+ __func__);
|
||||
+ return ov5640_fw_command(sensor, OV5640_FW_CMD_RELEASE_FOCUS);
|
||||
+ }
|
||||
+
|
||||
+ // Restart zone config
|
||||
+ ret = ov5640_fw_command(sensor, OV5640_FW_CMD_ZONE_CONFIG);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Set default focus zones
|
||||
+ ret = ov5640_fw_command(sensor, OV5640_FW_CMD_DEFAULT_ZONES);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(&client->dev, "%s: Triggering autofocus\n",
|
||||
+ __func__);
|
||||
+
|
||||
+ // Start focussing
|
||||
+ return ov5640_fw_command(sensor, command);
|
||||
+}
|
||||
+
|
||||
static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
|
||||
{
|
||||
struct ov5640_ctrls *ctrls = &sensor->ctrls;
|
||||
@@ -2614,6 +2809,32 @@ static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
|
||||
(BIT(2) | BIT(1)) : 0);
|
||||
}
|
||||
|
||||
+static int ov5640_get_af_status(struct ov5640_dev *sensor)
|
||||
+{
|
||||
+ u8 fw_status;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ switch (fw_status) {
|
||||
+ case OV5640_FW_STATUS_S_FIRMWARE:
|
||||
+ case OV5640_FW_STATUS_S_STARTUP:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_FAILED;
|
||||
+ break;
|
||||
+ case OV5640_FW_STATUS_S_IDLE:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_IDLE;
|
||||
+ break;
|
||||
+ case OV5640_FW_STATUS_S_FOCUSED:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_REACHED;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_BUSY;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
|
||||
@@ -2635,6 +2856,12 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
return val;
|
||||
sensor->ctrls.exposure->val = val;
|
||||
break;
|
||||
+ case V4L2_CID_FOCUS_AUTO:
|
||||
+ val = ov5640_get_af_status(sensor);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+ sensor->ctrls.af_status->val = val;
|
||||
+ break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2666,6 +2893,18 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_AUTO_WHITE_BALANCE:
|
||||
ret = ov5640_set_ctrl_white_balance(sensor, ctrl->val);
|
||||
break;
|
||||
+ case V4L2_CID_FOCUS_AUTO:
|
||||
+ if (ctrl->val)
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_CONTINUOUS_FOCUS);
|
||||
+ else
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_RELEASE_FOCUS);
|
||||
+ break;
|
||||
+ case V4L2_CID_AUTO_FOCUS_START:
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_TRIGGER_FOCUS);
|
||||
+ break;
|
||||
+ case V4L2_CID_AUTO_FOCUS_STOP:
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_RELEASE_FOCUS);
|
||||
+ break;
|
||||
case V4L2_CID_HUE:
|
||||
ret = ov5640_set_ctrl_hue(sensor, ctrl->val);
|
||||
break;
|
||||
@@ -2738,6 +2977,20 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
|
||||
ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
|
||||
0, 1023, 1, 0);
|
||||
|
||||
+ /* Autofocus */
|
||||
+ ctrls->focus_auto = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_AUTO,
|
||||
+ 0, 1, 1, 0);
|
||||
+ ctrls->af_start = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_FOCUS_START,
|
||||
+ 0, 1, 1, 0);
|
||||
+ ctrls->af_stop = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_FOCUS_STOP,
|
||||
+ 0, 1, 1, 0);
|
||||
+ ctrls->af_status = v4l2_ctrl_new_std(hdl, ops,
|
||||
+ V4L2_CID_AUTO_FOCUS_STATUS, 0,
|
||||
+ (V4L2_AUTO_FOCUS_STATUS_BUSY |
|
||||
+ V4L2_AUTO_FOCUS_STATUS_REACHED |
|
||||
+ V4L2_AUTO_FOCUS_STATUS_FAILED),
|
||||
+ 0, V4L2_AUTO_FOCUS_STATUS_IDLE);
|
||||
+
|
||||
ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
|
||||
0, 255, 1, 64);
|
||||
ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
|
||||
@@ -2771,6 +3024,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
|
||||
v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
|
||||
v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
|
||||
v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
|
||||
+ v4l2_ctrl_cluster(4, &ctrls->focus_auto);
|
||||
|
||||
sensor->sd.ctrl_handler = hdl;
|
||||
return 0;
|
||||
--
|
||||
GitLab
|
||||
|
6480
sys-kernel/pinephone-sources/files/config
Normal file
6480
sys-kernel/pinephone-sources/files/config
Normal file
File diff suppressed because it is too large
Load Diff
5849
sys-kernel/pinephone-sources/files/config-5.10.14
Normal file
5849
sys-kernel/pinephone-sources/files/config-5.10.14
Normal file
File diff suppressed because it is too large
Load Diff
5737
sys-kernel/pinephone-sources/files/config-5.10.15
Normal file
5737
sys-kernel/pinephone-sources/files/config-5.10.15
Normal file
File diff suppressed because it is too large
Load Diff
5786
sys-kernel/pinephone-sources/files/config-5.11.0
Normal file
5786
sys-kernel/pinephone-sources/files/config-5.11.0
Normal file
File diff suppressed because it is too large
Load Diff
5787
sys-kernel/pinephone-sources/files/config-5.11.6
Normal file
5787
sys-kernel/pinephone-sources/files/config-5.11.6
Normal file
File diff suppressed because it is too large
Load Diff
6359
sys-kernel/pinephone-sources/files/config-5.9.11
Normal file
6359
sys-kernel/pinephone-sources/files/config-5.9.11
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10
sys-kernel/pinephone-sources/files/dracut-pp.conf
Normal file
10
sys-kernel/pinephone-sources/files/dracut-pp.conf
Normal file
@ -0,0 +1,10 @@
|
||||
# load kernel modules that's needed to run accelarated osk SDL
|
||||
force_drivers+=" lima gpu_sched goodix evdev sun6i_mipi_dsi sun8i-drm-hdmi sun8i-mixer panel-sitronix-st7703 "
|
||||
# pmic
|
||||
force_drivers+=" axp20x-pek axp20x_adc "
|
||||
# force feedback
|
||||
force_drivers+=" gpio-vibra "
|
||||
# encryption module
|
||||
force_drivers+=" crc-t10dif "
|
||||
# emmc/sd driver
|
||||
force_drivers+=" sunxi-mmc "
|
@ -0,0 +1,280 @@
|
||||
From patchwork Sat Feb 22 02:42:10 2020
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: Qiang Yu <yuq825@gmail.com>
|
||||
X-Patchwork-Id: 11397805
|
||||
Return-Path: <SRS0=2VhQ=4K=lists.freedesktop.org=dri-devel-bounces@kernel.org>
|
||||
Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
|
||||
[172.30.200.123])
|
||||
by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AB9901395
|
||||
for <patchwork-dri-devel@patchwork.kernel.org>;
|
||||
Sat, 22 Feb 2020 02:43:37 +0000 (UTC)
|
||||
Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
|
||||
(No client certificate requested)
|
||||
by mail.kernel.org (Postfix) with ESMTPS id 88DCB20722
|
||||
for <patchwork-dri-devel@patchwork.kernel.org>;
|
||||
Sat, 22 Feb 2020 02:43:37 +0000 (UTC)
|
||||
Authentication-Results: mail.kernel.org;
|
||||
dkim=fail reason="signature verification failed" (2048-bit key)
|
||||
header.d=gmail.com header.i=@gmail.com header.b="CyObTePI"
|
||||
DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 88DCB20722
|
||||
Authentication-Results: mail.kernel.org;
|
||||
dmarc=fail (p=none dis=none) header.from=gmail.com
|
||||
Authentication-Results: mail.kernel.org;
|
||||
spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org
|
||||
Received: from gabe.freedesktop.org (localhost [127.0.0.1])
|
||||
by gabe.freedesktop.org (Postfix) with ESMTP id B7A676F5BC;
|
||||
Sat, 22 Feb 2020 02:43:36 +0000 (UTC)
|
||||
X-Original-To: dri-devel@lists.freedesktop.org
|
||||
Delivered-To: dri-devel@lists.freedesktop.org
|
||||
Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com
|
||||
[IPv6:2607:f8b0:4864:20::443])
|
||||
by gabe.freedesktop.org (Postfix) with ESMTPS id 2FC626F5C4;
|
||||
Sat, 22 Feb 2020 02:43:33 +0000 (UTC)
|
||||
Received: by mail-pf1-x443.google.com with SMTP id b185so2253361pfb.7;
|
||||
Fri, 21 Feb 2020 18:43:33 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
|
||||
h=from:to:cc:subject:date:message-id:in-reply-to:references;
|
||||
bh=zmu9+9eRFyNY15h9Ek3Z+76nUFKQGmj+zanQeEr6WEg=;
|
||||
b=CyObTePIC42njRlTMpIZ5jbV07vgmVzwQlIiClf8yxmuRae7p5rmPK3RHoGWUE6mkk
|
||||
UzllkCHvhzvt7xJeIXgotAX4N0urh0fusNlyXvE7soJ3jqUTaD2H3TvbAM0MRJq7UDUK
|
||||
AaNJLBmXC2yJo03J1uSp6YEyYbywQiMhQzFK79fByFG5hWbs376E1Wy3Qr0oQizMIxph
|
||||
R7MjdGqFOb3hoejatRsG9B+ZrhD5tsUWUOzAWgFoNNgROmPyzO6RSdqRf+R51mRMg2+Q
|
||||
7CG+ZMuNBgUyKNliZ2Z6qM/WB8h6d4zd5yyCRoQtealQsMcxy3ERJkGSa+XzXACOw1bW
|
||||
HiqA==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20161025;
|
||||
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
|
||||
:references;
|
||||
bh=zmu9+9eRFyNY15h9Ek3Z+76nUFKQGmj+zanQeEr6WEg=;
|
||||
b=SfIr8M5GIeETLcx/eWSJyGbZ97nYp9ucP4ZU6+QDVR67yOJvyK9xQ19orX0oLL4JzM
|
||||
sJu1kScGzfwMEmcKreQfO9W/M48PzEGuQbf4jPMFFslFKsxJYHYU0g8vJvCfmSFRc+uI
|
||||
CyBxeIgtwDfIMm8YFcqe16BwuPHqYZf3UNxPPOLJEd36t6VkBMRMjedSvCrzo3Z9vGgI
|
||||
/enU6NAeoiBdJGaRIV996k7frtHuIHCQYmhuQMl2c6kSfq/8YJDuwhQF5JyBKPpmsbun
|
||||
enEzl2SHAxR4US54RlWxvFJkoJqW3i6VoRHc7NhqjAscitShyKvjM3MkMZj85mC4DOXg
|
||||
+Uew==
|
||||
X-Gm-Message-State: APjAAAVeIOlNq5GJmxoyR4KHXrichrK35qwKJM0c31ZKqdCZpidHIHv2
|
||||
Fs9QJulvy/h7w2ta39NPizPVh8dbDyMxTA==
|
||||
X-Google-Smtp-Source:
|
||||
APXvYqwdgtryziiyB3qwd3ITAq/0Lqdj/vlMbD6j/DyX5dGHIYAmpNW5eZYvU/00f14I634rGNHvOw==
|
||||
X-Received: by 2002:aa7:957c:: with SMTP id
|
||||
x28mr40685571pfq.157.1582339412254;
|
||||
Fri, 21 Feb 2020 18:43:32 -0800 (PST)
|
||||
Received: from localhost.localdomain ([103.219.195.110])
|
||||
by smtp.gmail.com with ESMTPSA id u13sm3797317pjn.29.2020.02.21.18.43.29
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Fri, 21 Feb 2020 18:43:31 -0800 (PST)
|
||||
From: Qiang Yu <yuq825@gmail.com>
|
||||
To: dri-devel@lists.freedesktop.org
|
||||
Subject: [PATCH 5/5] drm/lima: add LIMA_BO_FLAG_FORCE_VA
|
||||
Date: Sat, 22 Feb 2020 10:42:10 +0800
|
||||
Message-Id: <20200222024210.18697-6-yuq825@gmail.com>
|
||||
X-Mailer: git-send-email 2.17.1
|
||||
In-Reply-To: <20200222024210.18697-1-yuq825@gmail.com>
|
||||
References: <20200222024210.18697-1-yuq825@gmail.com>
|
||||
X-BeenThere: dri-devel@lists.freedesktop.org
|
||||
X-Mailman-Version: 2.1.29
|
||||
Precedence: list
|
||||
List-Id: Direct Rendering Infrastructure - Development
|
||||
<dri-devel.lists.freedesktop.org>
|
||||
List-Unsubscribe: <https://lists.freedesktop.org/mailman/options/dri-devel>,
|
||||
<mailto:dri-devel-request@lists.freedesktop.org?subject=unsubscribe>
|
||||
List-Archive: <https://lists.freedesktop.org/archives/dri-devel>
|
||||
List-Post: <mailto:dri-devel@lists.freedesktop.org>
|
||||
List-Help: <mailto:dri-devel-request@lists.freedesktop.org?subject=help>
|
||||
List-Subscribe: <https://lists.freedesktop.org/mailman/listinfo/dri-devel>,
|
||||
<mailto:dri-devel-request@lists.freedesktop.org?subject=subscribe>
|
||||
Cc: lima@lists.freedesktop.org, David Airlie <airlied@linux.ie>,
|
||||
Vasily Khoruzhick <anarsoul@gmail.com>,
|
||||
Andreas Baierl <ichgeh@imkreisrum.de>,
|
||||
Qiang Yu <yuq825@gmail.com>, Icenowy Zheng <icenowy@aosc.io>,
|
||||
Erico Nunes <nunes.erico@gmail.com>
|
||||
MIME-Version: 1.0
|
||||
Errors-To: dri-devel-bounces@lists.freedesktop.org
|
||||
Sender: "dri-devel" <dri-devel-bounces@lists.freedesktop.org>
|
||||
|
||||
User can force created buffer to be mapped to GPU VM at a user
|
||||
specified address. This is used for debug tools in user space to
|
||||
replay some task.
|
||||
|
||||
Signed-off-by: Qiang Yu <yuq825@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/lima/lima_drv.c | 26 +++++++++++++++++++-------
|
||||
drivers/gpu/drm/lima/lima_gem.c | 7 +++++--
|
||||
drivers/gpu/drm/lima/lima_gem.h | 4 +++-
|
||||
drivers/gpu/drm/lima/lima_vm.c | 13 ++++++++++++-
|
||||
include/uapi/drm/lima_drm.h | 9 +++++++--
|
||||
5 files changed, 46 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
|
||||
index 8c5adc025902..f65021ea9598 100644
|
||||
--- a/drivers/gpu/drm/lima/lima_drv.c
|
||||
+++ b/drivers/gpu/drm/lima/lima_drv.c
|
||||
@@ -73,16 +73,27 @@ static int lima_ioctl_gem_create(struct drm_device *dev, void *data, struct drm_
|
||||
{
|
||||
struct drm_lima_gem_create *args = data;
|
||||
|
||||
- if (args->pad)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- if (args->flags & ~(LIMA_BO_FLAG_HEAP))
|
||||
+ if (args->flags & ~(LIMA_BO_FLAG_HEAP | LIMA_BO_FLAG_FORCE_VA))
|
||||
return -EINVAL;
|
||||
|
||||
if (args->size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
- return lima_gem_create_handle(dev, file, args->size, args->flags, &args->handle);
|
||||
+ if (args->flags & LIMA_BO_FLAG_FORCE_VA) {
|
||||
+ u64 max = (u64)args->va + (u64)args->size;
|
||||
+
|
||||
+ if (max > LIMA_VA_RESERVE_START)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!IS_ALIGNED(args->va, PAGE_SIZE))
|
||||
+ return -EINVAL;
|
||||
+ } else {
|
||||
+ if (args->va)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return lima_gem_create_handle(dev, file, args->size, args->flags,
|
||||
+ &args->handle, args->va);
|
||||
}
|
||||
|
||||
static int lima_ioctl_gem_info(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
@@ -253,6 +264,7 @@ DEFINE_DRM_GEM_FOPS(lima_drm_driver_fops);
|
||||
* Changelog:
|
||||
*
|
||||
* - 1.1.0 - add heap buffer support
|
||||
+ * - 1.2.0 - add force va support
|
||||
*/
|
||||
|
||||
static struct drm_driver lima_drm_driver = {
|
||||
@@ -264,9 +276,9 @@ static struct drm_driver lima_drm_driver = {
|
||||
.fops = &lima_drm_driver_fops,
|
||||
.name = "lima",
|
||||
.desc = "lima DRM",
|
||||
- .date = "20191231",
|
||||
+ .date = "20200215",
|
||||
.major = 1,
|
||||
- .minor = 1,
|
||||
+ .minor = 2,
|
||||
.patchlevel = 0,
|
||||
|
||||
.gem_create_object = lima_gem_create_object,
|
||||
diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
|
||||
index 5404e0d668db..c28d90756584 100644
|
||||
--- a/drivers/gpu/drm/lima/lima_gem.c
|
||||
+++ b/drivers/gpu/drm/lima/lima_gem.c
|
||||
@@ -95,7 +95,7 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
|
||||
}
|
||||
|
||||
int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
||||
- u32 size, u32 flags, u32 *handle)
|
||||
+ u32 size, u32 flags, u32 *handle, u32 va)
|
||||
{
|
||||
int err;
|
||||
gfp_t mask;
|
||||
@@ -116,8 +116,11 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
||||
mask |= __GFP_DMA32;
|
||||
mapping_set_gfp_mask(obj->filp->f_mapping, mask);
|
||||
|
||||
+ bo = to_lima_bo(obj);
|
||||
+ bo->flags = flags;
|
||||
+ bo->force_va = va;
|
||||
+
|
||||
if (is_heap) {
|
||||
- bo = to_lima_bo(obj);
|
||||
err = lima_heap_alloc(bo, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h
|
||||
index ccea06142f4b..2a6db0c0be89 100644
|
||||
--- a/drivers/gpu/drm/lima/lima_gem.h
|
||||
+++ b/drivers/gpu/drm/lima/lima_gem.h
|
||||
@@ -15,6 +15,8 @@ struct lima_bo {
|
||||
struct mutex lock;
|
||||
struct list_head va;
|
||||
|
||||
+ u32 flags;
|
||||
+ u32 force_va;
|
||||
size_t heap_size;
|
||||
};
|
||||
|
||||
@@ -37,7 +39,7 @@ static inline struct dma_resv *lima_bo_resv(struct lima_bo *bo)
|
||||
int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm);
|
||||
struct drm_gem_object *lima_gem_create_object(struct drm_device *dev, size_t size);
|
||||
int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
|
||||
- u32 size, u32 flags, u32 *handle);
|
||||
+ u32 size, u32 flags, u32 *handle, u32 va);
|
||||
int lima_gem_get_info(struct drm_file *file, u32 handle, u32 *va, u64 *offset);
|
||||
int lima_gem_submit(struct drm_file *file, struct lima_submit *submit);
|
||||
int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, s64 timeout_ns);
|
||||
diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c
|
||||
index 5b92fb82674a..be0510032538 100644
|
||||
--- a/drivers/gpu/drm/lima/lima_vm.c
|
||||
+++ b/drivers/gpu/drm/lima/lima_vm.c
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
+#include <drm/lima_drm.h>
|
||||
|
||||
#include "lima_device.h"
|
||||
#include "lima_vm.h"
|
||||
@@ -93,6 +94,7 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, bool create)
|
||||
struct lima_bo_va *bo_va;
|
||||
struct sg_dma_page_iter sg_iter;
|
||||
int offset = 0, err;
|
||||
+ u64 start, end;
|
||||
|
||||
mutex_lock(&bo->lock);
|
||||
|
||||
@@ -120,7 +122,16 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, bool create)
|
||||
|
||||
mutex_lock(&vm->lock);
|
||||
|
||||
- err = drm_mm_insert_node(&vm->mm, &bo_va->node, lima_bo_size(bo));
|
||||
+ if (bo->flags & LIMA_BO_FLAG_FORCE_VA) {
|
||||
+ start = bo->force_va;
|
||||
+ end = start + lima_bo_size(bo);
|
||||
+ } else {
|
||||
+ start = 0;
|
||||
+ end = U64_MAX;
|
||||
+ }
|
||||
+
|
||||
+ err = drm_mm_insert_node_in_range(&vm->mm, &bo_va->node, lima_bo_size(bo),
|
||||
+ 0, 0, start, end, 0);
|
||||
if (err)
|
||||
goto err_out1;
|
||||
|
||||
diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h
|
||||
index 1ec58d652a5a..3e699bb78394 100644
|
||||
--- a/include/uapi/drm/lima_drm.h
|
||||
+++ b/include/uapi/drm/lima_drm.h
|
||||
@@ -37,7 +37,12 @@ struct drm_lima_get_param {
|
||||
* due to lack of heap memory. size field of heap buffer is an up bound of
|
||||
* the backup memory which can be set to a fairly large value.
|
||||
*/
|
||||
-#define LIMA_BO_FLAG_HEAP (1 << 0)
|
||||
+#define LIMA_BO_FLAG_HEAP (1 << 0)
|
||||
+/*
|
||||
+ * force buffer GPU virtual address to be drm_lima_gem_create.va, this is
|
||||
+ * used to replay some task with fixed GPU virtual address
|
||||
+ */
|
||||
+#define LIMA_BO_FLAG_FORCE_VA (1 << 1)
|
||||
|
||||
/**
|
||||
* create a buffer for used by GPU
|
||||
@@ -46,7 +51,7 @@ struct drm_lima_gem_create {
|
||||
__u32 size; /* in, buffer size */
|
||||
__u32 flags; /* in, buffer flags */
|
||||
__u32 handle; /* out, GEM buffer handle */
|
||||
- __u32 pad; /* pad, must be zero */
|
||||
+ __u32 va; /* in, buffer va */
|
||||
};
|
||||
|
||||
/**
|
@ -0,0 +1,18 @@
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 086b5ebfa512..b4a71b02c474 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -304,11 +304,13 @@ &codec {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&aif2_pins>, <&aif3_pins>;
|
||||
status = "okay";
|
||||
+ allwinner,inverted-jack-detection;
|
||||
};
|
||||
|
||||
&codec_analog {
|
||||
cpvdd-supply = <®_eldo1>;
|
||||
status = "okay";
|
||||
+ allwinner,internal-bias-resistor;
|
||||
};
|
||||
|
||||
&cpu0 {
|
@ -0,0 +1,175 @@
|
||||
From 5da6a7e3f4d6e11f4887893672f849d2d4fa5b58 Mon Sep 17 00:00:00 2001
|
||||
From: Clayton Craft <clayton@craftyguy.net>
|
||||
Date: Wed, 16 Dec 2020 20:16:14 -0800
|
||||
Subject: [PATCH] dts: pinephone: drop modem-power node
|
||||
|
||||
---
|
||||
.../allwinner/sun50i-a64-pinephone-1.0.dts | 26 +++---------------
|
||||
.../allwinner/sun50i-a64-pinephone-1.1.dts | 27 +++----------------
|
||||
.../allwinner/sun50i-a64-pinephone-1.2.dts | 27 +++----------------
|
||||
.../dts/allwinner/sun50i-a64-pinephone.dtsi | 12 +++++++++
|
||||
4 files changed, 24 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
index 0f6faa44ce3e..2cc513772172 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
@@ -86,28 +86,6 @@ ®_drivevbus {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
-&uart3 {
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- power-supply = <®_vbat_bb>; /* PL7 */
|
||||
-
|
||||
- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */
|
||||
- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
|
||||
- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
|
||||
-
|
||||
- sleep-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
|
||||
- wakeup-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-RI */
|
||||
-
|
||||
- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */
|
||||
- dtr-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-DTR */
|
||||
- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */
|
||||
-
|
||||
- quectel,qdai = "1,1,0,1,0,0,1,1";
|
||||
- };
|
||||
-};
|
||||
-
|
||||
&usbphy {
|
||||
usb-role-switch;
|
||||
|
||||
@@ -118,6 +96,10 @@ usb0_drd_sw: endpoint {
|
||||
};
|
||||
};
|
||||
|
||||
+&ring_indicator {
|
||||
+ gpios = <&pio 1 2 GPIO_ACTIVE_LOW>; /* PB2 */
|
||||
+};
|
||||
+
|
||||
&sgm3140 {
|
||||
flash-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
enable-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
index 95a880fdc9ce..5f3b6a1a142f 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
@@ -109,34 +109,15 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&ring_indicator {
|
||||
+ gpios = <&pio 1 2 GPIO_ACTIVE_LOW>; /* PB2 */
|
||||
+};
|
||||
+
|
||||
&sgm3140 {
|
||||
enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
|
||||
};
|
||||
|
||||
-&uart3 {
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- power-supply = <®_vbat_bb>; /* PL7 */
|
||||
-
|
||||
- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */
|
||||
- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
|
||||
- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
|
||||
- //status-pwrkey-multiplexed; /* status acts as pwrkey */
|
||||
-
|
||||
- sleep-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
|
||||
- wakeup-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-RI */
|
||||
-
|
||||
- dtr-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-DTR */
|
||||
- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */
|
||||
- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */
|
||||
-
|
||||
- quectel,qdai = "1,1,0,1,0,0,1,1";
|
||||
- };
|
||||
-};
|
||||
-
|
||||
&usbphy {
|
||||
usb-role-switch;
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
index 23ba72508cfc..889841ca5b8a 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
@@ -101,34 +101,15 @@
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
+&ring_indicator {
|
||||
+ gpios = <&r_pio 0 6 GPIO_ACTIVE_LOW>; /* PL6 */
|
||||
+};
|
||||
+
|
||||
&sgm3140 {
|
||||
enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
|
||||
};
|
||||
|
||||
-&uart3 {
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- power-supply = <®_vbat_bb>; /* PL7 */
|
||||
-
|
||||
- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */
|
||||
- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
|
||||
- status-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
|
||||
- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
|
||||
-
|
||||
- host-ready-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
|
||||
- wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-RI */
|
||||
-
|
||||
- dtr-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-DTR */
|
||||
- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */
|
||||
- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */
|
||||
-
|
||||
- quectel,qdai = "1,1,0,1,0,0,1,1";
|
||||
- };
|
||||
-};
|
||||
-
|
||||
&usbphy {
|
||||
usb-role-switch;
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 02d82980cf39..979d01de8d84 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -192,6 +192,17 @@ ec25_codec: ec25-codec {
|
||||
compatible = "quectel,ec25";
|
||||
};
|
||||
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys";
|
||||
+
|
||||
+ ring_indicator: ring-indicator {
|
||||
+ label = "Ring Indicator";
|
||||
+ linux,can-disable;
|
||||
+ linux,code = <KEY_WAKEUP>;
|
||||
+ wakeup-source;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
i2c_csi: i2c-csi {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&pio 4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; /* PE13 */
|
||||
@@ -256,6 +267,7 @@ reg_usb_5v: usb-5v {
|
||||
reg_vbat_bb: vbat-bb {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-bb";
|
||||
+ regulator-always-on;
|
||||
regulator-min-microvolt = <3500000>;
|
||||
regulator-max-microvolt = <3500000>;
|
||||
gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,57 @@
|
||||
From c8da73c7ae6192f0229aa728c6443c768bf3450f Mon Sep 17 00:00:00 2001
|
||||
From: Danct12 <danct12@disroot.org>
|
||||
Date: Tue, 13 Oct 2020 08:30:32 +0700
|
||||
Subject: [PATCH] arm64: dts: allwinner: pinetab: enable HDMI
|
||||
|
||||
Signed-off-by: Danct12 <danct12@disroot.org>
|
||||
---
|
||||
.../boot/dts/allwinner/sun50i-a64-pinetab.dts | 26 +++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
index 407837d7fbec..9c96c1532a1e 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
@@ -35,6 +35,17 @@ chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
+ hdmi-connector {
|
||||
+ compatible = "hdmi-connector";
|
||||
+ type = "a";
|
||||
+
|
||||
+ port {
|
||||
+ hdmi_con_in: endpoint {
|
||||
+ remote-endpoint = <&hdmi_out_con>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
i2c-csi {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&pio 4 13 GPIO_ACTIVE_HIGH>; /* PE13 */
|
||||
@@ -462,6 +473,21 @@ ®_rtc_ldo {
|
||||
regulator-name = "vcc-rtc";
|
||||
};
|
||||
|
||||
+&simplefb_hdmi {
|
||||
+ vcc-hdmi-supply = <®_dldo1>;
|
||||
+};
|
||||
+
|
||||
+&hdmi {
|
||||
+ hvcc-supply = <®_dldo1>;
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&hdmi_out {
|
||||
+ hdmi_out_con: endpoint {
|
||||
+ remote-endpoint = <&hdmi_con_in>;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&sound {
|
||||
status = "okay";
|
||||
simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>;
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 7dd3866d9c2bef4bb73a781861aeeec595510509 Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
Date: Fri, 3 Apr 2020 17:13:55 +0200
|
||||
Subject: [PATCH] arm64: dts: allwinner: pinetab: enable jack detection
|
||||
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
index a87790df9..a72c2ec8c 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
@@ -117,11 +117,13 @@ wifi_pwrseq: wifi_pwrseq {
|
||||
};
|
||||
|
||||
&codec {
|
||||
+ allwinner,inverted-jack-detection;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&codec_analog {
|
||||
cpvdd-supply = <®_eldo1>;
|
||||
+ allwinner,internal-bias-resistor;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -448,6 +450,7 @@ ®_rtc_ldo {
|
||||
|
||||
&sound {
|
||||
status = "okay";
|
||||
+ simple-audio-card,name = "PineTab";
|
||||
simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>;
|
||||
simple-audio-card,widgets = "Microphone", "Internal Microphone Left",
|
||||
"Microphone", "Internal Microphone Right",
|
||||
--
|
||||
2.28.0
|
||||
|
67
sys-kernel/pinephone-sources/files/improve-brightness.patch
Normal file
67
sys-kernel/pinephone-sources/files/improve-brightness.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From de578360d41d166ca75b0624e72c5b14f56c0bdf Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
Date: Wed, 19 Aug 2020 13:10:02 +0200
|
||||
Subject: [PATCH] arm64: dts: sun50i-a64-pinephone: improve brightness values
|
||||
on BH/CE
|
||||
|
||||
Commit aad90c10 caused a brightness increase with the previous values.
|
||||
Subsequently, the lowest brightness value would still be fairly bright.
|
||||
|
||||
This commit aims at providing a wider range of usable brightness for
|
||||
1.1+ devices.
|
||||
|
||||
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
---
|
||||
.../boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts | 10 +++++-----
|
||||
.../boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts | 13 ++++++-------
|
||||
2 files changed, 11 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
index 2f993ffc6..c8dcd2291 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
@@ -34,11 +34,11 @@ &backlight {
|
||||
* value here was chosen as a safe default.
|
||||
*/
|
||||
brightness-levels = <
|
||||
- 774 793 814 842
|
||||
- 882 935 1003 1088
|
||||
- 1192 1316 1462 1633
|
||||
- 1830 2054 2309 2596
|
||||
- 2916 3271 3664 4096>;
|
||||
+ 392 413 436 468
|
||||
+ 512 571 647 742
|
||||
+ 857 995 1159 1349
|
||||
+ 1568 1819 2103 2423
|
||||
+ 2779 3176 3614 4096>;
|
||||
num-interpolated-steps = <50>;
|
||||
default-brightness-level = <400>;
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
index 6c3019933..017104df2 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
@@ -24,14 +24,13 @@ &backlight {
|
||||
* chosen as a safe default.
|
||||
*/
|
||||
brightness-levels = <
|
||||
- 5000 5248 5506 5858 6345
|
||||
- 6987 7805 8823 10062 11543
|
||||
- 13287 15317 17654 20319 23336
|
||||
- 26724 30505 34702 39335 44427
|
||||
- 50000
|
||||
- >;
|
||||
+ 392 413 436 468
|
||||
+ 512 571 647 742
|
||||
+ 857 995 1159 1349
|
||||
+ 1568 1819 2103 2423
|
||||
+ 2779 3176 3614 4096>;
|
||||
num-interpolated-steps = <50>;
|
||||
- default-brightness-level = <500>;
|
||||
+ default-brightness-level = <400>;
|
||||
};
|
||||
|
||||
&lis3mdl {
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,67 @@
|
||||
From de578360d41d166ca75b0624e72c5b14f56c0bdf Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
Date: Wed, 19 Aug 2020 13:10:02 +0200
|
||||
Subject: [PATCH] arm64: dts: sun50i-a64-pinephone: improve brightness values
|
||||
on BH/CE
|
||||
|
||||
Commit aad90c10 caused a brightness increase with the previous values.
|
||||
Subsequently, the lowest brightness value would still be fairly bright.
|
||||
|
||||
This commit aims at providing a wider range of usable brightness for
|
||||
1.1+ devices.
|
||||
|
||||
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@collabora.com>
|
||||
---
|
||||
.../boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts | 10 +++++-----
|
||||
.../boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts | 13 ++++++-------
|
||||
2 files changed, 11 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
index 2f993ffc6..c8dcd2291 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
@@ -34,11 +34,11 @@ &backlight {
|
||||
* value here was chosen as a safe default.
|
||||
*/
|
||||
brightness-levels = <
|
||||
- 774 793 814 842
|
||||
- 882 935 1003 1088
|
||||
- 1192 1316 1462 1633
|
||||
- 1830 2054 2309 2596
|
||||
- 2916 3271 3664 4096>;
|
||||
+ 392 413 436 468
|
||||
+ 512 571 647 742
|
||||
+ 857 995 1159 1349
|
||||
+ 1568 1819 2103 2423
|
||||
+ 2779 3176 3614 4096>;
|
||||
num-interpolated-steps = <50>;
|
||||
default-brightness-level = <400>;
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
index 6c3019933..017104df2 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
@@ -24,14 +24,13 @@ &backlight {
|
||||
* chosen as a safe default.
|
||||
*/
|
||||
brightness-levels = <
|
||||
- 5000 5248 5506 5858 6345
|
||||
- 6987 7805 8823 10062 11543
|
||||
- 13287 15317 17654 20319 23336
|
||||
- 26724 30505 34702 39335 44427
|
||||
- 50000
|
||||
- >;
|
||||
+ 392 413 436 468
|
||||
+ 512 571 647 742
|
||||
+ 857 995 1159 1349
|
||||
+ 1568 1819 2103 2423
|
||||
+ 2779 3176 3614 4096>;
|
||||
num-interpolated-steps = <50>;
|
||||
- default-brightness-level = <500>;
|
||||
+ default-brightness-level = <400>;
|
||||
};
|
||||
|
||||
&lis3mdl {
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,9 @@
|
||||
post_upgrade() {
|
||||
if findmnt --fstab -uno SOURCE /boot &>/dev/null && ! mountpoint -q /boot; then
|
||||
echo "WARNING: /boot appears to be a separate partition but is not mounted."
|
||||
fi
|
||||
}
|
||||
|
||||
post_remove() {
|
||||
rm -f boot/initramfs-linux.img
|
||||
}
|
11
sys-kernel/pinephone-sources/files/linux.preset
Normal file
11
sys-kernel/pinephone-sources/files/linux.preset
Normal file
@ -0,0 +1,11 @@
|
||||
# mkinitcpio preset file for the '%PKGBASE%' package
|
||||
|
||||
ALL_config="/etc/mkinitcpio.conf"
|
||||
ALL_kver="%KERNVER%"
|
||||
|
||||
PRESETS=('default')
|
||||
|
||||
#default_config="/etc/mkinitcpio.conf"
|
||||
default_image="/boot/initramfs-linux.img"
|
||||
#default_options=""
|
||||
|
@ -0,0 +1,409 @@
|
||||
From f062022f2a2781d6b8ca63c460b0e72ebac30870 Mon Sep 17 00:00:00 2001
|
||||
From: Martijn Braam <martijn@brixit.nl>
|
||||
Date: Mon, 28 Sep 2020 14:26:11 +0200
|
||||
Subject: [PATCH] media: ov5640: Implement autofocus
|
||||
|
||||
The autofocus functionality needs a firmware blob loaded into the
|
||||
internal microcontroller.
|
||||
|
||||
V4L2 doesn't have an api to control all autofocus functionality, but
|
||||
this at least makes it possible to focus on the center of the sensor.
|
||||
|
||||
Signed-off-by: Martijn Braam <martijn@brixit.nl>
|
||||
---
|
||||
drivers/media/i2c/ov5640.c | 254 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 254 insertions(+)
|
||||
|
||||
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
||||
index df0a507c211f..08a5304c0e95 100644
|
||||
--- a/drivers/media/i2c/ov5640.c
|
||||
+++ b/drivers/media/i2c/ov5640.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
+#include <linux/firmware.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -31,7 +32,11 @@
|
||||
|
||||
#define OV5640_DEFAULT_SLAVE_ID 0x3c
|
||||
|
||||
+#define OV5640_REG_SYS_RESET00 0x3000
|
||||
+#define OV5640_REG_SYS_RESET01 0x3001
|
||||
#define OV5640_REG_SYS_RESET02 0x3002
|
||||
+#define OV5640_REG_SYS_CLOCK_ENABLE00 0x3004
|
||||
+#define OV5640_REG_SYS_CLOCK_ENABLE01 0x3005
|
||||
#define OV5640_REG_SYS_CLOCK_ENABLE02 0x3006
|
||||
#define OV5640_REG_SYS_CTRL0 0x3008
|
||||
#define OV5640_REG_SYS_CTRL0_SW_PWDN 0x42
|
||||
@@ -41,6 +46,14 @@
|
||||
#define OV5640_REG_PAD_OUTPUT_ENABLE01 0x3017
|
||||
#define OV5640_REG_PAD_OUTPUT_ENABLE02 0x3018
|
||||
#define OV5640_REG_PAD_OUTPUT00 0x3019
|
||||
+#define OV5640_REG_FW_CMD_MAIN 0x3022
|
||||
+#define OV5640_REG_FW_CMD_ACK 0x3023
|
||||
+#define OV5640_REG_FW_CMD_PARA0 0x3024
|
||||
+#define OV5640_REG_FW_CMD_PARA1 0x3025
|
||||
+#define OV5640_REG_FW_CMD_PARA2 0x3026
|
||||
+#define OV5640_REG_FW_CMD_PARA3 0x3027
|
||||
+#define OV5640_REG_FW_CMD_PARA4 0x3028
|
||||
+#define OV5640_REG_FW_STATUS 0x3029
|
||||
#define OV5640_REG_SYSTEM_CONTROL1 0x302e
|
||||
#define OV5640_REG_SC_PLL_CTRL0 0x3034
|
||||
#define OV5640_REG_SC_PLL_CTRL1 0x3035
|
||||
@@ -59,6 +72,7 @@
|
||||
#define OV5640_REG_AEC_PK_MANUAL 0x3503
|
||||
#define OV5640_REG_AEC_PK_REAL_GAIN 0x350a
|
||||
#define OV5640_REG_AEC_PK_VTS 0x350c
|
||||
+#define OV5640_REG_VCM_CONTROL4 0x3606
|
||||
#define OV5640_REG_TIMING_DVPHO 0x3808
|
||||
#define OV5640_REG_TIMING_DVPVO 0x380a
|
||||
#define OV5640_REG_TIMING_HTS 0x380c
|
||||
@@ -95,6 +109,20 @@
|
||||
#define OV5640_REG_SDE_CTRL4 0x5584
|
||||
#define OV5640_REG_SDE_CTRL5 0x5585
|
||||
#define OV5640_REG_AVG_READOUT 0x56a1
|
||||
+#define OV5640_REG_FIRMWARE_BASE 0x8000
|
||||
+
|
||||
+#define OV5640_FW_STATUS_S_FIRMWARE 0x7f
|
||||
+#define OV5640_FW_STATUS_S_STARTUP 0x7e
|
||||
+#define OV5640_FW_STATUS_S_IDLE 0x70
|
||||
+#define OV5640_FW_STATUS_S_FOCUSING 0x00
|
||||
+#define OV5640_FW_STATUS_S_FOCUSED 0x10
|
||||
+
|
||||
+#define OV5640_FW_CMD_TRIGGER_FOCUS 0x03
|
||||
+#define OV5640_FW_CMD_CONTINUOUS_FOCUS 0x04
|
||||
+#define OV5640_FW_CMD_GET_FOCUS_RESULT 0x07
|
||||
+#define OV5640_FW_CMD_RELEASE_FOCUS 0x08
|
||||
+#define OV5640_FW_CMD_ZONE_CONFIG 0x12
|
||||
+#define OV5640_FW_CMD_DEFAULT_ZONES 0x80
|
||||
|
||||
enum ov5640_mode_id {
|
||||
OV5640_MODE_QCIF_176_144 = 0,
|
||||
@@ -218,6 +246,12 @@ struct ov5640_ctrls {
|
||||
struct v4l2_ctrl *auto_gain;
|
||||
struct v4l2_ctrl *gain;
|
||||
};
|
||||
+ struct {
|
||||
+ struct v4l2_ctrl *focus_auto;
|
||||
+ struct v4l2_ctrl *af_start;
|
||||
+ struct v4l2_ctrl *af_stop;
|
||||
+ struct v4l2_ctrl *af_status;
|
||||
+ };
|
||||
struct v4l2_ctrl *brightness;
|
||||
struct v4l2_ctrl *light_freq;
|
||||
struct v4l2_ctrl *saturation;
|
||||
@@ -261,6 +295,8 @@ struct ov5640_dev {
|
||||
|
||||
bool pending_mode_change;
|
||||
bool streaming;
|
||||
+
|
||||
+ bool af_initialized;
|
||||
};
|
||||
|
||||
static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd)
|
||||
@@ -1967,6 +2003,118 @@ static void ov5640_reset(struct ov5640_dev *sensor)
|
||||
usleep_range(20000, 25000);
|
||||
}
|
||||
|
||||
+static int ov5640_copy_fw_to_device(struct ov5640_dev *sensor,
|
||||
+ const struct firmware *fw)
|
||||
+{
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ const u8 *data = (const u8 *)fw->data;
|
||||
+ u8 fw_status;
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ // Putting MCU in reset state
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x20);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Write firmware
|
||||
+ for (i = 0; i < fw->size / sizeof(u8); i++)
|
||||
+ ov5640_write_reg(sensor,
|
||||
+ OV5640_REG_FIRMWARE_BASE + i,
|
||||
+ data[i]);
|
||||
+
|
||||
+ // Reset MCU state
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_MAIN, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_ACK, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA0, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA1, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA2, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA3, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA4, 0x00);
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_FW_STATUS, 0x7f);
|
||||
+
|
||||
+ // Start AF MCU
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x00);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_info(&client->dev, "firmware upload success\n");
|
||||
+
|
||||
+ // Wait for firmware to be ready
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status);
|
||||
+ if (fw_status == OV5640_FW_STATUS_S_IDLE) {
|
||||
+ dev_info(&client->dev, "fw started after %d ms\n", i * 50);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+ dev_err(&client->dev, "uploaded firmware didn't start, got to 0x%x, retrying...\n", fw_status);
|
||||
+
|
||||
+ // Putting MCU in reset state
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x20);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ // Start AF MCU
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x00);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ // Wait for firmware to be ready
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status);
|
||||
+ if (fw_status == OV5640_FW_STATUS_S_IDLE) {
|
||||
+ dev_info(&client->dev, "fw started after %d ms\n", i * 50);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+ dev_err(&client->dev, "uploaded firmware didn't start, got to 0x%x\n", fw_status);
|
||||
+ return -ETIMEDOUT;
|
||||
+}
|
||||
+
|
||||
+static int ov5640_af_init(struct ov5640_dev *sensor)
|
||||
+{
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ const char* fwname = "ov5640_af.bin";
|
||||
+ const struct firmware *fw;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (sensor->af_initialized) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (firmware_request_nowarn(&fw, fwname, &client->dev) == 0) {
|
||||
+ ret = ov5640_copy_fw_to_device(sensor, fw);
|
||||
+ if (ret == 0)
|
||||
+ sensor->af_initialized = 1;
|
||||
+ } else {
|
||||
+ dev_warn(&client->dev, "%s: no autofocus firmware available (%s)\n",
|
||||
+ __func__, fwname);
|
||||
+ ret = -1;
|
||||
+ }
|
||||
+ release_firmware(fw);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Enable AF systems
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE00,
|
||||
+ (BIT(6) | BIT(5)), (BIT(6) | BIT(5)));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE01,
|
||||
+ BIT(6), BIT(6));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Set lens focus driver on
|
||||
+ ov5640_write_reg(sensor, OV5640_REG_VCM_CONTROL4, 0x3f);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int ov5640_set_power_on(struct ov5640_dev *sensor)
|
||||
{
|
||||
struct i2c_client *client = sensor->i2c_client;
|
||||
@@ -1988,6 +2117,8 @@ static int ov5640_set_power_on(struct ov5640_dev *sensor)
|
||||
goto xclk_off;
|
||||
}
|
||||
|
||||
+ sensor->af_initialized = 0;
|
||||
+
|
||||
ov5640_reset(sensor);
|
||||
ov5640_power(sensor, true);
|
||||
|
||||
@@ -2416,6 +2547,35 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
|
||||
is_jpeg ? (BIT(5) | BIT(3)) : 0);
|
||||
}
|
||||
|
||||
+static int ov5640_fw_command(struct ov5640_dev *sensor, int command)
|
||||
+{
|
||||
+ u8 fw_ack;
|
||||
+ int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_FW_CMD_ACK, 0x01);
|
||||
+ if(ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ov5640_write_reg(sensor, OV5640_REG_FW_CMD_MAIN, command);
|
||||
+ if(ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < 100; i++) {
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_CMD_ACK, &fw_ack);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (fw_ack == 0){
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ msleep(50);
|
||||
+ }
|
||||
+ return -ETIMEDOUT;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/*
|
||||
* Sensor Controls.
|
||||
*/
|
||||
@@ -2532,6 +2692,41 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int ov5640_set_ctrl_focus(struct ov5640_dev *sensor, int command)
|
||||
+{
|
||||
+ struct i2c_client *client = sensor->i2c_client;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ov5640_af_init(sensor);
|
||||
+ if (ret) {
|
||||
+ dev_err(&client->dev, "%s: no autofocus firmware loaded\n",
|
||||
+ __func__);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (command == OV5640_FW_CMD_RELEASE_FOCUS) {
|
||||
+ dev_dbg(&client->dev, "%s: Releasing autofocus\n",
|
||||
+ __func__);
|
||||
+ return ov5640_fw_command(sensor, OV5640_FW_CMD_RELEASE_FOCUS);
|
||||
+ }
|
||||
+
|
||||
+ // Restart zone config
|
||||
+ ret = ov5640_fw_command(sensor, OV5640_FW_CMD_ZONE_CONFIG);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ // Set default focus zones
|
||||
+ ret = ov5640_fw_command(sensor, OV5640_FW_CMD_DEFAULT_ZONES);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(&client->dev, "%s: Triggering autofocus\n",
|
||||
+ __func__);
|
||||
+
|
||||
+ // Start focussing
|
||||
+ return ov5640_fw_command(sensor, command);
|
||||
+}
|
||||
+
|
||||
static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
|
||||
{
|
||||
struct ov5640_ctrls *ctrls = &sensor->ctrls;
|
||||
@@ -2638,6 +2833,32 @@ static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
|
||||
(BIT(2) | BIT(1)) : 0);
|
||||
}
|
||||
|
||||
+static int ov5640_get_af_status(struct ov5640_dev *sensor)
|
||||
+{
|
||||
+ u8 fw_status;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ switch (fw_status) {
|
||||
+ case OV5640_FW_STATUS_S_FIRMWARE:
|
||||
+ case OV5640_FW_STATUS_S_STARTUP:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_FAILED;
|
||||
+ break;
|
||||
+ case OV5640_FW_STATUS_S_IDLE:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_IDLE;
|
||||
+ break;
|
||||
+ case OV5640_FW_STATUS_S_FOCUSED:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_REACHED;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return V4L2_AUTO_FOCUS_STATUS_BUSY;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
|
||||
@@ -2659,6 +2880,12 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
return val;
|
||||
sensor->ctrls.exposure->val = val;
|
||||
break;
|
||||
+ case V4L2_CID_FOCUS_AUTO:
|
||||
+ val = ov5640_get_af_status(sensor);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+ sensor->ctrls.af_status->val = val;
|
||||
+ break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2690,6 +2917,18 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_AUTO_WHITE_BALANCE:
|
||||
ret = ov5640_set_ctrl_white_balance(sensor, ctrl->val);
|
||||
break;
|
||||
+ case V4L2_CID_FOCUS_AUTO:
|
||||
+ if (ctrl->val)
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_CONTINUOUS_FOCUS);
|
||||
+ else
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_RELEASE_FOCUS);
|
||||
+ break;
|
||||
+ case V4L2_CID_AUTO_FOCUS_START:
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_TRIGGER_FOCUS);
|
||||
+ break;
|
||||
+ case V4L2_CID_AUTO_FOCUS_STOP:
|
||||
+ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_RELEASE_FOCUS);
|
||||
+ break;
|
||||
case V4L2_CID_HUE:
|
||||
ret = ov5640_set_ctrl_hue(sensor, ctrl->val);
|
||||
break;
|
||||
@@ -2762,6 +3001,20 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
|
||||
ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
|
||||
0, 1023, 1, 0);
|
||||
|
||||
+ /* Autofocus */
|
||||
+ ctrls->focus_auto = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_AUTO,
|
||||
+ 0, 1, 1, 0);
|
||||
+ ctrls->af_start = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_FOCUS_START,
|
||||
+ 0, 1, 1, 0);
|
||||
+ ctrls->af_stop = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_FOCUS_STOP,
|
||||
+ 0, 1, 1, 0);
|
||||
+ ctrls->af_status = v4l2_ctrl_new_std(hdl, ops,
|
||||
+ V4L2_CID_AUTO_FOCUS_STATUS, 0,
|
||||
+ (V4L2_AUTO_FOCUS_STATUS_BUSY |
|
||||
+ V4L2_AUTO_FOCUS_STATUS_REACHED |
|
||||
+ V4L2_AUTO_FOCUS_STATUS_FAILED),
|
||||
+ 0, V4L2_AUTO_FOCUS_STATUS_IDLE);
|
||||
+
|
||||
ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
|
||||
0, 255, 1, 64);
|
||||
ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
|
||||
@@ -2795,6 +3048,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
|
||||
v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
|
||||
v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
|
||||
v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
|
||||
+ v4l2_ctrl_cluster(4, &ctrls->focus_auto);
|
||||
|
||||
sensor->sd.ctrl_handler = hdl;
|
||||
return 0;
|
||||
--
|
||||
2.25.4
|
||||
|
@ -0,0 +1,11 @@
|
||||
--- linux-pine64-5.9-da1a1dee4471aa5da391517c4af40d2c80fe828d/drivers/media/i2c/ov5640.c 2020-10-18 00:13:18.000000000 +0200
|
||||
+++ linux-pine64-5.9-da1a1dee4471aa5da391517c4af40d2c80fe828d/drivers/media/i2c/ov5640.c 2020-10-18 22:19:32.490533074 +0200
|
||||
@@ -2677,7 +2677,7 @@ static int ov5640_set_ctrl_focus(struct
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "%s: no autofocus firmware loaded\n",
|
||||
__func__);
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
if (command == OV5640_FW_CMD_RELEASE_FOCUS) {
|
@ -0,0 +1,36 @@
|
||||
From 29533cb13f24e26e7ddbc044597a3020437352e2 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman
|
||||
Date: Thu, 29 Oct 2020 01:13:49 +0100
|
||||
Subject: drm/sun4i: Fix mipi-dsi panel framerate being 2/3 of the expected
|
||||
value
|
||||
|
||||
This happens on Pinephone and on Pinetab. Both use MIPI-DSI panels.
|
||||
|
||||
On Pinephone framerate is 36.6 instead of expected 55.
|
||||
On Pinetab the similar 2/3 ratio holds.
|
||||
|
||||
Myabe there's a bug in BSP and dclk_div should really be 6 instead of 4.
|
||||
|
||||
Signed-off-by: Ondrej Jirman <megous@megous.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
index ab06f5e1fc95..1c56b4fb9ac8 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
|
||||
@@ -398,8 +398,8 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
|
||||
u32 block_space, start_delay;
|
||||
u32 tcon_div;
|
||||
|
||||
- tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
|
||||
- tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
|
||||
+ tcon->dclk_min_div = 6;
|
||||
+ tcon->dclk_max_div = 6;
|
||||
|
||||
sun4i_tcon0_mode_set_common(tcon, mode);
|
||||
|
||||
--
|
||||
cgit v1.2.3
|
||||
|
@ -0,0 +1,37 @@
|
||||
From e8be2e4affb906af7137437ac62fb3912609c11e Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman
|
||||
Date: Thu, 29 Oct 2020 04:55:40 +0100
|
||||
Subject: drm: panel: st7703: Fix xbd599 timings to make refresh rate exactly
|
||||
60.006Hz
|
||||
|
||||
Signed-off-by: Ondrej Jirman <megous@megous.com>
|
||||
---
|
||||
drivers/gpu/drm/panel/panel-sitronix-st7703.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
||||
index 4287aabb9007..070ef2baef6f 100644
|
||||
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
||||
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
||||
@@ -334,14 +334,14 @@ static int xbd599_init_sequence(struct st7703 *ctx)
|
||||
|
||||
static const struct drm_display_mode xbd599_mode = {
|
||||
.hdisplay = 720,
|
||||
- .hsync_start = 720 + 40,
|
||||
- .hsync_end = 720 + 40 + 40,
|
||||
- .htotal = 720 + 40 + 40 + 40,
|
||||
+ .hsync_start = 720 + 30,
|
||||
+ .hsync_end = 720 + 30 + 28,
|
||||
+ .htotal = 720 + 30 + 28 + 30,
|
||||
.vdisplay = 1440,
|
||||
.vsync_start = 1440 + 18,
|
||||
.vsync_end = 1440 + 18 + 10,
|
||||
.vtotal = 1440 + 18 + 10 + 17,
|
||||
- .clock = 69000,
|
||||
+ .clock = 72000,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
.width_mm = 68,
|
||||
.height_mm = 136,
|
||||
--
|
||||
cgit v1.2.3
|
||||
|
@ -0,0 +1,66 @@
|
||||
From 8a0bf7456f10a06adeeed0690d181f67d887e18e Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman
|
||||
Date: Tue, 28 Jan 2020 00:26:17 +0100
|
||||
Subject: drm: sun4i-drm: Recover from occasional HW failures
|
||||
|
||||
Layer can be disabled automatically by HW (HW clears the bit in
|
||||
some unknown situations). We need to always update this bit,
|
||||
so that DE2 will not fail.
|
||||
|
||||
Signed-off-by: Ondrej Jirman <megous@megous.com>
|
||||
---
|
||||
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 13 ++++++-------
|
||||
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 13 ++++++-------
|
||||
2 files changed, 12 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
index f1c87695b4d7..e58482f6d7ba 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
|
||||
@@ -36,13 +36,12 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
|
||||
DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
|
||||
enable ? "En" : "Dis", channel, overlay);
|
||||
|
||||
- if (!was_enabled != !enable) {
|
||||
- val = enable ? SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN : 0;
|
||||
-
|
||||
- regmap_update_bits(mixer->engine.regs,
|
||||
- SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
|
||||
- SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
|
||||
- }
|
||||
+ /* We always update the layer enable bit, because it can clear
|
||||
+ * spontaneously for unknown reasons. */
|
||||
+ val = enable ? SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN : 0;
|
||||
+ regmap_update_bits(mixer->engine.regs,
|
||||
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
|
||||
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
|
||||
|
||||
/*
|
||||
* If this layer was enabled and is being disabled or if it is
|
||||
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
index 81eda71c4fff..0c2ccc33d456 100644
|
||||
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
|
||||
@@ -30,13 +30,12 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
|
||||
DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
|
||||
enable ? "En" : "Dis", channel, overlay);
|
||||
|
||||
- if (!was_enabled != !enable) {
|
||||
- val = enable ? SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN : 0;
|
||||
-
|
||||
- regmap_update_bits(mixer->engine.regs,
|
||||
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
|
||||
- SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
|
||||
- }
|
||||
+ /* We always update the layer enable bit, because it can clear
|
||||
+ * spontaneously for unknown reasons. */
|
||||
+ val = enable ? SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN : 0;
|
||||
+ regmap_update_bits(mixer->engine.regs,
|
||||
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
|
||||
+ SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
|
||||
|
||||
/*
|
||||
* If this layer was enabled and is being disabled or if it is
|
||||
--
|
||||
cgit v1.2.3
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 2af59597979e0192cb4675c12e57ed2a857fe9ce Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Jirman
|
||||
Date: Wed, 7 Oct 2020 02:11:35 +0200
|
||||
Subject: clk: sunxi-ng: sun50i-a64: Switch parent of MIPI-DSI to periph0(1x)
|
||||
|
||||
This makes video0(1x) clock less constrained, and improves compatibility
|
||||
with external monitors on Pinephone when using both internal display
|
||||
and HDMI output at once.
|
||||
|
||||
Signed-off-by: Ondrej Jirman <megous@megous.com>
|
||||
Modified by: Philip Müller <philm@manjaro.org>
|
||||
---
|
||||
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
|
||||
index 8ac40a78e75e..e41eadc602e7 100644
|
||||
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
|
||||
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
|
||||
@@ -969,6 +969,8 @@ static struct ccu_rate_reset_nb sun50i_a
|
||||
.common = &pll_video0_clk.common,
|
||||
};
|
||||
|
||||
+#define CCU_MIPI_DSI_CLK 0x168
|
||||
+
|
||||
static int sun50i_a64_ccu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
@@ -990,6 +992,12 @@ static int sun50i_a64_ccu_probe(struct p
|
||||
writel(0x10040000, reg + SUN50I_A64_PLL_AUDIO_BIAS_REG);
|
||||
|
||||
writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
|
||||
+
|
||||
+ /* Set MIPI-DSI clock parent to periph0(1x), so that video0(1x) is free to change. */
|
||||
+ val = readl(reg + CCU_MIPI_DSI_CLK);
|
||||
+ val &= 0x30f;
|
||||
+ val |= (2 << 8) | ((4 - 1) << 0); /* M-1 */
|
||||
+ writel(val, reg + CCU_MIPI_DSI_CLK);
|
||||
|
||||
/* Force the parent of TCON0 to PLL-MIPI */
|
||||
val = readl(reg + SUN50I_A64_TCON0_REG);
|
||||
--
|
||||
cgit v1.2.3
|
||||
|
12
sys-kernel/pinephone-sources/files/panic-led.patch
Normal file
12
sys-kernel/pinephone-sources/files/panic-led.patch
Normal file
@ -0,0 +1,12 @@
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 1c555456b..05fab5d79 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -78,6 +78,7 @@ green {
|
||||
};
|
||||
|
||||
red {
|
||||
+ linux,default-trigger = "panic";
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
|
@ -0,0 +1,21 @@
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
index a72c2ec8c..b3a7bef13 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
@@ -227,7 +227,15 @@ &i2c0_pins {
|
||||
&i2c1 {
|
||||
status = "okay";
|
||||
|
||||
- /* TODO: add Bochs BMA223 accelerometer here */
|
||||
+ bma223@18 {
|
||||
+ compatible = "bosch,bma223", "bosch,bma222e";
|
||||
+ reg = <0x18>;
|
||||
+ interrupt-parent = <&pio>;
|
||||
+ interrupts = <7 5 IRQ_TYPE_LEVEL_HIGH>; /* PH5 */
|
||||
+ mount-matrix = "0", "-1", "0",
|
||||
+ "-1", "0", "0",
|
||||
+ "0", "0", "-1";
|
||||
+ };
|
||||
};
|
||||
|
||||
&lradc {
|
44
sys-kernel/pinephone-sources/files/pinetab-bluetooth.patch
Normal file
44
sys-kernel/pinephone-sources/files/pinetab-bluetooth.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 330d05da1b6e8118c9c4655f0b234cf32a2f1ce4 Mon Sep 17 00:00:00 2001
|
||||
From: Icenowy Zheng <icenowy@aosc.io>
|
||||
Date: Sun, 14 Apr 2019 23:46:47 +0800
|
||||
Subject: [PATCH] arm64: allwinner: a64: pinetab: enable RTL8723CS bluetooth
|
||||
|
||||
PineTab has a RTL8723CS Wi-Fi/BT combo chip on board, the bluetooth part
|
||||
of it communicates with A64 via UART, and the power of it is controlled
|
||||
with some GPIO at PL bank.
|
||||
|
||||
Enable the bluetooth in the device tree.
|
||||
|
||||
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
|
||||
---
|
||||
.../boot/dts/allwinner/sun50i-a64-pinetab.dts | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
index 84d6e8cb2b88..e8b823875740 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
|
||||
@@ -447,6 +447,20 @@ &uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&uart1 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ bluetooth {
|
||||
+ compatible = "realtek,rtl8723cs-bt";
|
||||
+ reset-gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */
|
||||
+ device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */
|
||||
+ host-wake-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
|
||||
+ firmware-postfix = "pinebook";
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&usb_otg {
|
||||
dr_mode = "otg";
|
||||
status = "okay";
|
||||
--
|
||||
GitLab
|
||||
|
@ -0,0 +1,26 @@
|
||||
From 5a3d7fd96843710d468603412a3270e7eefe997a Mon Sep 17 00:00:00 2001
|
||||
From: Danct12 <danct12@disroot.org>
|
||||
Date: Wed, 14 Oct 2020 01:18:40 +0700
|
||||
Subject: [PATCH] arm64: dts: pinephone: remove flash node for ov5640
|
||||
|
||||
Signed-off-by: Danct12 <danct12@disroot.org>
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 3781eb8ea..6bc0e9d6d 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -439,8 +439,6 @@ ov5640: rear-camera@4c {
|
||||
reset-gpios = <&pio 3 3 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; /* PD3 */
|
||||
powerdown-gpios = <&pio 2 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; /* PC0 */
|
||||
|
||||
- flash-leds = <&sgm3140_flash>;
|
||||
-
|
||||
port {
|
||||
ov5640_ep: endpoint {
|
||||
remote-endpoint = <&csi_ov5640_ep>;
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,35 @@
|
||||
From 3ed430f6b94479c7b4d26323b5fe6381ca11c0e4 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Lindgren <tony@atomide.com>
|
||||
Date: Tue, 27 Oct 2020 13:18:57 +0530
|
||||
Subject: [PATCH] usb: musb: avoid the hang in musb_pm_runtime_check_session
|
||||
|
||||
See thread at: https://lore.kernel.org/linux-usb/20201027045519.GA947883@aquila.localdomain/
|
||||
---
|
||||
drivers/usb/musb/musb_core.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
|
||||
index 384a8039a7fd5..fe87046d8b28a 100644
|
||||
--- a/drivers/usb/musb/musb_core.c
|
||||
+++ b/drivers/usb/musb/musb_core.c
|
||||
@@ -2005,10 +2005,13 @@ static void musb_pm_runtime_check_session(struct musb *musb)
|
||||
MUSB_DEVCTL_HR;
|
||||
switch (devctl & ~s) {
|
||||
case MUSB_QUIRK_B_DISCONNECT_99:
|
||||
- musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n");
|
||||
- schedule_delayed_work(&musb->irq_work,
|
||||
- msecs_to_jiffies(1000));
|
||||
- break;
|
||||
+ if (musb->quirk_retries && !musb->flush_irq_work) {
|
||||
+ musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n");
|
||||
+ schedule_delayed_work(&musb->irq_work,
|
||||
+ msecs_to_jiffies(1000));
|
||||
+ musb->quirk_retries--;
|
||||
+ break;
|
||||
+ }
|
||||
case MUSB_QUIRK_B_INVALID_VBUS_91:
|
||||
if (musb->quirk_retries && !musb->flush_irq_work) {
|
||||
musb_dbg(musb,
|
||||
--
|
||||
2.29.1
|
||||
|
34
sys-kernel/pinephone-sources/files/wifi-power-saving.patch
Normal file
34
sys-kernel/pinephone-sources/files/wifi-power-saving.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 62b516401f008d166b93ad2ea6f3012989b0cccb Mon Sep 17 00:00:00 2001
|
||||
From: Dalton <dalton@ubports.com>
|
||||
Date: Tue, 23 Jun 2020 20:54:12 -0500
|
||||
Subject: [PATCH] UBPORTS SAUCE: Disable 8723cs power saving
|
||||
|
||||
The runtime power management features in the 8723cs firmware on the
|
||||
PinePhone don't seem to work correctly. While we expect the chipset to
|
||||
leave a low power state when it's time to send or receive data, instead
|
||||
we get a delay of 10-20 seconds before any packets are sent.
|
||||
---
|
||||
drivers/staging/rtl8723cs-new/os_dep/linux/os_intfs.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/rtl8723cs-new/os_dep/linux/os_intfs.c b/drivers/staging/rtl8723cs-new/os_dep/linux/os_intfs.c
|
||||
index 3e6ba0a0fd17..5bb850a4caf0 100644
|
||||
--- a/drivers/staging/rtl8723cs-new/os_dep/linux/os_intfs.c
|
||||
+++ b/drivers/staging/rtl8723cs-new/os_dep/linux/os_intfs.c
|
||||
@@ -54,7 +54,12 @@ int rtw_adhoc_tx_pwr = 1;
|
||||
int rtw_soft_ap = 0;
|
||||
/* int smart_ps = 1; */
|
||||
#ifdef CONFIG_POWER_SAVING
|
||||
- int rtw_power_mgnt = PS_MODE_MAX;
|
||||
+ // Setting PS_MODE_ACTIVE by default keeps the power saving code in the
|
||||
+ // driver but works around an issue where the 8723cs won't leave Leisure
|
||||
+ // Power Saving mode without long delays. Allows for testing different
|
||||
+ // firmwares.
|
||||
+ // int rtw_power_mgnt = PS_MODE_MAX;
|
||||
+ int rtw_power_mgnt = PS_MODE_ACTIVE;
|
||||
#ifdef CONFIG_IPS_LEVEL_2
|
||||
int rtw_ips_mode = IPS_LEVEL_2;
|
||||
#else
|
||||
--
|
||||
GitLab
|
||||
|
@ -0,0 +1,74 @@
|
||||
# Copyright 1999-2020 Gentoo Authors
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
EAPI="6"
|
||||
K_NOUSENAME="yes"
|
||||
K_NOSETEXTRAVERSION="yes"
|
||||
K_SECURITY_UNSUPPORTED="1"
|
||||
ETYPE="sources"
|
||||
inherit kernel-2
|
||||
detect_version
|
||||
|
||||
DESCRIPTION="Full sources for the Linux kernel, with megi's patch for pinephone"
|
||||
HOMEPAGE="https://www.kernel.org"
|
||||
|
||||
KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
|
||||
MEGI_PATCH_URI="https://xff.cz/kernels/${PV:0:4}/patches/all.patch"
|
||||
SRC_URI="${KERNEL_URI} ${MEGI_PATCH_URI} -> all-${PV}.patch"
|
||||
|
||||
PATCHES=(
|
||||
${DISTDIR}/all-${PV}.patch
|
||||
${FILESDIR}/enable-hdmi-output-pinetab.patch
|
||||
#${FILESDIR}/improve-brightness.patch
|
||||
${FILESDIR}/enable-jack-detection-pinetab.patch
|
||||
${FILESDIR}/pinetab-bluetooth.patch
|
||||
${FILESDIR}/pinetab-accelerometer.patch
|
||||
${FILESDIR}/dts-pinephone-drop-modem-power-node.patch
|
||||
${FILESDIR}/dts-headphone-jack-detection.patch
|
||||
${FILESDIR}/media-ov5640-Implement-autofocus.patch
|
||||
${FILESDIR}/0011-dts-pinetab-hardcode-mmc-numbers.patch
|
||||
${FILESDIR}/0002-dts-add-pinetab-dev-old-display-panel.patch
|
||||
#${FILESDIR}/0001-arm64-dts-allwinner-pinephone-stop-LEDs-on-suspend.patch
|
||||
${FILESDIR}/0010-dts-pinephone-Add-pine64-pinephone-to-compat-list.patch
|
||||
${FILESDIR}/0012-pinephone-fix-pogopin-i2c.patch
|
||||
${FILESDIR}/0107-quirk-kernel-org-bug-210681-firmware_rome_error.patch
|
||||
${FILESDIR}/0177-leds-gpio-make-max_brightness-configurable.patch
|
||||
${FILESDIR}/0178-sun8i-codec-fix-headphone-jack-pin-name.patch
|
||||
${FILESDIR}/0179-arm64-dts-allwinner-pinephone-improve-device-tree.patch
|
||||
${FILESDIR}/panic-led.patch
|
||||
${FILESDIR}/PATCH-1-4-HID-magicmouse-add-Apple-Magic-Mouse-2-support.patch
|
||||
${FILESDIR}/PATCH-2-4-HID-magicmouse-fix-3-button-emulation-of-Mouse-2.patch
|
||||
${FILESDIR}/PATCH-3-4-HID-magicmouse-fix-reconnection-of-Magic-Mouse-2.patch
|
||||
${FILESDIR}/PATCH-4-4-HID-input-map-battery-capacity-00850065.patch
|
||||
#${FILESDIR}/camera-added-bggr-bayer-mode.patch
|
||||
#${FILESDIR}/0002-Bluetooth-Fix-LL-PRivacy-BLE-device-fails-to-connect.patch
|
||||
#${FILESDIR}/0003-Bluetooth-Fix-attempting-to-set-RPA-timeout-when-unsupported.patch
|
||||
#${FILESDIR}/0001-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch
|
||||
#${FILESDIR}/0002-revert-fbcon-remove-no-op-fbcon_set_origin.patch
|
||||
#${FILESDIR}/0003-revert-fbcon-remove-soft-scrollback-code.patch
|
||||
)
|
||||
|
||||
src_prepare() {
|
||||
default
|
||||
eapply_user
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
kernel-2_pkg_postinst
|
||||
einfo "For more info on this patchset, and how to report problems, see:"
|
||||
einfo "${HOMEPAGE}"
|
||||
einfo "To build the kernel use the following command:"
|
||||
einfo "make Image Image.gz modules"
|
||||
einfo "make DTC_FLAGS="-@" dtbs"
|
||||
einfo "make install; make modules_intall; make dtbs_install"
|
||||
einfo "If you use kernel config coming with this ebuild, don't forget to also copy dracut-pp.conf to /etc/dracut.conf.d/"
|
||||
einfo "to make sure proper kernel modules are loaded into initramfs"
|
||||
einfo "if you want to cross compile pinephone kernel on amd64 host, follow the https://wiki.gentoo.org/wiki/Cross_build_environment"
|
||||
einfo "to setup cross toolchain environment, then create a xmake wrapper like the following, and replace make with xmake in above commands"
|
||||
einfo "#!/bin/sh"
|
||||
einfo "exec make ARCH='arm64' CROSS_COMPILE='aarch64-unknown-linux-gnu-' INSTALL_MOD_PATH='${SYSROOT}' '$@'"
|
||||
}
|
||||
|
||||
pkg_postrm() {
|
||||
kernel-2_pkg_postrm
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user