This commit is contained in:
Gerben Jan Dijkman 2021-04-19 15:42:22 +02:00
parent aa5fe36bf4
commit 09ee2d1817
66 changed files with 8 additions and 557659 deletions

View File

@ -1,746 +0,0 @@
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

View File

@ -1,150 +0,0 @@
--- 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);

View File

@ -1,67 +0,0 @@
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, &params->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, &params->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

View File

@ -1,669 +0,0 @@
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

View File

@ -1,31 +0,0 @@
--- 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,

View File

@ -1,497 +0,0 @@
--- 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;

View File

@ -1,48 +0,0 @@
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

View File

@ -1,40 +0,0 @@
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;
}

View File

@ -1,66 +0,0 @@
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);
+ }
+}

View File

@ -1,497 +0,0 @@
--- 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;

View File

@ -1,215 +0,0 @@
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

View File

@ -1,58 +0,0 @@
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

View File

@ -1,327 +0,0 @@
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

View File

@ -1,82 +0,0 @@
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()

View File

@ -1,42 +0,0 @@
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

View File

@ -1,21 +0,0 @@
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,

View File

@ -1,21 +0,0 @@
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)

View File

@ -1,321 +0,0 @@
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

View File

@ -1,129 +0,0 @@
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
};

View File

@ -1,511 +0,0 @@
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;
+}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
[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%

View File

@ -1,11 +0,0 @@
[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%

View File

@ -1,118 +0,0 @@
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

View File

@ -1,247 +0,0 @@
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

View File

@ -1,134 +0,0 @@
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

View File

@ -1,265 +0,0 @@
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

View File

@ -1,155 +0,0 @@
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;
+ device->battery_min = 0;
+ device->battery_max = 100;
+ 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

View File

@ -1,330 +0,0 @@
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

View File

@ -1,129 +0,0 @@
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

View File

@ -1,113 +0,0 @@
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

View File

@ -1,118 +0,0 @@
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

View File

@ -1,140 +0,0 @@
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

View File

@ -1,178 +0,0 @@
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

View File

@ -1,202 +0,0 @@
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

View File

@ -1,144 +0,0 @@
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

View File

@ -1,311 +0,0 @@
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

View File

@ -1,749 +0,0 @@
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

View File

@ -1,612 +0,0 @@
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

View File

@ -1,492 +0,0 @@
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

View File

@ -1,137 +0,0 @@
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

View File

@ -1,329 +0,0 @@
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

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
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

View File

@ -1,390 +0,0 @@
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
# 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 "

View File

@ -1,280 +0,0 @@
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 */
};
/**

View File

@ -1,67 +0,0 @@
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

View File

@ -1,9 +0,0 @@
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
}

View File

@ -1,11 +0,0 @@
--- 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) {

View File

@ -1,36 +0,0 @@
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

View File

@ -1,37 +0,0 @@
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

View File

@ -1,66 +0,0 @@
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

View File

@ -1,44 +0,0 @@
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

View File

@ -1,26 +0,0 @@
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

View File

@ -1,35 +0,0 @@
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

View File

@ -1,34 +0,0 @@
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

View File

@ -17,18 +17,23 @@ 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
${DISTDIR}/all-${PV}.patch
${FILESDIR}/panic-led.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}/camera-autofocus.patch
${FILESDIR}/media-ov5640-dont-break-when-firmware-for-autofocus-isnt-loaded.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
)
src_prepare() {