Index: npl/kernel/linux_src/4200_fbcondecor.patch
===================================================================
--- npl/kernel/linux_src/4200_fbcondecor.patch	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ 	(revision )
@@ -1,2095 +1,0 @@
-diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX
-index fe85e7c5907a..22309308ba56 100644
---- a/Documentation/fb/00-INDEX
-+++ b/Documentation/fb/00-INDEX
-@@ -23,6 +23,8 @@ ep93xx-fb.txt
- 	- info on the driver for EP93xx LCD controller.
- fbcon.txt
- 	- intro to and usage guide for the framebuffer console (fbcon).
-+fbcondecor.txt
-+	- info on the Framebuffer Console Decoration
- framebuffer.txt
- 	- introduction to frame buffer devices.
- gxfb.txt
-diff --git a/Documentation/fb/fbcondecor.txt b/Documentation/fb/fbcondecor.txt
-new file mode 100644
-index 000000000000..637209e11ccd
---- /dev/null
-+++ b/Documentation/fb/fbcondecor.txt
-@@ -0,0 +1,207 @@
-+What is it?
-+-----------
-+
-+The framebuffer decorations are a kernel feature which allows displaying a
-+background picture on selected consoles.
-+
-+What do I need to get it to work?
-+---------------------------------
-+
-+To get fbcondecor up-and-running you will have to:
-+ 1) get a copy of splashutils [1] or a similar program
-+ 2) get some fbcondecor themes
-+ 3) build the kernel helper program
-+ 4) build your kernel with the FB_CON_DECOR option enabled.
-+
-+To get fbcondecor operational right after fbcon initialization is finished, you
-+will have to include a theme and the kernel helper into your initramfs image.
-+Please refer to splashutils documentation for instructions on how to do that.
-+
-+[1] The splashutils package can be downloaded from:
-+    http://github.com/alanhaggai/fbsplash
-+
-+The userspace helper
-+--------------------
-+
-+The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the
-+kernel whenever an important event occurs and the kernel needs some kind of
-+job to be carried out. Important events include console switches and video
-+mode switches (the kernel requests background images and configuration
-+parameters for the current console). The fbcondecor helper must be accessible at
-+all times. If it's not, fbcondecor will be switched off automatically.
-+
-+It's possible to set path to the fbcondecor helper by writing it to
-+/proc/sys/kernel/fbcondecor.
-+
-+*****************************************************************************
-+
-+The information below is mostly technical stuff. There's probably no need to
-+read it unless you plan to develop a userspace helper.
-+
-+The fbcondecor protocol
-+-----------------------
-+
-+The fbcondecor protocol defines a communication interface between the kernel and
-+the userspace fbcondecor helper.
-+
-+The kernel side is responsible for:
-+
-+ * rendering console text, using an image as a background (instead of a
-+   standard solid color fbcon uses),
-+ * accepting commands from the user via ioctls on the fbcondecor device,
-+ * calling the userspace helper to set things up as soon as the fb subsystem
-+   is initialized.
-+
-+The userspace helper is responsible for everything else, including parsing
-+configuration files, decompressing the image files whenever the kernel needs
-+it, and communicating with the kernel if necessary.
-+
-+The fbcondecor protocol specifies how communication is done in both ways:
-+kernel->userspace and userspace->helper.
-+
-+Kernel -> Userspace
-+-------------------
-+
-+The kernel communicates with the userspace helper by calling it and specifying
-+the task to be done in a series of arguments.
-+
-+The arguments follow the pattern:
-+<fbcondecor protocol version> <command> <parameters>
-+
-+All commands defined in fbcondecor protocol v2 have the following parameters:
-+ virtual console
-+ framebuffer number
-+ theme
-+
-+Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the
-+framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used.
-+
-+Fbcondecor protocol v2 specifies the following commands:
-+
-+getpic
-+------
-+ The kernel issues this command to request image data. It's up to the
-+ userspace  helper to find a background image appropriate for the specified
-+ theme and the current resolution. The userspace helper should respond by
-+ issuing the FBIOCONDECOR_SETPIC ioctl.
-+
-+init
-+----
-+ The kernel issues this command after the fbcondecor device is created and
-+ the fbcondecor interface is initialized. Upon receiving 'init', the userspace
-+ helper should parse the kernel command line (/proc/cmdline) or otherwise
-+ decide whether fbcondecor is to be activated.
-+
-+ To activate fbcondecor on the first console the helper should issue the
-+ FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands,
-+ in the above-mentioned order.
-+
-+ When the userspace helper is called in an early phase of the boot process
-+ (right after the initialization of fbcon), no filesystems will be mounted.
-+ The helper program should mount sysfs and then create the appropriate
-+ framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get
-+ current display settings and to be able to communicate with the kernel side.
-+ It should probably also mount the procfs to be able to parse the kernel
-+ command line parameters.
-+
-+ Note that the console sem is not held when the kernel calls fbcondecor_helper
-+ with the 'init' command. The fbcondecor helper should perform all ioctls with
-+ origin set to FBCON_DECOR_IO_ORIG_USER.
-+
-+modechange
-+----------
-+ The kernel issues this command on a mode change. The helper's response should
-+ be similar to the response to the 'init' command. Note that this time the
-+ console sem is held and all ioctls must be performed with origin set to
-+ FBCON_DECOR_IO_ORIG_KERNEL.
-+
-+
-+Userspace -> Kernel
-+-------------------
-+
-+Userspace programs can communicate with fbcondecor via ioctls on the
-+fbcondecor device. These ioctls are to be used by both the userspace helper
-+(called only by the kernel) and userspace configuration tools (run by the users).
-+
-+The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL
-+when doing the appropriate ioctls. All userspace configuration tools should
-+use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin
-+field when performing ioctls from the kernel helper will most likely result
-+in a console deadlock.
-+
-+FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console
-+semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire
-+the console sem.
-+
-+The framebuffer console decoration provides the following ioctls (all defined in
-+linux/fb.h):
-+
-+FBIOCONDECOR_SETPIC
-+description: loads a background picture for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: struct fb_image*
-+notes:
-+If called for consoles other than the current foreground one, the picture data
-+will be ignored.
-+
-+If the current virtual console is running in a 8-bpp mode, the cmap substruct
-+of fb_image has to be filled appropriately: start should be set to 16 (first
-+16 colors are reserved for fbcon), len to a value <= 240 and red, green and
-+blue should point to valid cmap data. The transp field is ingored. The fields
-+dx, dy, bg_color, fg_color in fb_image are ignored as well.
-+
-+FBIOCONDECOR_SETCFG
-+description: sets the fbcondecor config for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
-+notes: The structure has to be filled with valid data.
-+
-+FBIOCONDECOR_GETCFG
-+description: gets the fbcondecor config for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
-+
-+FBIOCONDECOR_SETSTATE
-+description: sets the fbcondecor state for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: unsigned int*
-+          values: 0 = disabled, 1 = enabled.
-+
-+FBIOCONDECOR_GETSTATE
-+description: gets the fbcondecor state for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: unsigned int*
-+          values: as in FBIOCONDECOR_SETSTATE
-+
-+Info on used structures:
-+
-+Definition of struct vc_decor can be found in linux/console_decor.h. It's
-+heavily commented. Note that the 'theme' field should point to a string
-+no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is
-+performed, the theme field should point to a char buffer of length
-+FBCON_DECOR_THEME_LEN.
-+
-+Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h.
-+The fields in this struct have the following meaning:
-+
-+vc:
-+Virtual console number.
-+
-+origin:
-+Specifies if the ioctl is performed as a response to a kernel request. The
-+fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace
-+programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to
-+avoid console semaphore deadlocks.
-+
-+data:
-+Pointer to a data structure appropriate for the performed ioctl. Type of
-+the data struct is specified in the ioctls description.
-+
-+*****************************************************************************
-+
-+Credit
-+------
-+
-+Original 'bootsplash' project & implementation by:
-+  Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>,
-+  Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>,
-+  Ken Wimer <wimer@suse.de>.
-+
-+Fbcondecor, fbcondecor protocol design, current implementation & docs by:
-+  Michal Januszewski <michalj+fbcondecor@gmail.com>
-+
-diff --git a/drivers/Makefile b/drivers/Makefile
-index 1d034b680431..9f41f2ea0c8b 100644
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -23,6 +23,10 @@ obj-y				+= pci/dwc/
- 
- obj-$(CONFIG_PARISC)		+= parisc/
- obj-$(CONFIG_RAPIDIO)		+= rapidio/
-+# tty/ comes before char/ so that the VT console is the boot-time
-+# default.
-+obj-y				+= tty/
-+obj-y				+= char/
- obj-y				+= video/
- obj-y				+= idle/
- 
-@@ -53,11 +57,6 @@ obj-$(CONFIG_REGULATOR)		+= regulator/
- # reset controllers early, since gpu drivers might rely on them to initialize
- obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
- 
--# tty/ comes before char/ so that the VT console is the boot-time
--# default.
--obj-y				+= tty/
--obj-y				+= char/
--
- # iommu/ comes before gpu as gpu are using iommu controllers
- obj-$(CONFIG_IOMMU_SUPPORT)	+= iommu/
- 
-diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
-index 7f1f1fbcef9e..8439b618dfc0 100644
---- a/drivers/video/console/Kconfig
-+++ b/drivers/video/console/Kconfig
-@@ -151,6 +151,19 @@ config FRAMEBUFFER_CONSOLE_ROTATION
-          such that other users of the framebuffer will remain normally
-          oriented.
- 
-+config FB_CON_DECOR
-+	bool "Support for the Framebuffer Console Decorations"
-+	depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING
-+	default n
-+	---help---
-+	  This option enables support for framebuffer console decorations which
-+	  makes it possible to display images in the background of the system
-+	  consoles.  Note that userspace utilities are necessary in order to take
-+	  advantage of these features. Refer to Documentation/fb/fbcondecor.txt
-+	  for more information.
-+
-+	  If unsure, say N.
-+
- config STI_CONSOLE
-         bool "STI text console"
-         depends on PARISC
-diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
-index db07b784bd2c..3e369bd120b8 100644
---- a/drivers/video/console/Makefile
-+++ b/drivers/video/console/Makefile
-@@ -9,4 +9,5 @@ obj-$(CONFIG_STI_CONSOLE)         += sticon.o sticore.o
- obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
- obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
- 
-+obj-$(CONFIG_FB_CON_DECOR)     	  += fbcondecor.o cfbcondecor.o
- obj-$(CONFIG_FB_STI)              += sticore.o
-diff --git a/drivers/video/console/cfbcondecor.c b/drivers/video/console/cfbcondecor.c
-new file mode 100644
-index 000000000000..b00960803edc
---- /dev/null
-+++ b/drivers/video/console/cfbcondecor.c
-@@ -0,0 +1,473 @@
-+/*
-+ *  linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions
-+ *
-+ *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
-+ *
-+ *  Code based upon "Bootdecor" (C) 2001-2003
-+ *       Volker Poplawski <volker@poplawski.de>,
-+ *       Stefan Reinauer <stepan@suse.de>,
-+ *       Steffen Winterfeldt <snwint@suse.de>,
-+ *       Michael Schroeder <mls@suse.de>,
-+ *       Ken Wimer <wimer@suse.de>.
-+ *
-+ *  This file is subject to the terms and conditions of the GNU General Public
-+ *  License.  See the file COPYING in the main directory of this archive for
-+ *  more details.
-+ */
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/fb.h>
-+#include <linux/selection.h>
-+#include <linux/slab.h>
-+#include <linux/vt_kern.h>
-+#include <asm/irq.h>
-+
-+#include "../fbdev/core/fbcon.h"
-+#include "fbcondecor.h"
-+
-+#define parse_pixel(shift, bpp, type)						\
-+	do {									\
-+		if (d & (0x80 >> (shift)))					\
-+			dd2[(shift)] = fgx;					\
-+		else								\
-+			dd2[(shift)] = transparent ? *(type *)decor_src : bgx;	\
-+		decor_src += (bpp);						\
-+	} while (0)								\
-+
-+extern int get_color(struct vc_data *vc, struct fb_info *info,
-+		     u16 c, int is_fg);
-+
-+void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
-+{
-+	int i, j, k;
-+	int minlen = min(min(info->var.red.length, info->var.green.length),
-+			     info->var.blue.length);
-+	u32 col;
-+
-+	for (j = i = 0; i < 16; i++) {
-+		k = color_table[i];
-+
-+		col = ((vc->vc_palette[j++]  >> (8-minlen))
-+			<< info->var.red.offset);
-+		col |= ((vc->vc_palette[j++] >> (8-minlen))
-+			<< info->var.green.offset);
-+		col |= ((vc->vc_palette[j++] >> (8-minlen))
-+			<< info->var.blue.offset);
-+			((u32 *)info->pseudo_palette)[k] = col;
-+	}
-+}
-+
-+void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height,
-+		      int width, u8 *src, u32 fgx, u32 bgx, u8 transparent)
-+{
-+	unsigned int x, y;
-+	u32 dd;
-+	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
-+	unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
-+	unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
-+	u16 dd2[4];
-+
-+	u8 *decor_src = (u8 *)(info->bgdecor.data + ds);
-+	u8 *dst = (u8 *)(info->screen_base + d);
-+
-+	if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
-+		return;
-+
-+	for (y = 0; y < height; y++) {
-+		switch (info->var.bits_per_pixel) {
-+
-+		case 32:
-+			for (x = 0; x < width; x++) {
-+
-+				if ((x & 7) == 0)
-+					d = *src++;
-+				if (d & 0x80)
-+					dd = fgx;
-+				else
-+					dd = transparent ?
-+					     *(u32 *)decor_src : bgx;
-+
-+				d <<= 1;
-+				decor_src += 4;
-+				fb_writel(dd, dst);
-+				dst += 4;
-+			}
-+			break;
-+		case 24:
-+			for (x = 0; x < width; x++) {
-+
-+				if ((x & 7) == 0)
-+					d = *src++;
-+				if (d & 0x80)
-+					dd = fgx;
-+				else
-+					dd = transparent ?
-+					     (*(u32 *)decor_src & 0xffffff) : bgx;
-+
-+				d <<= 1;
-+				decor_src += 3;
-+#ifdef __LITTLE_ENDIAN
-+				fb_writew(dd & 0xffff, dst);
-+				dst += 2;
-+				fb_writeb((dd >> 16), dst);
-+#else
-+				fb_writew(dd >> 8, dst);
-+				dst += 2;
-+				fb_writeb(dd & 0xff, dst);
-+#endif
-+				dst++;
-+			}
-+			break;
-+		case 16:
-+			for (x = 0; x < width; x += 2) {
-+				if ((x & 7) == 0)
-+					d = *src++;
-+
-+				parse_pixel(0, 2, u16);
-+				parse_pixel(1, 2, u16);
-+#ifdef __LITTLE_ENDIAN
-+				dd = dd2[0] | (dd2[1] << 16);
-+#else
-+				dd = dd2[1] | (dd2[0] << 16);
-+#endif
-+				d <<= 2;
-+				fb_writel(dd, dst);
-+				dst += 4;
-+			}
-+			break;
-+
-+		case 8:
-+			for (x = 0; x < width; x += 4) {
-+				if ((x & 7) == 0)
-+					d = *src++;
-+
-+				parse_pixel(0, 1, u8);
-+				parse_pixel(1, 1, u8);
-+				parse_pixel(2, 1, u8);
-+				parse_pixel(3, 1, u8);
-+
-+#ifdef __LITTLE_ENDIAN
-+				dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
-+#else
-+				dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
-+#endif
-+				d <<= 4;
-+				fb_writel(dd, dst);
-+				dst += 4;
-+			}
-+		}
-+
-+		dst += info->fix.line_length - width * bytespp;
-+		decor_src += (info->var.xres - width) * bytespp;
-+	}
-+}
-+
-+#define cc2cx(a)						\
-+	((info->fix.visual == FB_VISUAL_TRUECOLOR ||		\
-+		info->fix.visual == FB_VISUAL_DIRECTCOLOR) ?	\
-+			((u32 *)info->pseudo_palette)[a] : a)
-+
-+void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info,
-+		   const unsigned short *s, int count, int yy, int xx)
-+{
-+	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-+	struct fbcon_ops *ops = info->fbcon_par;
-+	int fg_color, bg_color, transparent;
-+	u8 *src;
-+	u32 bgx, fgx;
-+	u16 c = scr_readw(s);
-+
-+	fg_color = get_color(vc, info, c, 1);
-+	bg_color = get_color(vc, info, c, 0);
-+
-+	/* Don't paint the background image if console is blanked */
-+	transparent = ops->blank_state ? 0 :
-+		(vc->vc_decor.bg_color == bg_color);
-+
-+	xx = xx * vc->vc_font.width + vc->vc_decor.tx;
-+	yy = yy * vc->vc_font.height + vc->vc_decor.ty;
-+
-+	fgx = cc2cx(fg_color);
-+	bgx = cc2cx(bg_color);
-+
-+	while (count--) {
-+		c = scr_readw(s++);
-+		src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
-+		      ((vc->vc_font.width + 7) >> 3);
-+
-+		fbcon_decor_renderc(info, yy, xx, vc->vc_font.height,
-+			       vc->vc_font.width, src, fgx, bgx, transparent);
-+		xx += vc->vc_font.width;
-+	}
-+}
-+
-+void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor)
-+{
-+	int i;
-+	unsigned int dsize, s_pitch;
-+	struct fbcon_ops *ops = info->fbcon_par;
-+	struct vc_data *vc;
-+	u8 *src;
-+
-+	/* we really don't need any cursors while the console is blanked */
-+	if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
-+		return;
-+
-+	vc = vc_cons[ops->currcon].d;
-+
-+	src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
-+	if (!src)
-+		return;
-+
-+	s_pitch = (cursor->image.width + 7) >> 3;
-+	dsize = s_pitch * cursor->image.height;
-+	if (cursor->enable) {
-+		switch (cursor->rop) {
-+		case ROP_XOR:
-+			for (i = 0; i < dsize; i++)
-+				src[i] = cursor->image.data[i] ^ cursor->mask[i];
-+			break;
-+		case ROP_COPY:
-+		default:
-+			for (i = 0; i < dsize; i++)
-+				src[i] = cursor->image.data[i] & cursor->mask[i];
-+			break;
-+		}
-+	} else
-+		memcpy(src, cursor->image.data, dsize);
-+
-+	fbcon_decor_renderc(info,
-+			cursor->image.dy + vc->vc_decor.ty,
-+			cursor->image.dx + vc->vc_decor.tx,
-+			cursor->image.height,
-+			cursor->image.width,
-+			(u8 *)src,
-+			cc2cx(cursor->image.fg_color),
-+			cc2cx(cursor->image.bg_color),
-+			cursor->image.bg_color == vc->vc_decor.bg_color);
-+
-+	kfree(src);
-+}
-+
-+static void decorset(u8 *dst, int height, int width, int dstbytes,
-+				u32 bgx, int bpp)
-+{
-+	int i;
-+
-+	if (bpp == 8)
-+		bgx |= bgx << 8;
-+	if (bpp == 16 || bpp == 8)
-+		bgx |= bgx << 16;
-+
-+	while (height-- > 0) {
-+		u8 *p = dst;
-+
-+		switch (bpp) {
-+
-+		case 32:
-+			for (i = 0; i < width; i++) {
-+				fb_writel(bgx, p); p += 4;
-+			}
-+			break;
-+		case 24:
-+			for (i = 0; i < width; i++) {
-+#ifdef __LITTLE_ENDIAN
-+				fb_writew((bgx & 0xffff), (u16 *)p); p += 2;
-+				fb_writeb((bgx >> 16), p++);
-+#else
-+				fb_writew((bgx >> 8), (u16 *)p); p += 2;
-+				fb_writeb((bgx & 0xff), p++);
-+#endif
-+			}
-+			break;
-+		case 16:
-+			for (i = 0; i < width/4; i++) {
-+				fb_writel(bgx, p); p += 4;
-+				fb_writel(bgx, p); p += 4;
-+			}
-+			if (width & 2) {
-+				fb_writel(bgx, p); p += 4;
-+			}
-+			if (width & 1)
-+				fb_writew(bgx, (u16 *)p);
-+			break;
-+		case 8:
-+			for (i = 0; i < width/4; i++) {
-+				fb_writel(bgx, p); p += 4;
-+			}
-+
-+			if (width & 2) {
-+				fb_writew(bgx, p); p += 2;
-+			}
-+			if (width & 1)
-+				fb_writeb(bgx, (u8 *)p);
-+			break;
-+
-+		}
-+		dst += dstbytes;
-+	}
-+}
-+
-+void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
-+		   int srclinebytes, int bpp)
-+{
-+	int i;
-+
-+	while (height-- > 0) {
-+		u32 *p = (u32 *)dst;
-+		u32 *q = (u32 *)src;
-+
-+		switch (bpp) {
-+
-+		case 32:
-+			for (i = 0; i < width; i++)
-+				fb_writel(*q++, p++);
-+			break;
-+		case 24:
-+			for (i = 0; i < (width * 3 / 4); i++)
-+				fb_writel(*q++, p++);
-+			if ((width * 3) % 4) {
-+				if (width & 2) {
-+					fb_writeb(*(u8 *)q, (u8 *)p);
-+				} else if (width & 1) {
-+					fb_writew(*(u16 *)q, (u16 *)p);
-+					fb_writeb(*(u8 *)((u16 *)q + 1),
-+							(u8 *)((u16 *)p + 2));
-+				}
-+			}
-+			break;
-+		case 16:
-+			for (i = 0; i < width/4; i++) {
-+				fb_writel(*q++, p++);
-+				fb_writel(*q++, p++);
-+			}
-+			if (width & 2)
-+				fb_writel(*q++, p++);
-+			if (width & 1)
-+				fb_writew(*(u16 *)q, (u16 *)p);
-+			break;
-+		case 8:
-+			for (i = 0; i < width/4; i++)
-+				fb_writel(*q++, p++);
-+
-+			if (width & 2) {
-+				fb_writew(*(u16 *)q, (u16 *)p);
-+				q = (u32 *) ((u16 *)q + 1);
-+				p = (u32 *) ((u16 *)p + 1);
-+			}
-+			if (width & 1)
-+				fb_writeb(*(u8 *)q, (u8 *)p);
-+			break;
-+		}
-+
-+		dst += linebytes;
-+		src += srclinebytes;
-+	}
-+}
-+
-+static void decorfill(struct fb_info *info, int sy, int sx, int height,
-+		       int width)
-+{
-+	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
-+	int d  = sy * info->fix.line_length + sx * bytespp;
-+	int ds = (sy * info->var.xres + sx) * bytespp;
-+
-+	fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds),
-+		    height, width, info->fix.line_length, info->var.xres * bytespp,
-+		    info->var.bits_per_pixel);
-+}
-+
-+void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
-+		    int height, int width)
-+{
-+	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-+	struct fbcon_ops *ops = info->fbcon_par;
-+	u8 *dst;
-+	int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info);
-+
-+	transparent = (vc->vc_decor.bg_color == bg_color);
-+	sy = sy * vc->vc_font.height + vc->vc_decor.ty;
-+	sx = sx * vc->vc_font.width + vc->vc_decor.tx;
-+	height *= vc->vc_font.height;
-+	width *= vc->vc_font.width;
-+
-+	/* Don't paint the background image if console is blanked */
-+	if (transparent && !ops->blank_state) {
-+		decorfill(info, sy, sx, height, width);
-+	} else {
-+		dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
-+			     sx * ((info->var.bits_per_pixel + 7) >> 3));
-+		decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
-+			  info->var.bits_per_pixel);
-+	}
-+}
-+
-+void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info,
-+			    int bottom_only)
-+{
-+	unsigned int tw = vc->vc_cols*vc->vc_font.width;
-+	unsigned int th = vc->vc_rows*vc->vc_font.height;
-+
-+	if (!bottom_only) {
-+		/* top margin */
-+		decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres);
-+		/* left margin */
-+		decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx);
-+		/* right margin */
-+		decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th,
-+			   info->var.xres - vc->vc_decor.tx - tw);
-+	}
-+	decorfill(info, vc->vc_decor.ty + th, 0,
-+		   info->var.yres - vc->vc_decor.ty - th, info->var.xres);
-+}
-+
-+void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
-+			   int sx, int dx, int width)
-+{
-+	u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
-+	u16 *s = d + (dx - sx);
-+	u16 *start = d;
-+	u16 *ls = d;
-+	u16 *le = d + width;
-+	u16 c;
-+	int x = dx;
-+	u16 attr = 1;
-+
-+	do {
-+		c = scr_readw(d);
-+		if (attr != (c & 0xff00)) {
-+			attr = c & 0xff00;
-+			if (d > start) {
-+				fbcon_decor_putcs(vc, info, start, d - start, y, x);
-+				x += d - start;
-+				start = d;
-+			}
-+		}
-+		if (s >= ls && s < le && c == scr_readw(s)) {
-+			if (d > start) {
-+				fbcon_decor_putcs(vc, info, start, d - start, y, x);
-+				x += d - start + 1;
-+				start = d + 1;
-+			} else {
-+				x++;
-+				start++;
-+			}
-+		}
-+		s++;
-+		d++;
-+	} while (d < le);
-+	if (d > start)
-+		fbcon_decor_putcs(vc, info, start, d - start, y, x);
-+}
-+
-+void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank)
-+{
-+	if (blank) {
-+		decorset((u8 *)info->screen_base, info->var.yres, info->var.xres,
-+			  info->fix.line_length, 0, info->var.bits_per_pixel);
-+	} else {
-+		update_screen(vc);
-+		fbcon_decor_clear_margins(vc, info, 0);
-+	}
-+}
-+
-diff --git a/drivers/video/console/fbcondecor.c b/drivers/video/console/fbcondecor.c
-new file mode 100644
-index 000000000000..78288a497a60
---- /dev/null
-+++ b/drivers/video/console/fbcondecor.c
-@@ -0,0 +1,549 @@
-+/*
-+ *  linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations
-+ *
-+ *  Copyright (C) 2004-2009 Michal Januszewski <michalj+fbcondecor@gmail.com>
-+ *
-+ *  Code based upon "Bootsplash" (C) 2001-2003
-+ *       Volker Poplawski <volker@poplawski.de>,
-+ *       Stefan Reinauer <stepan@suse.de>,
-+ *       Steffen Winterfeldt <snwint@suse.de>,
-+ *       Michael Schroeder <mls@suse.de>,
-+ *       Ken Wimer <wimer@suse.de>.
-+ *
-+ *  Compat ioctl support by Thorsten Klein <TK@Thorsten-Klein.de>.
-+ *
-+ *  This file is subject to the terms and conditions of the GNU General Public
-+ *  License.  See the file COPYING in the main directory of this archive for
-+ *  more details.
-+ *
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/fb.h>
-+#include <linux/vt_kern.h>
-+#include <linux/vmalloc.h>
-+#include <linux/unistd.h>
-+#include <linux/syscalls.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/workqueue.h>
-+#include <linux/kmod.h>
-+#include <linux/miscdevice.h>
-+#include <linux/device.h>
-+#include <linux/fs.h>
-+#include <linux/compat.h>
-+#include <linux/console.h>
-+#include <linux/binfmts.h>
-+#include <linux/uaccess.h>
-+#include <asm/irq.h>
-+
-+#include "../fbdev/core/fbcon.h"
-+#include "fbcondecor.h"
-+
-+extern signed char con2fb_map[];
-+static int fbcon_decor_enable(struct vc_data *vc);
-+
-+static int initialized;
-+
-+char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper";
-+EXPORT_SYMBOL(fbcon_decor_path);
-+
-+int fbcon_decor_call_helper(char *cmd, unsigned short vc)
-+{
-+	char *envp[] = {
-+		"HOME=/",
-+		"PATH=/sbin:/bin",
-+		NULL
-+	};
-+
-+	char tfb[5];
-+	char tcons[5];
-+	unsigned char fb = (int) con2fb_map[vc];
-+
-+	char *argv[] = {
-+		fbcon_decor_path,
-+		"2",
-+		cmd,
-+		tcons,
-+		tfb,
-+		vc_cons[vc].d->vc_decor.theme,
-+		NULL
-+	};
-+
-+	snprintf(tfb, 5, "%d", fb);
-+	snprintf(tcons, 5, "%d", vc);
-+
-+	return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC);
-+}
-+
-+/* Disables fbcondecor on a virtual console; called with console sem held. */
-+int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw)
-+{
-+	struct fb_info *info;
-+
-+	if (!vc->vc_decor.state)
-+		return -EINVAL;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (info == NULL)
-+		return -EINVAL;
-+
-+	vc->vc_decor.state = 0;
-+	vc_resize(vc, info->var.xres / vc->vc_font.width,
-+		  info->var.yres / vc->vc_font.height);
-+
-+	if (fg_console == vc->vc_num && redraw) {
-+		redraw_screen(vc, 0);
-+		update_region(vc, vc->vc_origin +
-+			      vc->vc_size_row * vc->vc_top,
-+			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-+	}
-+
-+	printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n",
-+			 vc->vc_num);
-+
-+	return 0;
-+}
-+
-+/* Enables fbcondecor on a virtual console; called with console sem held. */
-+static int fbcon_decor_enable(struct vc_data *vc)
-+{
-+	struct fb_info *info;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 ||
-+	    info == NULL || vc->vc_decor.state || (!info->bgdecor.data &&
-+	    vc->vc_num == fg_console))
-+		return -EINVAL;
-+
-+	vc->vc_decor.state = 1;
-+	vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width,
-+		  vc->vc_decor.theight / vc->vc_font.height);
-+
-+	if (fg_console == vc->vc_num) {
-+		redraw_screen(vc, 0);
-+		update_region(vc, vc->vc_origin +
-+			      vc->vc_size_row * vc->vc_top,
-+			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-+		fbcon_decor_clear_margins(vc, info, 0);
-+	}
-+
-+	printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n",
-+			 vc->vc_num);
-+
-+	return 0;
-+}
-+
-+static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin)
-+{
-+	int ret;
-+
-+	console_lock();
-+	if (!state)
-+		ret = fbcon_decor_disable(vc, 1);
-+	else
-+		ret = fbcon_decor_enable(vc);
-+	console_unlock();
-+
-+	return ret;
-+}
-+
-+static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state)
-+{
-+	*state = vc->vc_decor.state;
-+}
-+
-+static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin)
-+{
-+	struct fb_info *info;
-+	int len;
-+	char *tmp;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (info == NULL || !cfg->twidth || !cfg->theight ||
-+	    cfg->tx + cfg->twidth  > info->var.xres ||
-+	    cfg->ty + cfg->theight > info->var.yres)
-+		return -EINVAL;
-+
-+	len = strnlen_user(cfg->theme, MAX_ARG_STRLEN);
-+	if (!len || len > FBCON_DECOR_THEME_LEN)
-+		return -EINVAL;
-+	tmp = kmalloc(len, GFP_KERNEL);
-+	if (!tmp)
-+		return -ENOMEM;
-+	if (copy_from_user(tmp, (void __user *)cfg->theme, len))
-+		return -EFAULT;
-+	cfg->theme = tmp;
-+	cfg->state = 0;
-+
-+	console_lock();
-+	if (vc->vc_decor.state)
-+		fbcon_decor_disable(vc, 1);
-+	kfree(vc->vc_decor.theme);
-+	vc->vc_decor = *cfg;
-+	console_unlock();
-+
-+	printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n",
-+			 vc->vc_num, vc->vc_decor.theme);
-+	return 0;
-+}
-+
-+static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc,
-+					struct vc_decor *decor)
-+{
-+	char __user *tmp;
-+
-+	tmp = decor->theme;
-+	*decor = vc->vc_decor;
-+	decor->theme = tmp;
-+
-+	if (vc->vc_decor.theme) {
-+		if (copy_to_user(tmp, vc->vc_decor.theme,
-+					strlen(vc->vc_decor.theme) + 1))
-+			return -EFAULT;
-+	} else
-+		if (put_user(0, tmp))
-+			return -EFAULT;
-+
-+	return 0;
-+}
-+
-+static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img,
-+						unsigned char origin)
-+{
-+	struct fb_info *info;
-+	int len;
-+	u8 *tmp;
-+
-+	if (vc->vc_num != fg_console)
-+		return -EINVAL;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (info == NULL)
-+		return -EINVAL;
-+
-+	if (img->width != info->var.xres || img->height != info->var.yres) {
-+		printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n");
-+		printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height,
-+				info->var.xres, info->var.yres);
-+		return -EINVAL;
-+	}
-+
-+	if (img->depth != info->var.bits_per_pixel) {
-+		printk(KERN_ERR "fbcondecor: picture depth mismatch\n");
-+		return -EINVAL;
-+	}
-+
-+	if (img->depth == 8) {
-+		if (!img->cmap.len || !img->cmap.red || !img->cmap.green ||
-+		    !img->cmap.blue)
-+			return -EINVAL;
-+
-+		tmp = vmalloc(img->cmap.len * 3 * 2);
-+		if (!tmp)
-+			return -ENOMEM;
-+
-+		if (copy_from_user(tmp,
-+				(void __user *)img->cmap.red,
-+						(img->cmap.len << 1)) ||
-+			copy_from_user(tmp + (img->cmap.len << 1),
-+				(void __user *)img->cmap.green,
-+						(img->cmap.len << 1)) ||
-+			copy_from_user(tmp + (img->cmap.len << 2),
-+				(void __user *)img->cmap.blue,
-+						(img->cmap.len << 1))) {
-+			vfree(tmp);
-+			return -EFAULT;
-+		}
-+
-+		img->cmap.transp = NULL;
-+		img->cmap.red = (u16 *)tmp;
-+		img->cmap.green = img->cmap.red + img->cmap.len;
-+		img->cmap.blue = img->cmap.green + img->cmap.len;
-+	} else {
-+		img->cmap.red = NULL;
-+	}
-+
-+	len = ((img->depth + 7) >> 3) * img->width * img->height;
-+
-+	/*
-+	 * Allocate an additional byte so that we never go outside of the
-+	 * buffer boundaries in the rendering functions in a 24 bpp mode.
-+	 */
-+	tmp = vmalloc(len + 1);
-+
-+	if (!tmp)
-+		goto out;
-+
-+	if (copy_from_user(tmp, (void __user *)img->data, len))
-+		goto out;
-+
-+	img->data = tmp;
-+
-+	console_lock();
-+
-+	if (info->bgdecor.data)
-+		vfree((u8 *)info->bgdecor.data);
-+	if (info->bgdecor.cmap.red)
-+		vfree(info->bgdecor.cmap.red);
-+
-+	info->bgdecor = *img;
-+
-+	if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) {
-+		redraw_screen(vc, 0);
-+		update_region(vc, vc->vc_origin +
-+			      vc->vc_size_row * vc->vc_top,
-+			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-+		fbcon_decor_clear_margins(vc, info, 0);
-+	}
-+
-+	console_unlock();
-+
-+	return 0;
-+
-+out:
-+	if (img->cmap.red)
-+		vfree(img->cmap.red);
-+
-+	if (tmp)
-+		vfree(tmp);
-+	return -ENOMEM;
-+}
-+
-+static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg)
-+{
-+	struct fbcon_decor_iowrapper __user *wrapper = (void __user *) arg;
-+	struct vc_data *vc = NULL;
-+	unsigned short vc_num = 0;
-+	unsigned char origin = 0;
-+	void __user *data = NULL;
-+
-+	if (!access_ok(VERIFY_READ, wrapper,
-+			sizeof(struct fbcon_decor_iowrapper)))
-+		return -EFAULT;
-+
-+	__get_user(vc_num, &wrapper->vc);
-+	__get_user(origin, &wrapper->origin);
-+	__get_user(data, &wrapper->data);
-+
-+	if (!vc_cons_allocated(vc_num))
-+		return -EINVAL;
-+
-+	vc = vc_cons[vc_num].d;
-+
-+	switch (cmd) {
-+	case FBIOCONDECOR_SETPIC:
-+	{
-+		struct fb_image img;
-+
-+		if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image)))
-+			return -EFAULT;
-+
-+		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
-+	}
-+	case FBIOCONDECOR_SETCFG:
-+	{
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
-+			return -EFAULT;
-+
-+		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
-+	}
-+	case FBIOCONDECOR_GETCFG:
-+	{
-+		int rval;
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
-+			return -EFAULT;
-+
-+		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
-+
-+		if (copy_to_user(data, &cfg, sizeof(struct vc_decor)))
-+			return -EFAULT;
-+		return rval;
-+	}
-+	case FBIOCONDECOR_SETSTATE:
-+	{
-+		unsigned int state = 0;
-+
-+		if (get_user(state, (unsigned int __user *)data))
-+			return -EFAULT;
-+		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
-+	}
-+	case FBIOCONDECOR_GETSTATE:
-+	{
-+		unsigned int state = 0;
-+
-+		fbcon_decor_ioctl_dogetstate(vc, &state);
-+		return put_user(state, (unsigned int __user *)data);
-+	}
-+
-+	default:
-+		return -ENOIOCTLCMD;
-+	}
-+}
-+
-+#ifdef CONFIG_COMPAT
-+
-+static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-+{
-+	struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg;
-+	struct vc_data *vc = NULL;
-+	unsigned short vc_num = 0;
-+	unsigned char origin = 0;
-+	compat_uptr_t data_compat = 0;
-+	void __user *data = NULL;
-+
-+	if (!access_ok(VERIFY_READ, wrapper,
-+			sizeof(struct fbcon_decor_iowrapper32)))
-+		return -EFAULT;
-+
-+	__get_user(vc_num, &wrapper->vc);
-+	__get_user(origin, &wrapper->origin);
-+	__get_user(data_compat, &wrapper->data);
-+	data = compat_ptr(data_compat);
-+
-+	if (!vc_cons_allocated(vc_num))
-+		return -EINVAL;
-+
-+	vc = vc_cons[vc_num].d;
-+
-+	switch (cmd) {
-+	case FBIOCONDECOR_SETPIC32:
-+	{
-+		struct fb_image32 img_compat;
-+		struct fb_image img;
-+
-+		if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32)))
-+			return -EFAULT;
-+
-+		fb_image_from_compat(img, img_compat);
-+
-+		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
-+	}
-+
-+	case FBIOCONDECOR_SETCFG32:
-+	{
-+		struct vc_decor32 cfg_compat;
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
-+			return -EFAULT;
-+
-+		vc_decor_from_compat(cfg, cfg_compat);
-+
-+		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
-+	}
-+
-+	case FBIOCONDECOR_GETCFG32:
-+	{
-+		int rval;
-+		struct vc_decor32 cfg_compat;
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
-+			return -EFAULT;
-+		cfg.theme = compat_ptr(cfg_compat.theme);
-+
-+		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
-+
-+		vc_decor_to_compat(cfg_compat, cfg);
-+
-+		if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32)))
-+			return -EFAULT;
-+		return rval;
-+	}
-+
-+	case FBIOCONDECOR_SETSTATE32:
-+	{
-+		compat_uint_t state_compat = 0;
-+		unsigned int state = 0;
-+
-+		if (get_user(state_compat, (compat_uint_t __user *)data))
-+			return -EFAULT;
-+
-+		state = (unsigned int)state_compat;
-+
-+		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
-+	}
-+
-+	case FBIOCONDECOR_GETSTATE32:
-+	{
-+		compat_uint_t state_compat = 0;
-+		unsigned int state = 0;
-+
-+		fbcon_decor_ioctl_dogetstate(vc, &state);
-+		state_compat = (compat_uint_t)state;
-+
-+		return put_user(state_compat, (compat_uint_t __user *)data);
-+	}
-+
-+	default:
-+		return -ENOIOCTLCMD;
-+	}
-+}
-+#else
-+  #define fbcon_decor_compat_ioctl NULL
-+#endif
-+
-+static struct file_operations fbcon_decor_ops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = fbcon_decor_ioctl,
-+	.compat_ioctl = fbcon_decor_compat_ioctl
-+};
-+
-+static struct miscdevice fbcon_decor_dev = {
-+	.minor = MISC_DYNAMIC_MINOR,
-+	.name = "fbcondecor",
-+	.fops = &fbcon_decor_ops
-+};
-+
-+void fbcon_decor_reset(void)
-+{
-+	int i;
-+
-+	for (i = 0; i < num_registered_fb; i++) {
-+		registered_fb[i]->bgdecor.data = NULL;
-+		registered_fb[i]->bgdecor.cmap.red = NULL;
-+	}
-+
-+	for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
-+		vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth =
-+						vc_cons[i].d->vc_decor.theight = 0;
-+		vc_cons[i].d->vc_decor.theme = NULL;
-+	}
-+}
-+
-+int fbcon_decor_init(void)
-+{
-+	int i;
-+
-+	fbcon_decor_reset();
-+
-+	if (initialized)
-+		return 0;
-+
-+	i = misc_register(&fbcon_decor_dev);
-+	if (i) {
-+		printk(KERN_ERR "fbcondecor: failed to register device\n");
-+		return i;
-+	}
-+
-+	fbcon_decor_call_helper("init", 0);
-+	initialized = 1;
-+	return 0;
-+}
-+
-+int fbcon_decor_exit(void)
-+{
-+	fbcon_decor_reset();
-+	return 0;
-+}
-diff --git a/drivers/video/console/fbcondecor.h b/drivers/video/console/fbcondecor.h
-new file mode 100644
-index 000000000000..c49386c16695
---- /dev/null
-+++ b/drivers/video/console/fbcondecor.h
-@@ -0,0 +1,77 @@
-+/*
-+ *  linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers
-+ *
-+ *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
-+ *
-+ */
-+
-+#ifndef __FBCON_DECOR_H
-+#define __FBCON_DECOR_H
-+
-+#ifndef _LINUX_FB_H
-+#include <linux/fb.h>
-+#endif
-+
-+/* This is needed for vc_cons in fbcmap.c */
-+#include <linux/vt_kern.h>
-+
-+struct fb_cursor;
-+struct fb_info;
-+struct vc_data;
-+
-+#ifdef CONFIG_FB_CON_DECOR
-+/* fbcondecor.c */
-+int fbcon_decor_init(void);
-+int fbcon_decor_exit(void);
-+int fbcon_decor_call_helper(char *cmd, unsigned short cons);
-+int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw);
-+
-+/* cfbcondecor.c */
-+void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
-+void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor);
-+void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
-+void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
-+void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank);
-+void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
-+void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp);
-+void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc);
-+
-+/* vt.c */
-+void acquire_console_sem(void);
-+void release_console_sem(void);
-+void do_unblank_screen(int entering_gfx);
-+
-+/* struct vc_data *y */
-+#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme)
-+
-+/* struct fb_info *x, struct vc_data *y */
-+#define fbcon_decor_active_nores(x, y) (x->bgdecor.data && fbcon_decor_active_vc(y))
-+
-+/* struct fb_info *x, struct vc_data *y */
-+#define fbcon_decor_active(x, y) (fbcon_decor_active_nores(x, y) &&	\
-+				x->bgdecor.width == x->var.xres &&	\
-+				x->bgdecor.height == x->var.yres &&	\
-+				x->bgdecor.depth == x->var.bits_per_pixel)
-+
-+#else /* CONFIG_FB_CON_DECOR */
-+
-+static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
-+static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
-+static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
-+static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
-+static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
-+static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
-+static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
-+static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {}
-+static inline int fbcon_decor_call_helper(char *cmd, unsigned short cons) { return 0; }
-+static inline int fbcon_decor_init(void) { return 0; }
-+static inline int fbcon_decor_exit(void) { return 0; }
-+static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
-+
-+#define fbcon_decor_active_vc(y) (0)
-+#define fbcon_decor_active_nores(x, y) (0)
-+#define fbcon_decor_active(x, y) (0)
-+
-+#endif /* CONFIG_FB_CON_DECOR */
-+
-+#endif /* __FBCON_DECOR_H */
-diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
-index 5e58f5ec0a28..1daa8c2cb2d8 100644
---- a/drivers/video/fbdev/Kconfig
-+++ b/drivers/video/fbdev/Kconfig
-@@ -1226,7 +1226,6 @@ config FB_MATROX
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
--	select FB_TILEBLITTING
- 	select FB_MACMODES if PPC_PMAC
- 	---help---
- 	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
-diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
-index 790900d646c0..3f940c93752c 100644
---- a/drivers/video/fbdev/core/bitblit.c
-+++ b/drivers/video/fbdev/core/bitblit.c
-@@ -18,6 +18,7 @@
- #include <linux/console.h>
- #include <asm/types.h>
- #include "fbcon.h"
-+#include "../../console/fbcondecor.h"
- 
- /*
-  * Accelerated handlers.
-@@ -55,6 +56,13 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
- 	area.height = height * vc->vc_font.height;
- 	area.width = width * vc->vc_font.width;
- 
-+	if (fbcon_decor_active(info, vc)) {
-+		area.sx += vc->vc_decor.tx;
-+		area.sy += vc->vc_decor.ty;
-+		area.dx += vc->vc_decor.tx;
-+		area.dy += vc->vc_decor.ty;
-+	}
-+
- 	info->fbops->fb_copyarea(info, &area);
- }
- 
-@@ -379,11 +387,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
- 	cursor.image.depth = 1;
- 	cursor.rop = ROP_XOR;
- 
--	if (info->fbops->fb_cursor)
--		err = info->fbops->fb_cursor(info, &cursor);
-+	if (fbcon_decor_active(info, vc)) {
-+		fbcon_decor_cursor(info, &cursor);
-+	} else {
-+		if (info->fbops->fb_cursor)
-+			err = info->fbops->fb_cursor(info, &cursor);
- 
--	if (err)
--		soft_cursor(info, &cursor);
-+		if (err)
-+			soft_cursor(info, &cursor);
-+	}
- 
- 	ops->cursor_reset = 0;
- }
-diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
-index 68a113594808..21f977cb59d2 100644
---- a/drivers/video/fbdev/core/fbcmap.c
-+++ b/drivers/video/fbdev/core/fbcmap.c
-@@ -17,6 +17,8 @@
- #include <linux/slab.h>
- #include <linux/uaccess.h>
- 
-+#include "../../console/fbcondecor.h"
-+
- static u16 red2[] __read_mostly = {
-     0x0000, 0xaaaa
- };
-@@ -256,9 +258,12 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
- 				break;
- 		}
- 	}
--	if (rc == 0)
-+	if (rc == 0) {
- 		fb_copy_cmap(cmap, &info->cmap);
--
-+		if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
-+		    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
-+			fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
-+	}
- 	return rc;
- }
- 
-diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
-index 04612f938bab..95c349200078 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 "../../console/fbcondecor.h"
- 
- #ifdef FBCONDEBUG
- #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-@@ -95,7 +96,7 @@ enum {
- 
- static struct display fb_display[MAX_NR_CONSOLES];
- 
--static signed char con2fb_map[MAX_NR_CONSOLES];
-+signed char con2fb_map[MAX_NR_CONSOLES];
- static signed char con2fb_map_boot[MAX_NR_CONSOLES];
- 
- static int logo_lines;
-@@ -282,7 +283,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
- 		!vt_force_oops_output(vc);
- }
- 
--static int get_color(struct vc_data *vc, struct fb_info *info,
-+int get_color(struct vc_data *vc, struct fb_info *info,
- 	      u16 c, int is_fg)
- {
- 	int depth = fb_get_color_depth(&info->var, &info->fix);
-@@ -551,6 +552,9 @@ static int do_fbcon_takeover(int show_logo)
- 		info_idx = -1;
- 	} else {
- 		fbcon_has_console_bind = 1;
-+#ifdef CONFIG_FB_CON_DECOR
-+		fbcon_decor_init();
-+#endif
- 	}
- 
- 	return err;
-@@ -1013,6 +1017,12 @@ static const char *fbcon_startup(void)
- 	rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- 	cols /= vc->vc_font.width;
- 	rows /= vc->vc_font.height;
-+
-+	if (fbcon_decor_active(info, vc)) {
-+		cols = vc->vc_decor.twidth / vc->vc_font.width;
-+		rows = vc->vc_decor.theight / vc->vc_font.height;
-+	}
-+
- 	vc_resize(vc, cols, rows);
- 
- 	DPRINTK("mode:   %s\n", info->fix.id);
-@@ -1042,7 +1052,7 @@ static void fbcon_init(struct vc_data *vc, int init)
- 	cap = info->flags;
- 
- 	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
--	    (info->fix.type == FB_TYPE_TEXT))
-+	    (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc))
- 		logo = 0;
- 
- 	if (var_to_display(p, &info->var, info))
-@@ -1275,6 +1285,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
- 		fbcon_clear_margins(vc, 0);
- 	}
- 
-+	if (fbcon_decor_active(info, vc)) {
-+		fbcon_decor_clear(vc, info, sy, sx, height, width);
-+		return;
-+	}
-+
- 	/* Split blits that cross physical y_wrap boundary */
- 
- 	y_break = p->vrows - p->yscroll;
-@@ -1294,10 +1309,15 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
- 	struct display *p = &fb_display[vc->vc_num];
- 	struct fbcon_ops *ops = info->fbcon_par;
- 
--	if (!fbcon_is_inactive(vc, info))
--		ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
--			   get_color(vc, info, scr_readw(s), 1),
--			   get_color(vc, info, scr_readw(s), 0));
-+	if (!fbcon_is_inactive(vc, info)) {
-+
-+		if (fbcon_decor_active(info, vc))
-+			fbcon_decor_putcs(vc, info, s, count, ypos, xpos);
-+		else
-+			ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
-+				   get_color(vc, info, scr_readw(s), 1),
-+				   get_color(vc, info, scr_readw(s), 0));
-+	}
- }
- 
- static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
-@@ -1313,8 +1333,12 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
- 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
- 	struct fbcon_ops *ops = info->fbcon_par;
- 
--	if (!fbcon_is_inactive(vc, info))
--		ops->clear_margins(vc, info, margin_color, bottom_only);
-+	if (!fbcon_is_inactive(vc, info)) {
-+		if (fbcon_decor_active(info, vc))
-+			fbcon_decor_clear_margins(vc, info, bottom_only);
-+		else
-+			ops->clear_margins(vc, info, margin_color, bottom_only);
-+	}
- }
- 
- static void fbcon_cursor(struct vc_data *vc, int mode)
-@@ -1835,7 +1859,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
- 			count = vc->vc_rows;
- 		if (softback_top)
- 			fbcon_softback_note(vc, t, count);
--		if (logo_shown >= 0)
-+		if (logo_shown >= 0 || fbcon_decor_active(info, vc))
- 			goto redraw_up;
- 		switch (p->scrollmode) {
- 		case SCROLL_MOVE:
-@@ -1928,6 +1952,8 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
- 			count = vc->vc_rows;
- 		if (logo_shown >= 0)
- 			goto redraw_down;
-+		if (fbcon_decor_active(info, vc))
-+			goto redraw_down;
- 		switch (p->scrollmode) {
- 		case SCROLL_MOVE:
- 			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
-@@ -2076,6 +2102,13 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s
- 		}
- 		return;
- 	}
-+
-+	if (fbcon_decor_active(info, vc) && sy == dy && height == 1) {
-+		/* must use slower redraw bmove to keep background pic intact */
-+		fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width);
-+		return;
-+	}
-+
- 	ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
- 		   height, width);
- }
-@@ -2146,8 +2179,8 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
- 	var.yres = virt_h * virt_fh;
- 	x_diff = info->var.xres - var.xres;
- 	y_diff = info->var.yres - var.yres;
--	if (x_diff < 0 || x_diff > virt_fw ||
--	    y_diff < 0 || y_diff > virt_fh) {
-+	if ((x_diff < 0 || x_diff > virt_fw ||
-+		y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) {
- 		const struct fb_videomode *mode;
- 
- 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
-@@ -2183,6 +2216,22 @@ static int fbcon_switch(struct vc_data *vc)
- 
- 	info = registered_fb[con2fb_map[vc->vc_num]];
- 	ops = info->fbcon_par;
-+	prev_console = ops->currcon;
-+	if (prev_console != -1)
-+		old_info = registered_fb[con2fb_map[prev_console]];
-+
-+#ifdef CONFIG_FB_CON_DECOR
-+	if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-+		struct vc_data *vc_curr = vc_cons[prev_console].d;
-+
-+		if (vc_curr && fbcon_decor_active_vc(vc_curr)) {
-+			// Clear the screen to avoid displaying funky colors
-+			// during palette updates.
-+			memset((u8 *)info->screen_base + info->fix.line_length * info->var.yoffset,
-+			       0, info->var.yres * info->fix.line_length);
-+		}
-+	}
-+#endif
- 
- 	if (softback_top) {
- 		if (softback_lines)
-@@ -2201,9 +2250,6 @@ static int fbcon_switch(struct vc_data *vc)
- 		logo_shown = FBCON_LOGO_CANSHOW;
- 	}
- 
--	prev_console = ops->currcon;
--	if (prev_console != -1)
--		old_info = registered_fb[con2fb_map[prev_console]];
- 	/*
- 	 * FIXME: If we have multiple fbdev's loaded, we need to
- 	 * update all info->currcon.  Perhaps, we can place this
-@@ -2247,6 +2293,18 @@ static int fbcon_switch(struct vc_data *vc)
- 			fbcon_del_cursor_timer(old_info);
- 	}
- 
-+	if (fbcon_decor_active_vc(vc)) {
-+		struct vc_data *vc_curr = vc_cons[prev_console].d;
-+
-+		if (!vc_curr->vc_decor.theme ||
-+			strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) ||
-+			(fbcon_decor_active_nores(info, vc_curr) &&
-+			 !fbcon_decor_active(info, vc_curr))) {
-+			fbcon_decor_disable(vc, 0);
-+			fbcon_decor_call_helper("modechange", vc->vc_num);
-+		}
-+	}
-+
- 	if (fbcon_is_inactive(vc, info) ||
- 	    ops->blank_state != FB_BLANK_UNBLANK)
- 		fbcon_del_cursor_timer(info);
-@@ -2355,15 +2413,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
- 		}
- 	}
- 
-- 	if (!fbcon_is_inactive(vc, info)) {
-+	if (!fbcon_is_inactive(vc, info)) {
- 		if (ops->blank_state != blank) {
- 			ops->blank_state = blank;
- 			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
- 			ops->cursor_flash = (!blank);
- 
--			if (!(info->flags & FBINFO_MISC_USEREVENT))
--				if (fb_blank(info, blank))
--					fbcon_generic_blank(vc, info, blank);
-+			if (!(info->flags & FBINFO_MISC_USEREVENT)) {
-+				if (fb_blank(info, blank)) {
-+					if (fbcon_decor_active(info, vc))
-+						fbcon_decor_blank(vc, info, blank);
-+					else
-+						fbcon_generic_blank(vc, info, blank);
-+				}
-+			}
- 		}
- 
- 		if (!blank)
-@@ -2546,13 +2609,22 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
- 		set_vc_hi_font(vc, true);
- 
- 	if (resize) {
-+		/* reset wrap/pan */
- 		int cols, rows;
- 
- 		cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
-+
-+		if (fbcon_decor_active(info, vc)) {
-+			info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-+			cols = vc->vc_decor.twidth;
-+			rows = vc->vc_decor.theight;
-+		}
- 		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)
-@@ -2681,7 +2753,11 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
- 	int i, j, k, depth;
- 	u8 val;
- 
--	if (fbcon_is_inactive(vc, info))
-+	if (fbcon_is_inactive(vc, info)
-+#ifdef CONFIG_FB_CON_DECOR
-+			|| vc->vc_num != fg_console
-+#endif
-+		)
- 		return;
- 
- 	if (!con_is_visible(vc))
-@@ -2707,7 +2783,47 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
- 	} else
- 		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
- 
--	fb_set_cmap(&palette_cmap, info);
-+	if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
-+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-+
-+		u16 *red, *green, *blue;
-+		int minlen = min(min(info->var.red.length, info->var.green.length),
-+				     info->var.blue.length);
-+
-+		struct fb_cmap cmap = {
-+			.start = 0,
-+			.len = (1 << minlen),
-+			.red = NULL,
-+			.green = NULL,
-+			.blue = NULL,
-+			.transp = NULL
-+		};
-+
-+		red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
-+
-+		if (!red)
-+			goto out;
-+
-+		green = red + 256;
-+		blue = green + 256;
-+		cmap.red = red;
-+		cmap.green = green;
-+		cmap.blue = blue;
-+
-+		for (i = 0; i < cmap.len; i++)
-+			red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
-+
-+		fb_set_cmap(&cmap, info);
-+		fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
-+		kfree(red);
-+
-+		return;
-+
-+	} else if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
-+		   info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL)
-+		fb_set_cmap(&info->bgdecor.cmap, info);
-+
-+out:	fb_set_cmap(&palette_cmap, info);
- }
- 
- static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
-@@ -2932,7 +3048,14 @@ static void fbcon_modechanged(struct fb_info *info)
- 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- 		cols /= vc->vc_font.width;
- 		rows /= vc->vc_font.height;
--		vc_resize(vc, cols, rows);
-+
-+		if (!fbcon_decor_active_nores(info, vc)) {
-+			vc_resize(vc, cols, rows);
-+		} else {
-+			fbcon_decor_disable(vc, 0);
-+			fbcon_decor_call_helper("modechange", vc->vc_num);
-+		}
-+
- 		updatescrollmode(p, info, vc);
- 		scrollback_max = 0;
- 		scrollback_current = 0;
-@@ -2977,7 +3100,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
- 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- 		cols /= vc->vc_font.width;
- 		rows /= vc->vc_font.height;
--		vc_resize(vc, cols, rows);
-+		if (!fbcon_decor_active_nores(info, vc))
-+			vc_resize(vc, cols, rows);
- 	}
- 
- 	if (fg != -1)
-@@ -3618,6 +3742,7 @@ static void fbcon_exit(void)
- 		}
- 	}
- 
-+	fbcon_decor_exit();
- 	fbcon_has_exited = 1;
- }
- 
-diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
-index f741ba8df01b..b0141433d249 100644
---- a/drivers/video/fbdev/core/fbmem.c
-+++ b/drivers/video/fbdev/core/fbmem.c
-@@ -1253,15 +1253,6 @@ struct fb_fix_screeninfo32 {
- 	u16			reserved[3];
- };
- 
--struct fb_cmap32 {
--	u32			start;
--	u32			len;
--	compat_caddr_t	red;
--	compat_caddr_t	green;
--	compat_caddr_t	blue;
--	compat_caddr_t	transp;
--};
--
- static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
- 			  unsigned long arg)
- {
-diff --git a/include/linux/console_decor.h b/include/linux/console_decor.h
-new file mode 100644
-index 000000000000..15143556c2aa
---- /dev/null
-+++ b/include/linux/console_decor.h
-@@ -0,0 +1,46 @@
-+#ifndef _LINUX_CONSOLE_DECOR_H_
-+#define _LINUX_CONSOLE_DECOR_H_ 1
-+
-+/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */
-+struct vc_decor {
-+	__u8 bg_color;				/* The color that is to be treated as transparent */
-+	__u8 state;				/* Current decor state: 0 = off, 1 = on */
-+	__u16 tx, ty;				/* Top left corner coordinates of the text field */
-+	__u16 twidth, theight;			/* Width and height of the text field */
-+	char *theme;
-+};
-+
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+#include <linux/compat.h>
-+
-+struct vc_decor32 {
-+	__u8 bg_color;				/* The color that is to be treated as transparent */
-+	__u8 state;				/* Current decor state: 0 = off, 1 = on */
-+	__u16 tx, ty;				/* Top left corner coordinates of the text field */
-+	__u16 twidth, theight;			/* Width and height of the text field */
-+	compat_uptr_t theme;
-+};
-+
-+#define vc_decor_from_compat(to, from) \
-+	(to).bg_color = (from).bg_color; \
-+	(to).state    = (from).state; \
-+	(to).tx       = (from).tx; \
-+	(to).ty       = (from).ty; \
-+	(to).twidth   = (from).twidth; \
-+	(to).theight  = (from).theight; \
-+	(to).theme    = compat_ptr((from).theme)
-+
-+#define vc_decor_to_compat(to, from) \
-+	(to).bg_color = (from).bg_color; \
-+	(to).state    = (from).state; \
-+	(to).tx       = (from).tx; \
-+	(to).ty       = (from).ty; \
-+	(to).twidth   = (from).twidth; \
-+	(to).theight  = (from).theight; \
-+	(to).theme    = ptr_to_compat((from).theme)
-+
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
-+#endif
-diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
-index c0ec478ea5bf..8bfed6b21fc9 100644
---- a/include/linux/console_struct.h
-+++ b/include/linux/console_struct.h
-@@ -21,6 +21,7 @@ struct vt_struct;
- struct uni_pagedir;
- 
- #define NPAR 16
-+#include <linux/console_decor.h>
- 
- /*
-  * Example: vc_data of a console that was scrolled 3 lines down.
-@@ -141,6 +142,8 @@ struct vc_data {
- 	struct uni_pagedir *vc_uni_pagedir;
- 	struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
- 	bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
-+
-+	struct vc_decor vc_decor;
- 	/* additional information is in vt_kern.h */
- };
- 
-diff --git a/include/linux/fb.h b/include/linux/fb.h
-index bc24e48e396d..ad7d182c7545 100644
---- a/include/linux/fb.h
-+++ b/include/linux/fb.h
-@@ -239,6 +239,34 @@ struct fb_deferred_io {
- };
- #endif
- 
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+struct fb_image32 {
-+	__u32 dx;			/* Where to place image */
-+	__u32 dy;
-+	__u32 width;			/* Size of image */
-+	__u32 height;
-+	__u32 fg_color;			/* Only used when a mono bitmap */
-+	__u32 bg_color;
-+	__u8  depth;			/* Depth of the image */
-+	const compat_uptr_t data;	/* Pointer to image data */
-+	struct fb_cmap32 cmap;		/* color map info */
-+};
-+
-+#define fb_image_from_compat(to, from) \
-+	(to).dx       = (from).dx; \
-+	(to).dy       = (from).dy; \
-+	(to).width    = (from).width; \
-+	(to).height   = (from).height; \
-+	(to).fg_color = (from).fg_color; \
-+	(to).bg_color = (from).bg_color; \
-+	(to).depth    = (from).depth; \
-+	(to).data     = compat_ptr((from).data); \
-+	fb_cmap_from_compat((to).cmap, (from).cmap)
-+
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
- /*
-  * Frame buffer operations
-  *
-@@ -509,6 +537,9 @@ struct fb_info {
- #define FBINFO_STATE_SUSPENDED	1
- 	u32 state;			/* Hardware state i.e suspend */
- 	void *fbcon_par;                /* fbcon use-only private area */
-+
-+	struct fb_image bgdecor;
-+
- 	/* From here on everything is device dependent */
- 	void *par;
- 	/* we need the PCI or similar aperture base/size not
-diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h
-index 6cd9b198b7c6..a228440649fa 100644
---- a/include/uapi/linux/fb.h
-+++ b/include/uapi/linux/fb.h
-@@ -9,6 +9,23 @@
- 
- #define FB_MAX			32	/* sufficient for now */
- 
-+struct fbcon_decor_iowrapper {
-+	unsigned short vc;		/* Virtual console */
-+	unsigned char origin;		/* Point of origin of the request */
-+	void *data;
-+};
-+
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+#include <linux/compat.h>
-+struct fbcon_decor_iowrapper32 {
-+	unsigned short vc;		/* Virtual console */
-+	unsigned char origin;		/* Point of origin of the request */
-+	compat_uptr_t data;
-+};
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
- /* ioctls
-    0x46 is 'F'								*/
- #define FBIOGET_VSCREENINFO	0x4600
-@@ -36,6 +53,25 @@
- #define FBIOGET_DISPINFO        0x4618
- #define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
- 
-+#define FBIOCONDECOR_SETCFG	_IOWR('F', 0x19, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_GETCFG	_IOR('F', 0x1A, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_SETSTATE	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_GETSTATE	_IOR('F', 0x1C, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_SETPIC	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+#define FBIOCONDECOR_SETCFG32	_IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_GETCFG32	_IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_SETSTATE32	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_GETSTATE32	_IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_SETPIC32	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
-+#define FBCON_DECOR_THEME_LEN		128	/* Maximum length of a theme name */
-+#define FBCON_DECOR_IO_ORIG_KERNEL	0	/* Kernel ioctl origin */
-+#define FBCON_DECOR_IO_ORIG_USER	1	/* User ioctl origin */
-+
- #define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/
- #define FB_TYPE_PLANES			1	/* Non interleaved planes */
- #define FB_TYPE_INTERLEAVED_PLANES	2	/* Interleaved planes	*/
-@@ -278,6 +314,29 @@ struct fb_var_screeninfo {
- 	__u32 reserved[4];		/* Reserved for future compatibility */
- };
- 
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+struct fb_cmap32 {
-+	__u32 start;
-+	__u32 len;			/* Number of entries */
-+	compat_uptr_t red;		/* Red values	*/
-+	compat_uptr_t green;
-+	compat_uptr_t blue;
-+	compat_uptr_t transp;		/* transparency, can be NULL */
-+};
-+
-+#define fb_cmap_from_compat(to, from) \
-+	(to).start  = (from).start; \
-+	(to).len    = (from).len; \
-+	(to).red    = compat_ptr((from).red); \
-+	(to).green  = compat_ptr((from).green); \
-+	(to).blue   = compat_ptr((from).blue); \
-+	(to).transp = compat_ptr((from).transp)
-+
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
-+
- struct fb_cmap {
- 	__u32 start;			/* First entry	*/
- 	__u32 len;			/* Number of entries */
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index d9c31bc2eaea..e33ac56cc32a 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -150,6 +150,10 @@ static const int cap_last_cap = CAP_LAST_CAP;
- static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
- #endif
- 
-+#ifdef CONFIG_FB_CON_DECOR
-+extern char fbcon_decor_path[];
-+#endif
-+
- #ifdef CONFIG_INOTIFY_USER
- #include <linux/inotify.h>
- #endif
-@@ -283,6 +287,15 @@ static struct ctl_table sysctl_base_table[] = {
- 		.mode		= 0555,
- 		.child		= dev_table,
- 	},
-+#ifdef CONFIG_FB_CON_DECOR
-+	{
-+		.procname	= "fbcondecor",
-+		.data		= &fbcon_decor_path,
-+		.maxlen		= KMOD_PATH_LEN,
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dostring,
-+	},
-+#endif
- 	{ }
- };
- 
Index: npl/kernel/linux_src/config
===================================================================
--- npl/kernel/linux_src/config	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ npl/kernel/linux_src/config	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -1,21 +1,46 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86 5.14.12 Kernel Configuration
-#
-CONFIG_CC_VERSION_TEXT="gcc (GCC) 5.4.0"
-CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=50400
-CONFIG_CLANG_VERSION=0
-CONFIG_AS_IS_GNU=y
-CONFIG_AS_VERSION=22700
-CONFIG_LD_IS_BFD=y
-CONFIG_LD_VERSION=22700
-CONFIG_LLD_VERSION=0
-CONFIG_CC_CAN_LINK=y
-CONFIG_CC_CAN_LINK_STATIC=y
-CONFIG_CC_HAS_ASM_GOTO=y
+# Linux/x86 4.4.27 Kernel Configuration
+#
+# CONFIG_64BIT is not set
+CONFIG_X86_32=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_PERF_EVENTS_INTEL_UNCORE=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_HAVE_INTEL_TXT=y
+CONFIG_X86_32_SMP=y
+CONFIG_X86_32_LAZY_GS=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 CONFIG_IRQ_WORK=y
-CONFIG_BUILDTIME_TABLE_SORT=y
-CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
 
 #
@@ -23,8 +48,8 @@
 #
 CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
 # CONFIG_COMPILE_TEST is not set
 CONFIG_LOCALVERSION="_bigmem_syn3"
 # CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_BUILD_SALT=""
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
@@ -33,5 +58,4 @@
 CONFIG_HAVE_KERNEL_LZO=y
 CONFIG_HAVE_KERNEL_LZ4=y
-CONFIG_HAVE_KERNEL_ZSTD=y
 # CONFIG_KERNEL_GZIP is not set
 # CONFIG_KERNEL_BZIP2 is not set
@@ -40,6 +64,4 @@
 # CONFIG_KERNEL_LZO is not set
 # CONFIG_KERNEL_LZ4 is not set
-# CONFIG_KERNEL_ZSTD is not set
-CONFIG_DEFAULT_INIT=""
 CONFIG_DEFAULT_HOSTNAME="(none)"
 CONFIG_SWAP=y
@@ -48,6 +70,6 @@
 CONFIG_POSIX_MQUEUE=y
 CONFIG_POSIX_MQUEUE_SYSCTL=y
-# CONFIG_WATCH_QUEUE is not set
 CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
 CONFIG_USELIB=y
 # CONFIG_AUDIT is not set
@@ -59,21 +81,13 @@
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
 CONFIG_GENERIC_PENDING_IRQ=y
-CONFIG_GENERIC_IRQ_MIGRATION=y
-CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_IRQ_DOMAIN=y
 CONFIG_IRQ_DOMAIN_HIERARCHY=y
 CONFIG_GENERIC_MSI_IRQ=y
 CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
-CONFIG_IRQ_MSI_IOMMU=y
-CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
-CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
 CONFIG_IRQ_FORCED_THREADING=y
 CONFIG_SPARSE_IRQ=y
-# end of IRQ subsystem
-
 CONFIG_CLOCKSOURCE_WATCHDOG=y
-CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
 CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
@@ -82,6 +96,4 @@
 CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
 CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
-CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
 
 #
@@ -94,20 +106,4 @@
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
-# end of Timers subsystem
-
-CONFIG_BPF=y
-CONFIG_HAVE_EBPF_JIT=y
-
-#
-# BPF subsystem
-#
-# CONFIG_BPF_SYSCALL is not set
-# CONFIG_BPF_JIT is not set
-# end of BPF subsystem
-
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_SCHED_CORE is not set
 
 #
@@ -122,8 +118,4 @@
 CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
-# CONFIG_PSI is not set
-# end of CPU/Task time and stats accounting
-
-CONFIG_CPU_ISOLATION=y
 
 #
@@ -133,50 +125,38 @@
 # CONFIG_RCU_EXPERT is not set
 CONFIG_SRCU=y
-CONFIG_TREE_SRCU=y
+# CONFIG_TASKS_RCU is not set
 CONFIG_RCU_STALL_COMMON=y
-CONFIG_RCU_NEED_SEGCBLIST=y
-# end of RCU Subsystem
-
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_BUILD_BIN2C=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
-# CONFIG_IKHEADERS is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
-CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
 CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
-
-#
-# Scheduler features
-#
-# CONFIG_UCLAMP_TASK is not set
-# end of Scheduler features
-
 CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
 CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_CPUACCT=y
 # CONFIG_MEMCG is not set
-# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_HUGETLB is not set
+# CONFIG_CGROUP_PERF is not set
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_CFS_BANDWIDTH is not set
 CONFIG_RT_GROUP_SCHED=y
-# CONFIG_CGROUP_PIDS is not set
-# CONFIG_CGROUP_RDMA is not set
-# CONFIG_CGROUP_FREEZER is not set
-# CONFIG_CGROUP_HUGETLB is not set
-CONFIG_CPUSETS=y
-CONFIG_PROC_PID_CPUSET=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CGROUP_CPUACCT=y
-# CONFIG_CGROUP_PERF is not set
-# CONFIG_CGROUP_MISC is not set
-CONFIG_SOCK_CGROUP_DATA=y
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
-CONFIG_TIME_NS=y
 CONFIG_IPC_NS=y
 CONFIG_USER_NS=y
 CONFIG_PID_NS=y
 CONFIG_NET_NS=y
-# CONFIG_CHECKPOINT_RESTORE is not set
 # CONFIG_SCHED_AUTOGROUP is not set
 # CONFIG_SYSFS_DEPRECATED is not set
@@ -190,13 +170,11 @@
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
-CONFIG_RD_ZSTD=y
-# CONFIG_BOOT_CONFIG is not set
-CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_LD_ORPHAN_WARN=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_HAVE_UID16=y
 CONFIG_SYSCTL_EXCEPTION_TRACE=y
 CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BPF=y
 # CONFIG_EXPERT is not set
 CONFIG_UID16=y
@@ -204,8 +182,7 @@
 CONFIG_SGETMASK_SYSCALL=y
 CONFIG_SYSFS_SYSCALL=y
-CONFIG_FHANDLE=y
-CONFIG_POSIX_TIMERS=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
 CONFIG_PRINTK=y
-CONFIG_PRINTK_NMI=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
@@ -213,19 +190,15 @@
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_FUTEX_PI=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
 CONFIG_SHMEM=y
 CONFIG_AIO=y
-CONFIG_IO_URING=y
 CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_PCI_QUIRKS=y
 CONFIG_MEMBARRIER=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_BASE_RELATIVE=y
-# CONFIG_USERFAULTFD is not set
-CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
-CONFIG_RSEQ=y
 # CONFIG_EMBEDDED is not set
 CONFIG_HAVE_PERF_EVENTS=y
@@ -235,63 +208,148 @@
 #
 CONFIG_PERF_EVENTS=y
-# end of Kernel Performance Events And Counters
-
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLUB_DEBUG=y
 # CONFIG_COMPAT_BRK is not set
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-CONFIG_SLAB_MERGE_DEFAULT=y
-# CONFIG_SLAB_FREELIST_RANDOM is not set
-# CONFIG_SLAB_FREELIST_HARDENED is not set
-# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set
-CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
 # CONFIG_PROFILING is not set
-# end of General setup
-
-# CONFIG_64BIT is not set
-CONFIG_X86_32=y
-CONFIG_X86=y
-CONFIG_INSTRUCTION_DECODER=y
-CONFIG_OUTPUT_FORMAT="elf32-i386"
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_MMU=y
-CONFIG_ARCH_MMAP_RND_BITS_MIN=8
-CONFIG_ARCH_MMAP_RND_BITS_MAX=16
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_BUG=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_HAS_CPU_RELAX=y
-CONFIG_ARCH_HAS_FILTER_PGPROT=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
-CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
-CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
-CONFIG_HAVE_INTEL_TXT=y
-CONFIG_X86_32_SMP=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
-CONFIG_FIX_EARLYCON_MEM=y
-CONFIG_PGTABLE_LEVELS=3
+CONFIG_KEXEC_CORE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_CMDLINE_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_ASN1=m
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_FREEZER=y
 
 #
 # Processor type and features
 #
+CONFIG_ZONE_DMA=y
 CONFIG_SMP=y
 CONFIG_X86_FEATURE_NAMES=y
 CONFIG_X86_MPPARSE=y
-# CONFIG_GOLDFISH is not set
-# CONFIG_RETPOLINE is not set
-# CONFIG_X86_CPU_RESCTRL is not set
 CONFIG_X86_BIGSMP=y
 # CONFIG_X86_EXTENDED_PLATFORM is not set
 CONFIG_X86_INTEL_LPSS=y
 # CONFIG_X86_AMD_PLATFORM_DEVICE is not set
-CONFIG_IOSF_MBI=y
+CONFIG_IOSF_MBI=m
 CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
 # CONFIG_X86_32_IRIS is not set
@@ -300,12 +358,10 @@
 CONFIG_PARAVIRT=y
 CONFIG_PARAVIRT_SPINLOCKS=y
-CONFIG_X86_HV_CALLBACK_VECTOR=y
 # CONFIG_XEN is not set
 CONFIG_KVM_GUEST=y
-CONFIG_ARCH_CPUIDLE_HALTPOLL=y
-# CONFIG_PVH is not set
+CONFIG_LGUEST_GUEST=y
 # CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
 CONFIG_PARAVIRT_CLOCK=y
-# CONFIG_M486SX is not set
+CONFIG_NO_BOOTMEM=y
 # CONFIG_M486 is not set
 # CONFIG_M586 is not set
@@ -340,47 +396,35 @@
 CONFIG_X86_CMPXCHG64=y
 CONFIG_X86_CMOV=y
-CONFIG_X86_MINIMUM_CPU_FAMILY=6
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
 CONFIG_X86_DEBUGCTLMSR=y
-CONFIG_IA32_FEAT_CTL=y
-CONFIG_X86_VMX_FEATURE_NAMES=y
 CONFIG_CPU_SUP_INTEL=y
 CONFIG_CPU_SUP_AMD=y
-CONFIG_CPU_SUP_HYGON=y
 CONFIG_CPU_SUP_CENTAUR=y
 CONFIG_CPU_SUP_TRANSMETA_32=y
-CONFIG_CPU_SUP_ZHAOXIN=y
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
 CONFIG_DMI=y
-CONFIG_NR_CPUS_RANGE_BEGIN=2
-CONFIG_NR_CPUS_RANGE_END=64
-CONFIG_NR_CPUS_DEFAULT=32
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
 CONFIG_NR_CPUS=16
 CONFIG_SCHED_SMT=y
 CONFIG_SCHED_MC=y
-CONFIG_SCHED_MC_PRIO=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
 CONFIG_X86_MCE=y
-# CONFIG_X86_MCELOG_LEGACY is not set
 CONFIG_X86_MCE_INTEL=y
 CONFIG_X86_MCE_AMD=y
 CONFIG_X86_ANCIENT_MCE=y
 CONFIG_X86_MCE_THRESHOLD=y
-
-#
-# Performance monitoring
-#
-CONFIG_PERF_EVENTS_INTEL_UNCORE=y
-CONFIG_PERF_EVENTS_INTEL_RAPL=y
-CONFIG_PERF_EVENTS_INTEL_CSTATE=y
-# CONFIG_PERF_EVENTS_AMD_POWER is not set
-# end of Performance monitoring
-
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_THERMAL_VECTOR=y
 # CONFIG_X86_LEGACY_VM86 is not set
+# CONFIG_VM86 is not set
 CONFIG_X86_16BIT=y
 CONFIG_X86_ESPFIX32=y
-CONFIG_X86_IOPL_IOPERM=y
 # CONFIG_TOSHIBA is not set
 # CONFIG_I8K is not set
@@ -398,4 +442,6 @@
 CONFIG_HIGHMEM=y
 CONFIG_X86_PAE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
 # CONFIG_NUMA is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
@@ -403,8 +449,51 @@
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ILLEGAL_POINTER_VALUE=0
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+CONFIG_MEMORY_BALLOON=y
+CONFIG_BALLOON_COMPACTION=y
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_MEMORY_FAILURE=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+# CONFIG_CMA is not set
+# CONFIG_ZSWAP is not set
+CONFIG_ZPOOL=m
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+# CONFIG_PGTABLE_MAPPING is not set
+# CONFIG_ZSMALLOC_STAT is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
 # CONFIG_X86_PMEM_LEGACY is not set
 CONFIG_HIGHPTE=y
 CONFIG_X86_CHECK_BIOS_CORRUPTION=y
 CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+CONFIG_X86_RESERVE_LOW=64
+# CONFIG_MATH_EMULATION is not set
 CONFIG_MTRR=y
 # CONFIG_MTRR_SANITIZER is not set
@@ -413,10 +502,8 @@
 CONFIG_ARCH_RANDOM=y
 CONFIG_X86_SMAP=y
-CONFIG_X86_UMIP=y
-CONFIG_X86_INTEL_TSX_MODE_OFF=y
-# CONFIG_X86_INTEL_TSX_MODE_ON is not set
-# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
+# CONFIG_X86_INTEL_MPX is not set
 CONFIG_EFI=y
 # CONFIG_EFI_STUB is not set
+CONFIG_SECCOMP=y
 CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
@@ -436,7 +523,5 @@
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_MODIFY_LDT_SYSCALL=y
-# end of Processor type and features
-
-CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 
 #
@@ -454,6 +539,4 @@
 CONFIG_PM_CLK=y
 # CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
-# CONFIG_ENERGY_MODEL is not set
-CONFIG_ARCH_SUPPORTS_ACPI=y
 CONFIG_ACPI=y
 CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
@@ -461,6 +544,6 @@
 CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
 # CONFIG_ACPI_DEBUGGER is not set
-CONFIG_ACPI_SPCR_TABLE=y
 CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS_POWER=y
 CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y
 # CONFIG_ACPI_EC_DEBUGFS is not set
@@ -468,20 +551,18 @@
 CONFIG_ACPI_BATTERY=m
 CONFIG_ACPI_BUTTON=m
-# CONFIG_ACPI_TINY_POWER_BUTTON is not set
 CONFIG_ACPI_FAN=m
-# CONFIG_ACPI_TAD is not set
 CONFIG_ACPI_DOCK=y
 CONFIG_ACPI_CPU_FREQ_PSS=y
-CONFIG_ACPI_PROCESSOR_CSTATE=y
 CONFIG_ACPI_PROCESSOR_IDLE=y
-CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_PROCESSOR=m
 CONFIG_ACPI_IPMI=m
 CONFIG_ACPI_HOTPLUG_CPU=y
 CONFIG_ACPI_PROCESSOR_AGGREGATOR=m
 CONFIG_ACPI_THERMAL=m
-CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
-CONFIG_ACPI_TABLE_UPGRADE=y
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_PCI_SLOT=y
+CONFIG_X86_PM_TIMER=y
 CONFIG_ACPI_CONTAINER=y
 CONFIG_ACPI_HOTPLUG_IOAPIC=y
@@ -489,12 +570,12 @@
 CONFIG_ACPI_HED=m
 # CONFIG_ACPI_BGRT is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+# CONFIG_ACPI_NFIT is not set
 CONFIG_HAVE_ACPI_APEI=y
 CONFIG_HAVE_ACPI_APEI_NMI=y
 # CONFIG_ACPI_APEI is not set
-# CONFIG_ACPI_DPTF is not set
 # CONFIG_ACPI_EXTLOG is not set
-# CONFIG_ACPI_CONFIGFS is not set
 # CONFIG_PMIC_OPREGION is not set
-CONFIG_X86_PM_TIMER=y
+# CONFIG_SFI is not set
 # CONFIG_APM is not set
 
@@ -503,11 +584,12 @@
 #
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_GOV_ATTR_SET=y
 CONFIG_CPU_FREQ_GOV_COMMON=y
-# CONFIG_CPU_FREQ_STAT is not set
+CONFIG_CPU_FREQ_STAT=m
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=m
@@ -515,5 +597,4 @@
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
 
 #
@@ -545,5 +626,4 @@
 CONFIG_X86_SPEEDSTEP_LIB=m
 # CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set
-# end of CPU Frequency scaling
 
 #
@@ -553,15 +633,11 @@
 CONFIG_CPU_IDLE_GOV_LADDER=y
 CONFIG_CPU_IDLE_GOV_MENU=y
-# CONFIG_CPU_IDLE_GOV_TEO is not set
-# CONFIG_CPU_IDLE_GOV_HALTPOLL is not set
-CONFIG_HALTPOLL_CPUIDLE=y
-# end of CPU Idle
-
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
 CONFIG_INTEL_IDLE=y
-# end of Power management and ACPI options
 
 #
 # Bus options (PCI etc.)
 #
+CONFIG_PCI=y
 # CONFIG_PCI_GOBIOS is not set
 # CONFIG_PCI_GOMMCONFIG is not set
@@ -571,4 +647,30 @@
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+CONFIG_PCI_BUS_ADDR_T_64BIT=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HT_IRQ=y
+CONFIG_PCI_ATS=y
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+CONFIG_PCI_PASID=y
+CONFIG_PCI_LABEL=y
+
+#
+# PCI host controller drivers
+#
 CONFIG_ISA_DMA_API=y
 # CONFIG_ISA is not set
@@ -578,338 +680,23 @@
 # CONFIG_GEOS is not set
 CONFIG_AMD_NB=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
 # CONFIG_X86_SYSFB is not set
-# end of Bus options (PCI etc.)
-
-#
-# Binary Emulations
-#
-CONFIG_COMPAT_32=y
-# end of Binary Emulations
-
-CONFIG_HAVE_ATOMIC_IOMAP=y
-
-#
-# Firmware Drivers
-#
-# CONFIG_EDD is not set
-CONFIG_FIRMWARE_MEMMAP=y
-CONFIG_DMIID=y
-# CONFIG_DMI_SYSFS is not set
-CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
-# CONFIG_ISCSI_IBFT is not set
-# CONFIG_FW_CFG_SYSFS is not set
-# CONFIG_GOOGLE_FIRMWARE is not set
-
-#
-# EFI (Extensible Firmware Interface) Support
-#
-# CONFIG_EFI_VARS is not set
-CONFIG_EFI_ESRT=y
-# CONFIG_EFI_RUNTIME_MAP is not set
-# CONFIG_EFI_FAKE_MEMMAP is not set
-CONFIG_EFI_RUNTIME_WRAPPERS=y
-# CONFIG_EFI_BOOTLOADER_CONTROL is not set
-CONFIG_EFI_CAPSULE_LOADER=y
-CONFIG_EFI_CAPSULE_QUIRK_QUARK_CSH=y
-# CONFIG_EFI_TEST is not set
-# CONFIG_EFI_RCI2_TABLE is not set
-# CONFIG_EFI_DISABLE_PCI_DMA is not set
-# end of EFI (Extensible Firmware Interface) Support
-
-CONFIG_EFI_EARLYCON=y
-CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
-
-#
-# Tegra firmware driver
-#
-# end of Tegra firmware driver
-# end of Firmware Drivers
-
-CONFIG_HAVE_KVM=y
-CONFIG_HAVE_KVM_IRQCHIP=y
-CONFIG_HAVE_KVM_IRQFD=y
-CONFIG_HAVE_KVM_IRQ_ROUTING=y
-CONFIG_HAVE_KVM_EVENTFD=y
-CONFIG_KVM_MMIO=y
-CONFIG_KVM_ASYNC_PF=y
-CONFIG_HAVE_KVM_MSI=y
-CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
-CONFIG_KVM_VFIO=y
-CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
-CONFIG_HAVE_KVM_IRQ_BYPASS=y
-CONFIG_HAVE_KVM_NO_POLL=y
-CONFIG_KVM_XFER_TO_GUEST_WORK=y
-CONFIG_HAVE_KVM_PM_NOTIFIER=y
-CONFIG_VIRTUALIZATION=y
-CONFIG_KVM=m
-CONFIG_KVM_INTEL=m
-CONFIG_KVM_AMD=m
-# CONFIG_KVM_XEN is not set
-CONFIG_AS_AVX512=y
-CONFIG_AS_SHA1_NI=y
-CONFIG_AS_SHA256_NI=y
-
-#
-# General architecture-dependent options
-#
-CONFIG_CRASH_CORE=y
-CONFIG_KEXEC_CORE=y
-CONFIG_HOTPLUG_SMT=y
-CONFIG_GENERIC_ENTRY=y
-# CONFIG_KPROBES is not set
-# CONFIG_JUMP_LABEL is not set
-# CONFIG_STATIC_CALL_SELFTEST is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_ARCH_USE_BUILTIN_BSWAP=y
-CONFIG_USER_RETURN_NOTIFIER=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_OPTPROBES=y
-CONFIG_HAVE_KPROBES_ON_FTRACE=y
-CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
-CONFIG_HAVE_NMI=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_GENERIC_SMP_IDLE_THREAD=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
-CONFIG_ARCH_WANTS_NO_INSTR=y
-CONFIG_ARCH_32BIT_OFF_T=y
-CONFIG_HAVE_ASM_MODVERSIONS=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
-CONFIG_HAVE_HW_BREAKPOINT=y
-CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
-CONFIG_HAVE_USER_RETURN_NOTIFIER=y
-CONFIG_HAVE_PERF_EVENTS_NMI=y
-CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
-CONFIG_MMU_GATHER_TABLE_FREE=y
-CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
-CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
-CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
-CONFIG_HAVE_CMPXCHG_LOCAL=y
-CONFIG_HAVE_CMPXCHG_DOUBLE=y
-CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
-CONFIG_HAVE_ARCH_SECCOMP=y
-CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
-CONFIG_SECCOMP=y
-CONFIG_SECCOMP_FILTER=y
-# CONFIG_SECCOMP_CACHE_DEBUG is not set
-CONFIG_HAVE_ARCH_STACKLEAK=y
-CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
-CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y
-CONFIG_LTO_NONE=y
-CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_MOVE_PUD=y
-CONFIG_HAVE_MOVE_PMD=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARCH_HUGE_VMAP=y
-CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_MODULES_USE_ELF_REL=y
-CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
-CONFIG_HAVE_EXIT_THREAD=y
-CONFIG_ARCH_MMAP_RND_BITS=8
-CONFIG_CLONE_BACKWARDS=y
-CONFIG_OLD_SIGSUSPEND3=y
-CONFIG_OLD_SIGACTION=y
-CONFIG_COMPAT_32BIT_TIME=y
-CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y
-# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
-CONFIG_ARCH_USE_MEMREMAP_PROT=y
-CONFIG_ARCH_HAS_MEM_ENCRYPT=y
-CONFIG_HAVE_STATIC_CALL=y
-CONFIG_HAVE_PREEMPT_DYNAMIC=y
-CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
-CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
-CONFIG_ARCH_SPLIT_ARG64=y
-
-#
-# GCOV-based kernel profiling
-#
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-# end of GCOV-based kernel profiling
-
-CONFIG_HAVE_GCC_PLUGINS=y
-CONFIG_GCC_PLUGINS=y
-# CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set
-# CONFIG_GCC_PLUGIN_RANDSTRUCT is not set
-# end of General architecture-dependent options
-
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_MODULE_SIG is not set
-CONFIG_MODULE_COMPRESS_NONE=y
-# CONFIG_MODULE_COMPRESS_GZIP is not set
-# CONFIG_MODULE_COMPRESS_XZ is not set
-# CONFIG_MODULE_COMPRESS_ZSTD is not set
-# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set
-CONFIG_MODPROBE_PATH="/sbin/modprobe"
-CONFIG_MODULES_TREE_LOOKUP=y
-CONFIG_BLOCK=y
-CONFIG_BLK_SCSI_REQUEST=y
-CONFIG_BLK_DEV_BSG=y
-CONFIG_BLK_DEV_BSGLIB=y
-CONFIG_BLK_DEV_INTEGRITY=y
-CONFIG_BLK_DEV_INTEGRITY_T10=m
-# CONFIG_BLK_DEV_ZONED is not set
-# CONFIG_BLK_CMDLINE_PARSER is not set
-CONFIG_BLK_WBT=y
-CONFIG_BLK_WBT_MQ=y
-# CONFIG_BLK_SED_OPAL is not set
-# CONFIG_BLK_INLINE_ENCRYPTION is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_AIX_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-CONFIG_EFI_PARTITION=y
-# CONFIG_SYSV68_PARTITION is not set
-# CONFIG_CMDLINE_PARTITION is not set
-# end of Partition Types
-
-CONFIG_BLK_MQ_PCI=y
-CONFIG_BLK_MQ_VIRTIO=y
-CONFIG_BLK_PM=y
-
-#
-# IO Schedulers
-#
-CONFIG_MQ_IOSCHED_DEADLINE=y
-CONFIG_MQ_IOSCHED_KYBER=y
-# CONFIG_IOSCHED_BFQ is not set
-# end of IO Schedulers
-
-CONFIG_PREEMPT_NOTIFIERS=y
-CONFIG_PADATA=y
-CONFIG_ASN1=m
-CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
-CONFIG_INLINE_READ_UNLOCK=y
-CONFIG_INLINE_READ_UNLOCK_IRQ=y
-CONFIG_INLINE_WRITE_UNLOCK=y
-CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_MUTEX_SPIN_ON_OWNER=y
-CONFIG_RWSEM_SPIN_ON_OWNER=y
-CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
-CONFIG_QUEUED_SPINLOCKS=y
-CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
-CONFIG_QUEUED_RWLOCKS=y
-CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
-CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
-CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
-CONFIG_FREEZER=y
-
-#
-# Executable file formats
+
+#
+# Executable file formats / Emulations
 #
 CONFIG_BINFMT_ELF=y
-CONFIG_ELFCORE=y
 CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
 CONFIG_BINFMT_SCRIPT=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_MISC=y
 CONFIG_COREDUMP=y
-# end of Executable file formats
-
-#
-# Memory Management options
-#
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_SPARSEMEM_STATIC=y
-CONFIG_HAVE_FAST_GUP=y
-CONFIG_MEMORY_ISOLATION=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
-CONFIG_MEMORY_BALLOON=y
-CONFIG_BALLOON_COMPACTION=y
-CONFIG_COMPACTION=y
-CONFIG_PAGE_REPORTING=y
-CONFIG_MIGRATION=y
-CONFIG_CONTIG_ALLOC=y
-CONFIG_PHYS_ADDR_T_64BIT=y
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_MMU_NOTIFIER=y
-CONFIG_KSM=y
-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
-CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
-CONFIG_MEMORY_FAILURE=y
-CONFIG_TRANSPARENT_HUGEPAGE=y
-CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
-# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
-CONFIG_CLEANCACHE=y
-CONFIG_FRONTSWAP=y
-# CONFIG_CMA is not set
-# CONFIG_ZSWAP is not set
-CONFIG_ZPOOL=m
-CONFIG_ZBUD=m
-# CONFIG_Z3FOLD is not set
-CONFIG_ZSMALLOC=m
-# CONFIG_ZSMALLOC_STAT is not set
-CONFIG_GENERIC_EARLY_IOREMAP=y
-# CONFIG_IDLE_PAGE_TRACKING is not set
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_ZONE_DMA=y
-# CONFIG_PERCPU_STATS is not set
-
-#
-# GUP_TEST needs to have DEBUG_FS enabled
-#
-CONFIG_GUP_GET_PTE_LOW_HIGH=y
-# CONFIG_READ_ONLY_THP_FOR_FS is not set
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
-CONFIG_KMAP_LOCAL=y
-CONFIG_SECRETMEM=y
-# end of Memory Management options
-
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_PMC_ATOM=y
 CONFIG_NET=y
 CONFIG_NET_INGRESS=y
-CONFIG_NET_EGRESS=y
-CONFIG_NET_REDIRECT=y
-CONFIG_SKB_EXTENSIONS=y
 
 #
@@ -919,16 +706,11 @@
 CONFIG_PACKET_DIAG=m
 CONFIG_UNIX=y
-CONFIG_UNIX_SCM=y
 CONFIG_UNIX_DIAG=m
-# CONFIG_TLS is not set
 CONFIG_XFRM=y
 CONFIG_XFRM_ALGO=m
 CONFIG_XFRM_USER=m
-# CONFIG_XFRM_INTERFACE is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
 # CONFIG_XFRM_STATISTICS is not set
-CONFIG_XFRM_AH=m
-CONFIG_XFRM_ESP=m
 CONFIG_XFRM_IPCOMP=m
 CONFIG_NET_KEY=m
@@ -948,5 +730,4 @@
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE_COMMON=y
 CONFIG_IP_MROUTE=y
 # CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
@@ -960,14 +741,14 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
-# CONFIG_INET_ESP_OFFLOAD is not set
-# CONFIG_INET_ESPINTCP is not set
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_INET_UDP_DIAG is not set
-# CONFIG_INET_RAW_DIAG is not set
-# CONFIG_INET_DIAG_DESTROY is not set
 CONFIG_TCP_CONG_ADVANCED=y
 CONFIG_TCP_CONG_BIC=y
@@ -978,5 +759,4 @@
 CONFIG_TCP_CONG_HYBLA=y
 CONFIG_TCP_CONG_VEGAS=y
-# CONFIG_TCP_CONG_NV is not set
 CONFIG_TCP_CONG_SCALABLE=y
 CONFIG_TCP_CONG_LP=y
@@ -986,5 +766,4 @@
 # CONFIG_TCP_CONG_DCTCP is not set
 # CONFIG_TCP_CONG_CDG is not set
-# CONFIG_TCP_CONG_BBR is not set
 # CONFIG_DEFAULT_BIC is not set
 CONFIG_DEFAULT_CUBIC=y
@@ -1003,6 +782,4 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
-# CONFIG_INET6_ESP_OFFLOAD is not set
-# CONFIG_INET6_ESPINTCP is not set
 CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
@@ -1010,4 +787,8 @@
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
 # CONFIG_IPV6_VTI is not set
 CONFIG_IPV6_SIT=y
@@ -1021,12 +802,9 @@
 # CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set
 CONFIG_IPV6_PIMSM_V2=y
-# CONFIG_IPV6_SEG6_LWTUNNEL is not set
-# CONFIG_IPV6_SEG6_HMAC is not set
-# CONFIG_IPV6_RPL_LWTUNNEL is not set
-# CONFIG_MPTCP is not set
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NET_PTP_CLASSIFY=y
 # CONFIG_NETWORK_PHY_TIMESTAMPING is not set
 CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
 CONFIG_NETFILTER_ADVANCED=y
 CONFIG_BRIDGE_NETFILTER=m
@@ -1037,13 +815,9 @@
 CONFIG_NETFILTER_INGRESS=y
 CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_FAMILY_BRIDGE=y
-CONFIG_NETFILTER_FAMILY_ARP=y
 CONFIG_NETFILTER_NETLINK_ACCT=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NETFILTER_NETLINK_OSF=m
 CONFIG_NF_CONNTRACK=m
-CONFIG_NF_LOG_SYSLOG=m
-CONFIG_NETFILTER_CONNCOUNT=m
+CONFIG_NF_LOG_COMMON=m
 CONFIG_NF_CONNTRACK_MARK=y
 CONFIG_NF_CONNTRACK_SECMARK=y
@@ -1053,9 +827,8 @@
 # CONFIG_NF_CONNTRACK_TIMEOUT is not set
 # CONFIG_NF_CONNTRACK_TIMESTAMP is not set
-# CONFIG_NF_CONNTRACK_LABELS is not set
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_GRE=y
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
@@ -1070,6 +843,11 @@
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
 # CONFIG_NETFILTER_NETLINK_GLUE_CT is not set
 CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
 CONFIG_NF_NAT_AMANDA=m
 CONFIG_NF_NAT_FTP=m
@@ -1077,6 +855,5 @@
 CONFIG_NF_NAT_SIP=m
 CONFIG_NF_NAT_TFTP=m
-CONFIG_NF_NAT_REDIRECT=y
-CONFIG_NF_NAT_MASQUERADE=y
+CONFIG_NF_NAT_REDIRECT=m
 CONFIG_NETFILTER_SYNPROXY=m
 # CONFIG_NF_TABLES is not set
@@ -1088,5 +865,4 @@
 CONFIG_NETFILTER_XT_MARK=m
 CONFIG_NETFILTER_XT_CONNMARK=m
-CONFIG_NETFILTER_XT_SET=m
 
 #
@@ -1103,4 +879,5 @@
 # CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
 CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_IMQ=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_NAT=m
@@ -1111,5 +888,4 @@
 CONFIG_NETFILTER_XT_TARGET_RATEEST=m
 CONFIG_NETFILTER_XT_TARGET_REDIRECT=m
-CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
 # CONFIG_NETFILTER_XT_TARGET_TPROXY is not set
@@ -1160,5 +936,5 @@
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
-# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
@@ -1167,24 +943,5 @@
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
-# end of Core Netfilter Configuration
-
-CONFIG_IP_SET=m
-CONFIG_IP_SET_MAX=256
-CONFIG_IP_SET_BITMAP_IP=m
-CONFIG_IP_SET_BITMAP_IPMAC=m
-CONFIG_IP_SET_BITMAP_PORT=m
-CONFIG_IP_SET_HASH_IP=m
-CONFIG_IP_SET_HASH_IPMARK=m
-CONFIG_IP_SET_HASH_IPPORT=m
-CONFIG_IP_SET_HASH_IPPORTIP=m
-CONFIG_IP_SET_HASH_IPPORTNET=m
-# CONFIG_IP_SET_HASH_IPMAC is not set
-CONFIG_IP_SET_HASH_MAC=m
-CONFIG_IP_SET_HASH_NETPORTNET=m
-CONFIG_IP_SET_HASH_NET=m
-CONFIG_IP_SET_HASH_NETNET=m
-CONFIG_IP_SET_HASH_NETPORT=m
-CONFIG_IP_SET_HASH_NETIFACE=m
-CONFIG_IP_SET_LIST_SET=m
+# CONFIG_IP_SET is not set
 # CONFIG_IP_VS is not set
 
@@ -1193,10 +950,13 @@
 #
 CONFIG_NF_DEFRAG_IPV4=m
-# CONFIG_NF_SOCKET_IPV4 is not set
-# CONFIG_NF_TPROXY_IPV4 is not set
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
 CONFIG_NF_DUP_IPV4=m
 # CONFIG_NF_LOG_ARP is not set
 CONFIG_NF_LOG_IPV4=m
 CONFIG_NF_REJECT_IPV4=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_NF_NAT_MASQUERADE_IPV4=m
+CONFIG_NF_NAT_PROTO_GRE=m
 CONFIG_NF_NAT_PPTP=m
 CONFIG_NF_NAT_H323=m
@@ -1221,14 +981,15 @@
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-# end of IP: Netfilter Configuration
 
 #
 # IPv6: Netfilter Configuration
 #
-# CONFIG_NF_SOCKET_IPV6 is not set
-# CONFIG_NF_TPROXY_IPV6 is not set
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NF_DUP_IPV6=m
 CONFIG_NF_REJECT_IPV6=m
 CONFIG_NF_LOG_IPV6=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_NF_NAT_MASQUERADE_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
@@ -1241,5 +1002,4 @@
 CONFIG_IP6_NF_MATCH_RPFILTER=m
 CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_MATCH_SRH is not set
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
@@ -1251,8 +1011,4 @@
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
-# end of IPv6: Netfilter Configuration
-
-CONFIG_NF_DEFRAG_IPV6=m
-# CONFIG_NF_CONNTRACK_BRIDGE is not set
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
@@ -1276,5 +1032,4 @@
 CONFIG_BRIDGE_EBT_LOG=m
 CONFIG_BRIDGE_EBT_NFLOG=m
-# CONFIG_BPFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
@@ -1289,7 +1044,5 @@
 CONFIG_BRIDGE_IGMP_SNOOPING=y
 CONFIG_BRIDGE_VLAN_FILTERING=y
-# CONFIG_BRIDGE_MRP is not set
-# CONFIG_BRIDGE_CFM is not set
-# CONFIG_NET_DSA is not set
+CONFIG_HAVE_NET_DSA=y
 CONFIG_VLAN_8021Q=m
 # CONFIG_VLAN_8021Q_GVRP is not set
@@ -1298,4 +1051,5 @@
 CONFIG_LLC=m
 # CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
@@ -1319,7 +1073,4 @@
 CONFIG_NET_SCH_TEQL=m
 CONFIG_NET_SCH_TBF=m
-# CONFIG_NET_SCH_CBS is not set
-# CONFIG_NET_SCH_ETF is not set
-# CONFIG_NET_SCH_TAPRIO is not set
 CONFIG_NET_SCH_GRED=m
 CONFIG_NET_SCH_DSMARK=m
@@ -1327,18 +1078,13 @@
 CONFIG_NET_SCH_DRR=m
 CONFIG_NET_SCH_MQPRIO=m
-# CONFIG_NET_SCH_SKBPRIO is not set
 CONFIG_NET_SCH_CHOKE=m
 CONFIG_NET_SCH_QFQ=m
 CONFIG_NET_SCH_CODEL=m
 CONFIG_NET_SCH_FQ_CODEL=m
-# CONFIG_NET_SCH_CAKE is not set
 CONFIG_NET_SCH_FQ=m
 CONFIG_NET_SCH_HHF=m
 CONFIG_NET_SCH_PIE=m
-# CONFIG_NET_SCH_FQ_PIE is not set
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_SCH_PLUG=m
-# CONFIG_NET_SCH_ETS is not set
-# CONFIG_NET_SCH_DEFAULT is not set
 
 #
@@ -1359,5 +1105,4 @@
 CONFIG_NET_CLS_BPF=m
 # CONFIG_NET_CLS_FLOWER is not set
-# CONFIG_NET_CLS_MATCHALL is not set
 CONFIG_NET_EMATCH=y
 CONFIG_NET_EMATCH_STACK=32
@@ -1367,6 +1112,4 @@
 CONFIG_NET_EMATCH_META=m
 CONFIG_NET_EMATCH_TEXT=m
-# CONFIG_NET_EMATCH_IPSET is not set
-# CONFIG_NET_EMATCH_IPT is not set
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
@@ -1374,5 +1117,4 @@
 CONFIG_GACT_PROB=y
 CONFIG_NET_ACT_MIRRED=m
-# CONFIG_NET_ACT_SAMPLE is not set
 CONFIG_NET_ACT_IPT=m
 # CONFIG_NET_ACT_NAT is not set
@@ -1381,14 +1123,8 @@
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
-# CONFIG_NET_ACT_MPLS is not set
 # CONFIG_NET_ACT_VLAN is not set
 # CONFIG_NET_ACT_BPF is not set
 CONFIG_NET_ACT_CONNMARK=m
-# CONFIG_NET_ACT_CTINFO is not set
-# CONFIG_NET_ACT_SKBMOD is not set
-# CONFIG_NET_ACT_IFE is not set
-# CONFIG_NET_ACT_TUNNEL_KEY is not set
-# CONFIG_NET_ACT_GATE is not set
-# CONFIG_NET_TC_SKB_EXT is not set
+CONFIG_NET_CLS_IND=y
 CONFIG_NET_SCH_FIFO=y
 # CONFIG_DCB is not set
@@ -1399,24 +1135,15 @@
 CONFIG_OPENVSWITCH_VXLAN=m
 CONFIG_VSOCKETS=m
-CONFIG_VSOCKETS_DIAG=m
-CONFIG_VSOCKETS_LOOPBACK=m
 CONFIG_VMWARE_VMCI_VSOCKETS=m
-# CONFIG_VIRTIO_VSOCKETS is not set
-CONFIG_VIRTIO_VSOCKETS_COMMON=m
-# CONFIG_HYPERV_VSOCKETS is not set
+CONFIG_NETLINK_MMAP=y
 # CONFIG_NETLINK_DIAG is not set
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_MPLS_ROUTING is not set
-CONFIG_NET_NSH=m
 CONFIG_HSR=m
 # CONFIG_NET_SWITCHDEV is not set
 # CONFIG_NET_L3_MASTER_DEV is not set
-# CONFIG_QRTR is not set
-# CONFIG_NET_NCSI is not set
-CONFIG_PCPU_DEV_REFCNT=y
 CONFIG_RPS=y
 CONFIG_RFS_ACCEL=y
-CONFIG_SOCK_RX_QUEUE_MAPPING=y
 CONFIG_XPS=y
 # CONFIG_CGROUP_NET_PRIO is not set
@@ -1430,15 +1157,13 @@
 #
 # CONFIG_NET_PKTGEN is not set
-# end of Network testing
-# end of Networking options
-
 # CONFIG_HAMRADIO is not set
 # CONFIG_CAN is not set
+# CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_AF_KCM is not set
 CONFIG_FIB_RULES=y
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
 
 #
@@ -1446,4 +1171,5 @@
 #
 CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -1451,89 +1177,13 @@
 # CONFIG_CEPH_LIB is not set
 # CONFIG_NFC is not set
-# CONFIG_PSAMPLE is not set
-# CONFIG_NET_IFE is not set
 # CONFIG_LWTUNNEL is not set
-CONFIG_DST_CACHE=y
-CONFIG_GRO_CELLS=y
-CONFIG_NET_SELFTESTS=m
-CONFIG_NET_DEVLINK=y
-CONFIG_PAGE_POOL=y
-CONFIG_FAILOVER=m
-CONFIG_ETHTOOL_NETLINK=y
 
 #
 # Device Drivers
 #
-CONFIG_HAVE_EISA=y
-# CONFIG_EISA is not set
-CONFIG_HAVE_PCI=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCIEAER=y
-# CONFIG_PCIEAER_INJECT is not set
-# CONFIG_PCIE_ECRC is not set
-CONFIG_PCIEASPM=y
-CONFIG_PCIEASPM_DEFAULT=y
-# CONFIG_PCIEASPM_POWERSAVE is not set
-# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
-# CONFIG_PCIEASPM_PERFORMANCE is not set
-CONFIG_PCIE_PME=y
-# CONFIG_PCIE_DPC is not set
-# CONFIG_PCIE_PTM is not set
-CONFIG_PCI_MSI=y
-CONFIG_PCI_MSI_IRQ_DOMAIN=y
-CONFIG_PCI_QUIRKS=y
-# CONFIG_PCI_STUB is not set
-CONFIG_PCI_ATS=y
-CONFIG_PCI_LOCKLESS_CONFIG=y
-# CONFIG_PCI_IOV is not set
-# CONFIG_PCI_PRI is not set
-CONFIG_PCI_PASID=y
-CONFIG_PCI_LABEL=y
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# PCI controller drivers
-#
-
-#
-# DesignWare PCI Core Support
-#
-# CONFIG_PCIE_DW_PLAT_HOST is not set
-# CONFIG_PCI_MESON is not set
-# end of DesignWare PCI Core Support
-
-#
-# Mobiveil PCIe Core Support
-#
-# end of Mobiveil PCIe Core Support
-
-#
-# Cadence PCIe controllers support
-#
-# end of Cadence PCIe controllers support
-# end of PCI controller drivers
-
-#
-# PCI Endpoint
-#
-# CONFIG_PCI_ENDPOINT is not set
-# end of PCI Endpoint
-
-#
-# PCI switch controller drivers
-#
-# CONFIG_PCI_SW_SWITCHTEC is not set
-# end of PCI switch controller drivers
-
-# CONFIG_CXL_BUS is not set
-# CONFIG_PCCARD is not set
-# CONFIG_RAPIDIO is not set
 
 #
 # Generic Driver Options
 #
-CONFIG_AUXILIARY_BUS=y
 CONFIG_UEVENT_HELPER=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -1542,45 +1192,29 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-
-#
-# Firmware loader
-#
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
 CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_FW_LOADER_USER_HELPER is not set
-# CONFIG_FW_LOADER_COMPRESS is not set
-CONFIG_FW_CACHE=y
-# end of Firmware loader
-
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
 CONFIG_ALLOW_DEV_COREDUMP=y
-# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
 CONFIG_GENERIC_CPU_AUTOPROBE=y
-CONFIG_GENERIC_CPU_VULNERABILITIES=y
 CONFIG_REGMAP=y
 CONFIG_REGMAP_I2C=m
 CONFIG_REGMAP_MMIO=y
-# end of Generic Driver Options
+# CONFIG_DMA_SHARED_BUFFER is not set
 
 #
 # Bus devices
 #
-# CONFIG_MHI_BUS is not set
-# end of Bus devices
-
 CONFIG_CONNECTOR=m
-# CONFIG_GNSS is not set
 CONFIG_MTD=m
 # CONFIG_MTD_TESTS is not set
-
-#
-# Partition parsers
-#
-CONFIG_MTD_AR7_PARTS=m
-# CONFIG_MTD_CMDLINE_PARTS is not set
 CONFIG_MTD_REDBOOT_PARTS=m
 CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
 # CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
 # CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
-# end of Partition parsers
+# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_AR7_PARTS=m
 
 #
@@ -1611,6 +1245,11 @@
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
 CONFIG_MTD_CFI_I1=y
 CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=m
 CONFIG_MTD_CFI_AMDSTD=m
@@ -1620,5 +1259,4 @@
 CONFIG_MTD_ROM=m
 CONFIG_MTD_ABSENT=m
-# end of RAM/ROM/Flash chip drivers
 
 #
@@ -1637,5 +1275,4 @@
 CONFIG_MTD_INTEL_VR_NOR=m
 CONFIG_MTD_PLATRAM=m
-# end of Mapping drivers for chip access
 
 #
@@ -1656,10 +1293,22 @@
 CONFIG_BCH_CONST_M=14
 CONFIG_BCH_CONST_T=4
-# end of Self-contained MTD device drivers
-
-#
-# NAND
-#
-CONFIG_MTD_NAND_CORE=m
+CONFIG_MTD_NAND_ECC=m
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_PCI is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_RICOH is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_CS553X is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
 CONFIG_MTD_ONENAND=m
 # CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
@@ -1667,15 +1316,4 @@
 # CONFIG_MTD_ONENAND_OTP is not set
 # CONFIG_MTD_ONENAND_2X_PROGRAM is not set
-# CONFIG_MTD_RAW_NAND is not set
-
-#
-# ECC engine support
-#
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_NAND_ECC_SW_HAMMING=y
-# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set
-# CONFIG_MTD_NAND_ECC_SW_BCH is not set
-# end of ECC engine support
-# end of NAND
 
 #
@@ -1684,6 +1322,6 @@
 CONFIG_MTD_LPDDR=m
 CONFIG_MTD_QINFO_PROBE=m
-# end of LPDDR & LPDDR2 PCM memory drivers
-
+CONFIG_MTD_SPI_NOR=m
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
 CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_WL_THRESHOLD=4096
@@ -1692,5 +1330,4 @@
 # CONFIG_MTD_UBI_GLUEBI is not set
 # CONFIG_MTD_UBI_BLOCK is not set
-# CONFIG_MTD_HYPERBUS is not set
 # CONFIG_OF is not set
 CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
@@ -1706,19 +1343,16 @@
 # CONFIG_BLK_DEV_NULL_BLK is not set
 # CONFIG_BLK_DEV_FD is not set
-CONFIG_CDROM=m
 CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
 CONFIG_ZRAM=m
-CONFIG_ZRAM_DEF_COMP_LZORLE=y
-# CONFIG_ZRAM_DEF_COMP_LZ4 is not set
-# CONFIG_ZRAM_DEF_COMP_LZO is not set
-# CONFIG_ZRAM_DEF_COMP_LZ4HC is not set
-# CONFIG_ZRAM_DEF_COMP_842 is not set
-CONFIG_ZRAM_DEF_COMP="lzo-rle"
-# CONFIG_ZRAM_WRITEBACK is not set
+CONFIG_ZRAM_LZ4_COMPRESS=y
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
 CONFIG_BLK_DEV_CRYPTOLOOP=y
-CONFIG_BLK_DEV_DRBD=m
-# CONFIG_DRBD_FAULT_INJECTION is not set
+# CONFIG_BLK_DEV_DRBD is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_SX8=m
@@ -1729,26 +1363,18 @@
 CONFIG_ATA_OVER_ETH=m
 CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
 # CONFIG_BLK_DEV_RBD is not set
 CONFIG_BLK_DEV_RSXX=m
-
-#
-# NVME Support
-#
-CONFIG_NVME_CORE=m
 CONFIG_BLK_DEV_NVME=m
-# CONFIG_NVME_MULTIPATH is not set
-# CONFIG_NVME_HWMON is not set
-# CONFIG_NVME_FC is not set
-# CONFIG_NVME_TCP is not set
-# CONFIG_NVME_TARGET is not set
-# end of NVME Support
 
 #
 # Misc devices
 #
+# CONFIG_SENSORS_LIS3LV02D is not set
 # CONFIG_AD525X_DPOT is not set
 # CONFIG_DUMMY_IRQ is not set
 # CONFIG_IBM_ASM is not set
 # CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
 # CONFIG_ICS932S401 is not set
@@ -1759,4 +1385,5 @@
 # CONFIG_ISL29020 is not set
 # CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
 # CONFIG_SENSORS_BH1770 is not set
 # CONFIG_SENSORS_APDS990X is not set
@@ -1764,9 +1391,8 @@
 # CONFIG_DS1682 is not set
 CONFIG_VMWARE_BALLOON=m
+# CONFIG_BMP085_I2C is not set
 # CONFIG_PCH_PHUB is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
 # CONFIG_SRAM is not set
-# CONFIG_DW_XDATA_PCIE is not set
-# CONFIG_PCI_ENDPOINT_TEST is not set
-# CONFIG_XILINX_SDFEC is not set
 # CONFIG_C2PORT is not set
 
@@ -1777,9 +1403,5 @@
 # CONFIG_EEPROM_LEGACY is not set
 # CONFIG_EEPROM_MAX6875 is not set
-CONFIG_EEPROM_93CX6=m
-# CONFIG_EEPROM_IDT_89HPESX is not set
-# CONFIG_EEPROM_EE1004 is not set
-# end of EEPROM support
-
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_CB710_CORE is not set
 
@@ -1788,25 +1410,107 @@
 #
 # CONFIG_TI_ST is not set
-# end of Texas Instruments shared transport line discipline
-
 # CONFIG_SENSORS_LIS3_I2C is not set
 
 #
-# Altera FPGA firmware download module (requires I2C)
+# Altera FPGA firmware download module
 #
 # CONFIG_ALTERA_STAPL is not set
-# CONFIG_INTEL_MEI is not set
-# CONFIG_INTEL_MEI_ME is not set
-# CONFIG_INTEL_MEI_TXE is not set
 CONFIG_VMWARE_VMCI=m
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
 # CONFIG_ECHO is not set
-# CONFIG_BCM_VK is not set
-# CONFIG_MISC_ALCOR_PCI is not set
-# CONFIG_MISC_RTSX_PCI is not set
-# CONFIG_MISC_RTSX_USB is not set
-# CONFIG_HABANA_AI is not set
-# CONFIG_UACCE is not set
-# CONFIG_PVPANIC is not set
-# end of Misc devices
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEACPI=y
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_PLATFORM=m
+CONFIG_BLK_DEV_CMD640=y
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=y
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=m
+CONFIG_BLK_DEV_OPTI621=m
+CONFIG_BLK_DEV_RZ1000=m
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_AEC62XX=m
+CONFIG_BLK_DEV_ALI15X3=m
+CONFIG_BLK_DEV_AMD74XX=m
+CONFIG_BLK_DEV_ATIIXP=m
+CONFIG_BLK_DEV_CMD64X=m
+CONFIG_BLK_DEV_TRIFLEX=m
+# CONFIG_BLK_DEV_CS5520 is not set
+CONFIG_BLK_DEV_CS5530=m
+CONFIG_BLK_DEV_CS5535=m
+CONFIG_BLK_DEV_CS5536=m
+CONFIG_BLK_DEV_HPT366=m
+CONFIG_BLK_DEV_JMICRON=m
+CONFIG_BLK_DEV_SC1200=m
+CONFIG_BLK_DEV_PIIX=m
+CONFIG_BLK_DEV_IT8172=m
+CONFIG_BLK_DEV_IT8213=m
+CONFIG_BLK_DEV_IT821X=m
+CONFIG_BLK_DEV_NS87415=m
+CONFIG_BLK_DEV_PDC202XX_OLD=m
+CONFIG_BLK_DEV_PDC202XX_NEW=m
+CONFIG_BLK_DEV_SVWKS=m
+CONFIG_BLK_DEV_SIIMAGE=m
+CONFIG_BLK_DEV_SIS5513=m
+CONFIG_BLK_DEV_SLC90E66=m
+CONFIG_BLK_DEV_TRM290=m
+CONFIG_BLK_DEV_VIA82CXXX=m
+CONFIG_BLK_DEV_TC86C001=m
+CONFIG_BLK_DEV_IDEDMA=y
 
 #
@@ -1818,4 +1522,5 @@
 CONFIG_SCSI_DMA=y
 CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
 CONFIG_SCSI_PROC_FS=y
 
@@ -1825,5 +1530,7 @@
 CONFIG_BLK_DEV_SD=m
 CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_CHR_DEV_SCH=m
@@ -1843,6 +1550,4 @@
 CONFIG_SCSI_SAS_HOST_SMP=y
 # CONFIG_SCSI_SRP_ATTRS is not set
-# end of SCSI Transports
-
 CONFIG_SCSI_LOWLEVEL=y
 CONFIG_ISCSI_TCP=m
@@ -1890,18 +1595,10 @@
 CONFIG_SCSI_MPT3SAS_MAX_SGE=128
 CONFIG_SCSI_MPT2SAS=m
-# CONFIG_SCSI_MPI3MR is not set
-# CONFIG_SCSI_SMARTPQI is not set
 CONFIG_SCSI_UFSHCD=m
 CONFIG_SCSI_UFSHCD_PCI=m
-# CONFIG_SCSI_UFS_DWC_TC_PCI is not set
 CONFIG_SCSI_UFSHCD_PLATFORM=m
-# CONFIG_SCSI_UFS_CDNS_PLATFORM is not set
-# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_BSG is not set
 CONFIG_SCSI_HPTIOP=m
 CONFIG_SCSI_BUSLOGIC=m
 # CONFIG_SCSI_FLASHPOINT is not set
-# CONFIG_SCSI_MYRB is not set
-# CONFIG_SCSI_MYRS is not set
 CONFIG_VMWARE_PVSCSI=m
 CONFIG_HYPERV_STORAGE=m
@@ -1912,5 +1609,10 @@
 # CONFIG_SCSI_SNIC is not set
 CONFIG_SCSI_DMX3191D=m
-# CONFIG_SCSI_FDOMAIN_PCI is not set
+CONFIG_SCSI_EATA=m
+CONFIG_SCSI_EATA_TAGGED_QUEUE=y
+CONFIG_SCSI_EATA_LINKED_COMMANDS=y
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
 CONFIG_SCSI_ISCI=m
 CONFIG_SCSI_IPS=m
@@ -1929,6 +1631,4 @@
 CONFIG_SCSI_QLA_FC=m
 CONFIG_SCSI_QLA_ISCSI=m
-# CONFIG_QEDI is not set
-# CONFIG_QEDF is not set
 CONFIG_SCSI_LPFC=m
 CONFIG_SCSI_DC395x=m
@@ -1943,11 +1643,8 @@
 CONFIG_SCSI_CHELSIO_FCOE=m
 # CONFIG_SCSI_DH is not set
-# end of SCSI device support
-
+# CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=m
-CONFIG_SATA_HOST=y
-CONFIG_PATA_TIMINGS=y
+# CONFIG_ATA_NONSTANDARD is not set
 CONFIG_ATA_VERBOSE_ERROR=y
-CONFIG_ATA_FORCE=y
 CONFIG_ATA_ACPI=y
 # CONFIG_SATA_ZPODD is not set
@@ -1958,5 +1655,4 @@
 #
 CONFIG_SATA_AHCI=m
-CONFIG_SATA_MOBILE_LPM_POLICY=0
 CONFIG_SATA_AHCI_PLATFORM=m
 CONFIG_SATA_INIC162X=m
@@ -1977,7 +1673,4 @@
 #
 CONFIG_ATA_PIIX=m
-CONFIG_SATA_DWC=m
-# CONFIG_SATA_DWC_OLD_DMA is not set
-# CONFIG_SATA_DWC_DEBUG is not set
 CONFIG_SATA_MV=m
 CONFIG_SATA_NV=m
@@ -2047,5 +1740,5 @@
 CONFIG_PATA_ACPI=m
 CONFIG_ATA_GENERIC=m
-CONFIG_PATA_LEGACY=m
+# CONFIG_PATA_LEGACY is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
@@ -2060,22 +1753,20 @@
 # CONFIG_BCACHE_DEBUG is not set
 # CONFIG_BCACHE_CLOSURES_DEBUG is not set
-# CONFIG_BCACHE_ASYNC_REGISTRATION is not set
 CONFIG_BLK_DEV_DM_BUILTIN=y
 CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_MQ_DEFAULT is not set
 # CONFIG_DM_DEBUG is not set
 CONFIG_DM_BUFIO=m
-# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
 CONFIG_DM_BIO_PRISON=m
 CONFIG_DM_PERSISTENT_DATA=m
-# CONFIG_DM_UNSTRIPED is not set
+# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 # CONFIG_DM_THIN_PROVISIONING is not set
 CONFIG_DM_CACHE=m
+CONFIG_DM_CACHE_MQ=m
 CONFIG_DM_CACHE_SMQ=m
-# CONFIG_DM_WRITECACHE is not set
-# CONFIG_DM_EBS is not set
+CONFIG_DM_CACHE_CLEANER=m
 # CONFIG_DM_ERA is not set
-# CONFIG_DM_CLONE is not set
 CONFIG_DM_MIRROR=m
 # CONFIG_DM_LOG_USERSPACE is not set
@@ -2085,8 +1776,5 @@
 CONFIG_DM_MULTIPATH_QL=m
 CONFIG_DM_MULTIPATH_ST=m
-# CONFIG_DM_MULTIPATH_HST is not set
-# CONFIG_DM_MULTIPATH_IOA is not set
 # CONFIG_DM_DELAY is not set
-# CONFIG_DM_DUST is not set
 CONFIG_DM_UEVENT=y
 # CONFIG_DM_FLAKEY is not set
@@ -2094,5 +1782,4 @@
 CONFIG_DM_SWITCH=m
 # CONFIG_DM_LOG_WRITES is not set
-# CONFIG_DM_INTEGRITY is not set
 # CONFIG_TARGET_CORE is not set
 CONFIG_FUSION=y
@@ -2109,6 +1796,4 @@
 # CONFIG_FIREWIRE is not set
 # CONFIG_FIREWIRE_NOSY is not set
-# end of IEEE 1394 (FireWire) support
-
 CONFIG_MACINTOSH_DRIVERS=y
 # CONFIG_MAC_EMUMOUSEBTN is not set
@@ -2118,6 +1803,4 @@
 CONFIG_BONDING=m
 CONFIG_DUMMY=m
-CONFIG_WIREGUARD=m
-# CONFIG_WIREGUARD_DEBUG is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_NET_FC is not set
@@ -2129,8 +1812,13 @@
 CONFIG_VXLAN=m
 # CONFIG_GENEVE is not set
-# CONFIG_BAREUDP is not set
-# CONFIG_GTP is not set
-# CONFIG_MACSEC is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_IMQ=m
+# CONFIG_IMQ_BEHAVIOR_AA is not set
+CONFIG_IMQ_BEHAVIOR_AB=y
+# CONFIG_IMQ_BEHAVIOR_BA is not set
+# CONFIG_IMQ_BEHAVIOR_BB is not set
+CONFIG_IMQ_NUM_DEVS=4
 CONFIG_TUN=m
 # CONFIG_TUN_VNET_CROSS_LE is not set
@@ -2140,4 +1828,18 @@
 CONFIG_SUNGEM_PHY=m
 # CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_RING=m
+CONFIG_VHOST=m
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
 CONFIG_ETHERNET=y
 CONFIG_MDIO=m
@@ -2149,18 +1851,11 @@
 CONFIG_NET_VENDOR_AGERE=y
 CONFIG_ET131X=m
-CONFIG_NET_VENDOR_ALACRITECH=y
-# CONFIG_SLICOSS is not set
 CONFIG_NET_VENDOR_ALTEON=y
 CONFIG_ACENIC=m
 # CONFIG_ACENIC_OMIT_TIGON_I is not set
 CONFIG_ALTERA_TSE=m
-CONFIG_NET_VENDOR_AMAZON=y
-# CONFIG_ENA_ETHERNET is not set
 CONFIG_NET_VENDOR_AMD=y
 CONFIG_AMD8111_ETH=m
 CONFIG_PCNET32=m
-# CONFIG_AMD_XGBE is not set
-CONFIG_NET_VENDOR_AQUANTIA=y
-# CONFIG_AQTION is not set
 CONFIG_NET_VENDOR_ARC=y
 CONFIG_NET_VENDOR_ATHEROS=y
@@ -2170,4 +1865,8 @@
 CONFIG_ATL1C=m
 CONFIG_ALX=m
+CONFIG_NET_VENDOR_AURORA=y
+CONFIG_AURORA_NB8800=m
+CONFIG_NET_CADENCE=y
+CONFIG_MACB=m
 CONFIG_NET_VENDOR_BROADCOM=y
 CONFIG_B44=m
@@ -2175,20 +1874,13 @@
 CONFIG_B44_PCICORE_AUTOSELECT=y
 CONFIG_B44_PCI=y
-# CONFIG_BCMGENET is not set
+CONFIG_BCMGENET=m
 CONFIG_BNX2=m
 CONFIG_CNIC=m
 CONFIG_TIGON3=m
-CONFIG_TIGON3_HWMON=y
 CONFIG_BNX2X=m
-# CONFIG_SYSTEMPORT is not set
+# CONFIG_BNX2X_VXLAN is not set
 CONFIG_BNXT=m
-CONFIG_BNXT_FLOWER_OFFLOAD=y
-CONFIG_BNXT_HWMON=y
 CONFIG_NET_VENDOR_BROCADE=y
 CONFIG_BNA=m
-CONFIG_NET_VENDOR_CADENCE=y
-CONFIG_MACB=m
-CONFIG_MACB_USE_HWSTAMP=y
-# CONFIG_MACB_PCI is not set
 CONFIG_NET_VENDOR_CAVIUM=y
 CONFIG_NET_VENDOR_CHELSIO=y
@@ -2198,9 +1890,6 @@
 CONFIG_CHELSIO_T4=m
 # CONFIG_CHELSIO_T4VF is not set
-CONFIG_CHELSIO_LIB=m
-CONFIG_CHELSIO_INLINE_CRYPTO=y
 CONFIG_NET_VENDOR_CISCO=y
 CONFIG_ENIC=m
-CONFIG_NET_VENDOR_CORTINA=y
 CONFIG_CX_ECAT=m
 CONFIG_DNET=m
@@ -2225,19 +1914,15 @@
 CONFIG_BE2NET=m
 CONFIG_BE2NET_HWMON=y
-CONFIG_BE2NET_BE2=y
-CONFIG_BE2NET_BE3=y
-CONFIG_BE2NET_LANCER=y
-CONFIG_BE2NET_SKYHAWK=y
+CONFIG_BE2NET_VXLAN=y
 CONFIG_NET_VENDOR_EZCHIP=y
-CONFIG_NET_VENDOR_GOOGLE=y
-# CONFIG_GVE is not set
-CONFIG_NET_VENDOR_HUAWEI=y
-# CONFIG_HINIC is not set
-CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_EXAR=y
+CONFIG_S2IO=m
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_HP=y
+CONFIG_HP100=m
 CONFIG_NET_VENDOR_INTEL=y
 CONFIG_E100=m
 CONFIG_E1000=m
 CONFIG_E1000E=m
-CONFIG_E1000E_HWTS=y
 CONFIG_IGB=m
 CONFIG_IGB_HWMON=y
@@ -2245,13 +1930,13 @@
 CONFIG_IXGB=m
 CONFIG_IXGBE=m
+CONFIG_IXGBE_VXLAN=y
 CONFIG_IXGBE_HWMON=y
 CONFIG_IXGBEVF=m
 CONFIG_I40E=m
-CONFIG_IAVF=m
+CONFIG_I40E_VXLAN=y
 CONFIG_I40EVF=m
-# CONFIG_ICE is not set
 CONFIG_FM10K=m
-# CONFIG_IGC is not set
-CONFIG_NET_VENDOR_MICROSOFT=y
+CONFIG_FM10K_VXLAN=y
+CONFIG_NET_VENDOR_I825XX=y
 CONFIG_JME=m
 CONFIG_NET_VENDOR_MARVELL=y
@@ -2262,24 +1947,15 @@
 CONFIG_NET_VENDOR_MELLANOX=y
 CONFIG_MLX4_EN=m
+CONFIG_MLX4_EN_VXLAN=y
 CONFIG_MLX4_CORE=m
 CONFIG_MLX4_DEBUG=y
-CONFIG_MLX4_CORE_GEN2=y
 CONFIG_MLX5_CORE=m
-# CONFIG_MLX5_FPGA is not set
 # CONFIG_MLX5_CORE_EN is not set
 CONFIG_MLXSW_CORE=m
-CONFIG_MLXSW_CORE_HWMON=y
-CONFIG_MLXSW_CORE_THERMAL=y
 CONFIG_MLXSW_PCI=m
-CONFIG_MLXSW_I2C=m
-CONFIG_MLXSW_MINIMAL=m
-CONFIG_MLXFW=m
 CONFIG_NET_VENDOR_MICREL=y
 CONFIG_KS8842=m
 CONFIG_KS8851_MLL=m
 CONFIG_KSZ884X_PCI=m
-CONFIG_NET_VENDOR_MICROCHIP=y
-# CONFIG_LAN743X is not set
-CONFIG_NET_VENDOR_MICROSEMI=y
 CONFIG_NET_VENDOR_MYRI=y
 CONFIG_MYRI10GE=m
@@ -2288,11 +1964,4 @@
 CONFIG_NATSEMI=m
 CONFIG_NS83820=m
-CONFIG_NET_VENDOR_NETERION=y
-CONFIG_S2IO=m
-# CONFIG_VXGE is not set
-CONFIG_NET_VENDOR_NETRONOME=y
-# CONFIG_NFP is not set
-CONFIG_NET_VENDOR_NI=y
-# CONFIG_NI_XGE_MANAGEMENT_ENET is not set
 CONFIG_NET_VENDOR_8390=y
 CONFIG_NE2K_PCI=m
@@ -2302,20 +1971,17 @@
 CONFIG_PCH_GBE=m
 CONFIG_ETHOC=m
-CONFIG_NET_VENDOR_PACKET_ENGINES=y
+CONFIG_NET_PACKET_ENGINE=y
 CONFIG_HAMACHI=m
 CONFIG_YELLOWFIN=m
-CONFIG_NET_VENDOR_PENSANDO=y
 CONFIG_NET_VENDOR_QLOGIC=y
 CONFIG_QLA3XXX=m
 CONFIG_QLCNIC=m
+# CONFIG_QLCNIC_VXLAN is not set
 CONFIG_QLCNIC_HWMON=y
+CONFIG_QLGE=m
 CONFIG_NETXEN_NIC=m
 CONFIG_QED=m
 # CONFIG_QEDE is not set
 CONFIG_NET_VENDOR_QUALCOMM=y
-# CONFIG_QCOM_EMAC is not set
-# CONFIG_RMNET is not set
-CONFIG_NET_VENDOR_RDC=y
-CONFIG_R6040=m
 CONFIG_NET_VENDOR_REALTEK=y
 CONFIG_8139CP=m
@@ -2327,14 +1993,10 @@
 CONFIG_R8169=m
 CONFIG_NET_VENDOR_RENESAS=y
+CONFIG_NET_VENDOR_RDC=y
+CONFIG_R6040=m
 CONFIG_NET_VENDOR_ROCKER=y
 CONFIG_NET_VENDOR_SAMSUNG=y
 CONFIG_SXGBE_ETH=m
 CONFIG_NET_VENDOR_SEEQ=y
-CONFIG_NET_VENDOR_SOLARFLARE=y
-CONFIG_SFC=m
-CONFIG_SFC_MTD=y
-CONFIG_SFC_MCDI_MON=y
-CONFIG_SFC_MCDI_LOGGING=y
-# CONFIG_SFC_FALCON is not set
 CONFIG_NET_VENDOR_SILAN=y
 CONFIG_SC92031=m
@@ -2342,16 +2004,17 @@
 CONFIG_SIS900=m
 CONFIG_SIS190=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_SFC_MCDI_MON=y
+CONFIG_SFC_MCDI_LOGGING=y
 CONFIG_NET_VENDOR_SMSC=y
 CONFIG_EPIC100=m
 CONFIG_SMSC911X=m
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
 CONFIG_SMSC9420=m
-CONFIG_NET_VENDOR_SOCIONEXT=y
 CONFIG_NET_VENDOR_STMICRO=y
 CONFIG_STMMAC_ETH=m
-# CONFIG_STMMAC_SELFTESTS is not set
 CONFIG_STMMAC_PLATFORM=m
 CONFIG_DWMAC_GENERIC=m
-CONFIG_DWMAC_INTEL=m
-# CONFIG_DWMAC_LOONGSON is not set
 # CONFIG_STMMAC_PCI is not set
 CONFIG_NET_VENDOR_SUN=y
@@ -2361,9 +2024,8 @@
 CONFIG_NIU=m
 CONFIG_NET_VENDOR_SYNOPSYS=y
-# CONFIG_DWC_XLGMAC is not set
 CONFIG_NET_VENDOR_TEHUTI=y
 CONFIG_TEHUTI=m
 CONFIG_NET_VENDOR_TI=y
-# CONFIG_TI_CPSW_PHY_SEL is not set
+CONFIG_TI_CPSW_ALE=m
 CONFIG_TLAN=m
 CONFIG_NET_VENDOR_VIA=y
@@ -2377,84 +2039,40 @@
 # CONFIG_WIZNET_BUS_INDIRECT is not set
 CONFIG_WIZNET_BUS_ANY=y
-CONFIG_NET_VENDOR_XILINX=y
-# CONFIG_XILINX_EMACLITE is not set
-# CONFIG_XILINX_AXI_EMAC is not set
-# CONFIG_XILINX_LL_TEMAC is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_NET_SB1000 is not set
-CONFIG_PHYLINK=m
 CONFIG_PHYLIB=m
-CONFIG_SWPHY=y
-CONFIG_FIXED_PHY=m
-# CONFIG_SFP is not set
 
 #
 # MII PHY device drivers
 #
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
 CONFIG_AMD_PHY=m
-# CONFIG_ADIN_PHY is not set
-# CONFIG_AQUANTIA_PHY is not set
-# CONFIG_AX88796B_PHY is not set
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+# CONFIG_TERANETICS_PHY is not set
+CONFIG_SMSC_PHY=m
+CONFIG_BCM_NET_PHYLIB=m
 CONFIG_BROADCOM_PHY=m
-# CONFIG_BCM54140_PHY is not set
 CONFIG_BCM7XXX_PHY=m
-# CONFIG_BCM84881_PHY is not set
 # CONFIG_BCM87XX_PHY is not set
-CONFIG_BCM_NET_PHYLIB=m
-CONFIG_CICADA_PHY=m
-# CONFIG_CORTINA_PHY is not set
-CONFIG_DAVICOM_PHY=m
 CONFIG_ICPLUS_PHY=m
-CONFIG_LXT_PHY=m
-# CONFIG_INTEL_XWAY_PHY is not set
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
 CONFIG_LSI_ET1011C_PHY=m
-CONFIG_MARVELL_PHY=m
-# CONFIG_MARVELL_10G_PHY is not set
-# CONFIG_MARVELL_88X2222_PHY is not set
-# CONFIG_MEDIATEK_GE_PHY is not set
 CONFIG_MICREL_PHY=m
-# CONFIG_MICROCHIP_PHY is not set
-# CONFIG_MICROCHIP_T1_PHY is not set
-# CONFIG_MICROSEMI_PHY is not set
-# CONFIG_MOTORCOMM_PHY is not set
-CONFIG_NATIONAL_PHY=m
-# CONFIG_NXP_C45_TJA11XX_PHY is not set
-# CONFIG_NXP_TJA11XX_PHY is not set
-CONFIG_QSEMI_PHY=m
-CONFIG_REALTEK_PHY=m
-# CONFIG_RENESAS_PHY is not set
-# CONFIG_ROCKCHIP_PHY is not set
-CONFIG_SMSC_PHY=m
-CONFIG_STE10XP=m
-# CONFIG_TERANETICS_PHY is not set
-# CONFIG_DP83822_PHY is not set
-# CONFIG_DP83TC811_PHY is not set
 # CONFIG_DP83848_PHY is not set
 # CONFIG_DP83867_PHY is not set
-# CONFIG_DP83869_PHY is not set
-CONFIG_VITESSE_PHY=m
-# CONFIG_XILINX_GMII2RGMII is not set
-CONFIG_MDIO_DEVICE=m
-CONFIG_MDIO_BUS=m
-CONFIG_FWNODE_MDIO=m
-CONFIG_ACPI_MDIO=m
-CONFIG_MDIO_DEVRES=m
+# CONFIG_MICROCHIP_PHY is not set
+CONFIG_FIXED_PHY=m
 CONFIG_MDIO_BITBANG=m
+CONFIG_MDIO_GPIO=m
 # CONFIG_MDIO_BCM_UNIMAC is not set
-CONFIG_MDIO_GPIO=m
-# CONFIG_MDIO_MVUSB is not set
-# CONFIG_MDIO_MSCC_MIIM is not set
-
-#
-# MDIO Multiplexers
-#
-
-#
-# PCS device drivers
-#
-CONFIG_PCS_XPCS=m
-# end of PCS device drivers
-
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -2476,16 +2094,12 @@
 # CONFIG_USB_NET_DRIVERS is not set
 # CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
-
-#
-# Wireless WAN
-#
-# CONFIG_WWAN is not set
-# end of Wireless WAN
-
 CONFIG_VMXNET3=m
 # CONFIG_FUJITSU_ES is not set
 CONFIG_HYPERV_NET=m
-CONFIG_NET_FAILOVER=m
 # CONFIG_ISDN is not set
 # CONFIG_NVM is not set
@@ -2497,4 +2111,5 @@
 CONFIG_INPUT_LEDS=m
 # CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=m
 # CONFIG_INPUT_SPARSEKMAP is not set
 CONFIG_INPUT_MATRIXKMAP=m
@@ -2518,8 +2133,6 @@
 # CONFIG_KEYBOARD_ADP5589 is not set
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_QT1050 is not set
 # CONFIG_KEYBOARD_QT1070 is not set
 # CONFIG_KEYBOARD_QT2160 is not set
-# CONFIG_KEYBOARD_DLINK_DIR685 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 CONFIG_KEYBOARD_GPIO=m
@@ -2538,10 +2151,8 @@
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
-CONFIG_MOUSE_PS2_BYD=y
 CONFIG_MOUSE_PS2_LOGIPS2PP=y
 CONFIG_MOUSE_PS2_SYNAPTICS=y
@@ -2572,8 +2183,9 @@
 CONFIG_INPUT_PCSPKR=y
 # CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
 # CONFIG_INPUT_APANEL is not set
+# CONFIG_INPUT_GP2A is not set
 # CONFIG_INPUT_GPIO_BEEPER is not set
-# CONFIG_INPUT_GPIO_DECODER is not set
-# CONFIG_INPUT_GPIO_VIBRA is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
 # CONFIG_INPUT_WISTRON_BTNS is not set
 # CONFIG_INPUT_ATLAS_BTNS is not set
@@ -2587,9 +2199,6 @@
 # CONFIG_INPUT_PCF8574 is not set
 # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
-# CONFIG_INPUT_DA7280_HAPTICS is not set
 # CONFIG_INPUT_ADXL34X is not set
 # CONFIG_INPUT_IMS_PCU is not set
-# CONFIG_INPUT_IQS269A is not set
-# CONFIG_INPUT_IQS626A is not set
 # CONFIG_INPUT_CMA3000 is not set
 # CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set
@@ -2598,5 +2207,4 @@
 # CONFIG_INPUT_DRV2665_HAPTICS is not set
 # CONFIG_INPUT_DRV2667_HAPTICS is not set
-# CONFIG_RMI4_CORE is not set
 
 #
@@ -2615,9 +2223,6 @@
 # CONFIG_SERIO_ARC_PS2 is not set
 CONFIG_HYPERV_KEYBOARD=m
-# CONFIG_SERIO_GPIO_PS2 is not set
 # CONFIG_USERIO is not set
 # CONFIG_GAMEPORT is not set
-# end of Hardware I/O ports
-# end of Input device support
 
 #
@@ -2632,7 +2237,13 @@
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_LDISC_AUTOLOAD=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
 
 #
@@ -2643,10 +2254,7 @@
 # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
 CONFIG_SERIAL_8250_PNP=y
-# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
-# CONFIG_SERIAL_8250_FINTEK is not set
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_DMA=y
 CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_EXAR=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
@@ -2656,9 +2264,9 @@
 # CONFIG_SERIAL_8250_DETECT_IRQ is not set
 CONFIG_SERIAL_8250_RSA=y
-CONFIG_SERIAL_8250_DWLIB=y
+# CONFIG_SERIAL_8250_FSL is not set
 # CONFIG_SERIAL_8250_DW is not set
 # CONFIG_SERIAL_8250_RT288X is not set
-CONFIG_SERIAL_8250_LPSS=y
-CONFIG_SERIAL_8250_MID=y
+# CONFIG_SERIAL_8250_FINTEK is not set
+# CONFIG_SERIAL_8250_MID is not set
 
 #
@@ -2669,9 +2277,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_JSM=m
-# CONFIG_SERIAL_LANTIQ is not set
 # CONFIG_SERIAL_SCCNXP is not set
 # CONFIG_SERIAL_SC16IS7XX is not set
 # CONFIG_SERIAL_TIMBERDALE is not set
-# CONFIG_SERIAL_BCM63XX is not set
 # CONFIG_SERIAL_ALTERA_JTAGUART is not set
 # CONFIG_SERIAL_ALTERA_UART is not set
@@ -2681,36 +2287,24 @@
 CONFIG_SERIAL_RP2_NR_UARTS=32
 # CONFIG_SERIAL_FSL_LPUART is not set
-# CONFIG_SERIAL_FSL_LINFLEXUART is not set
-# CONFIG_SERIAL_SPRD is not set
-# end of Serial drivers
-
-CONFIG_SERIAL_MCTRL_GPIO=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_N_GSM is not set
-# CONFIG_NOZOMI is not set
-# CONFIG_NULL_TTY is not set
 CONFIG_HVC_DRIVER=y
-# CONFIG_SERIAL_DEV_BUS is not set
-CONFIG_VIRTIO_CONSOLE=m
+CONFIG_VIRTIO_CONSOLE=y
 CONFIG_IPMI_HANDLER=m
-CONFIG_IPMI_DMI_DECODE=y
-CONFIG_IPMI_PLAT_DATA=y
 CONFIG_IPMI_PANIC_EVENT=y
 CONFIG_IPMI_PANIC_STRING=y
 CONFIG_IPMI_DEVICE_INTERFACE=m
 CONFIG_IPMI_SI=m
+# CONFIG_IPMI_SI_PROBE_DEFAULTS is not set
 CONFIG_IPMI_SSIF=m
 CONFIG_IPMI_WATCHDOG=m
 CONFIG_IPMI_POWEROFF=m
-# CONFIG_IPMB_DEVICE_INTERFACE is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_TIMERIOMEM=y
 CONFIG_HW_RANDOM_INTEL=y
 CONFIG_HW_RANDOM_AMD=y
-# CONFIG_HW_RANDOM_BA431 is not set
 CONFIG_HW_RANDOM_GEODE=y
 CONFIG_HW_RANDOM_VIA=y
 CONFIG_HW_RANDOM_VIRTIO=m
-# CONFIG_HW_RANDOM_XIPHERA is not set
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_SONYPI is not set
@@ -2718,7 +2312,5 @@
 # CONFIG_PC8736x_GPIO is not set
 # CONFIG_NSC_GPIO is not set
-CONFIG_DEVMEM=y
-CONFIG_NVRAM=y
-CONFIG_DEVPORT=y
+# CONFIG_RAW_DRIVER is not set
 CONFIG_HPET=y
 CONFIG_HPET_MMAP=y
@@ -2727,10 +2319,6 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
 # CONFIG_XILLYBUS is not set
-# CONFIG_XILLYUSB is not set
-# end of Character devices
-
-# CONFIG_RANDOM_TRUST_CPU is not set
-# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
 
 #
@@ -2760,5 +2348,4 @@
 CONFIG_I2C_AMD756_S4882=m
 CONFIG_I2C_AMD8111=m
-# CONFIG_I2C_AMD_MP2 is not set
 CONFIG_I2C_I801=m
 CONFIG_I2C_ISCH=m
@@ -2767,5 +2354,4 @@
 CONFIG_I2C_NFORCE2=m
 CONFIG_I2C_NFORCE2_S4985=m
-# CONFIG_I2C_NVIDIA_GPU is not set
 CONFIG_I2C_SIS5595=m
 CONFIG_I2C_SIS630=m
@@ -2784,14 +2370,12 @@
 CONFIG_I2C_CBUS_GPIO=m
 CONFIG_I2C_DESIGNWARE_CORE=m
-# CONFIG_I2C_DESIGNWARE_SLAVE is not set
 CONFIG_I2C_DESIGNWARE_PLATFORM=m
-# CONFIG_I2C_DESIGNWARE_BAYTRAIL is not set
 CONFIG_I2C_DESIGNWARE_PCI=m
 CONFIG_I2C_EG20T=m
 CONFIG_I2C_EMEV2=m
 CONFIG_I2C_GPIO=m
-# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
 CONFIG_I2C_OCORES=m
 CONFIG_I2C_PCA_PLATFORM=m
+# CONFIG_I2C_PXA_PCI is not set
 CONFIG_I2C_SIMTEC=m
 CONFIG_I2C_XILINX=m
@@ -2801,5 +2385,5 @@
 #
 CONFIG_I2C_DIOLAN_U2C=m
-# CONFIG_I2C_CP2615 is not set
+CONFIG_I2C_PARPORT_LIGHT=m
 CONFIG_I2C_ROBOTFUZZ_OSIF=m
 CONFIG_I2C_TAOS_EVM=m
@@ -2810,21 +2394,19 @@
 #
 CONFIG_SCx200_ACB=m
-# end of I2C Hardware Bus support
-
 # CONFIG_I2C_STUB is not set
-CONFIG_I2C_SLAVE=y
-# CONFIG_I2C_SLAVE_EEPROM is not set
-# CONFIG_I2C_SLAVE_TESTUNIT is not set
+# CONFIG_I2C_SLAVE is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
-# end of I2C support
-
-# CONFIG_I3C is not set
 # CONFIG_SPI is not set
 # CONFIG_SPMI is not set
 # CONFIG_HSI is not set
+
+#
+# PPS support
+#
 CONFIG_PPS=m
 # CONFIG_PPS_DEBUG is not set
+# CONFIG_NTP_PPS is not set
 
 #
@@ -2848,42 +2430,19 @@
 #
 CONFIG_PTP_1588_CLOCK_PCH=m
-CONFIG_PTP_1588_CLOCK_KVM=m
-# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set
-# CONFIG_PTP_1588_CLOCK_IDTCM is not set
-# CONFIG_PTP_1588_CLOCK_VMW is not set
-# CONFIG_PTP_1588_CLOCK_OCP is not set
-# end of PTP clock support
-
 CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
 # CONFIG_PINCTRL_AMD is not set
-# CONFIG_PINCTRL_MCP23S08 is not set
 # CONFIG_PINCTRL_BAYTRAIL is not set
 # CONFIG_PINCTRL_CHERRYVIEW is not set
-# CONFIG_PINCTRL_LYNXPOINT is not set
-# CONFIG_PINCTRL_ALDERLAKE is not set
 # CONFIG_PINCTRL_BROXTON is not set
-# CONFIG_PINCTRL_CANNONLAKE is not set
-# CONFIG_PINCTRL_CEDARFORK is not set
-# CONFIG_PINCTRL_DENVERTON is not set
-# CONFIG_PINCTRL_ELKHARTLAKE is not set
-# CONFIG_PINCTRL_EMMITSBURG is not set
-# CONFIG_PINCTRL_GEMINILAKE is not set
-# CONFIG_PINCTRL_ICELAKE is not set
-# CONFIG_PINCTRL_JASPERLAKE is not set
-# CONFIG_PINCTRL_LAKEFIELD is not set
-# CONFIG_PINCTRL_LEWISBURG is not set
 # CONFIG_PINCTRL_SUNRISEPOINT is not set
-# CONFIG_PINCTRL_TIGERLAKE is not set
-
-#
-# Renesas pinctrl drivers
-#
-# end of Renesas pinctrl drivers
-
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
-CONFIG_GPIOLIB_FASTPATH_LIMIT=512
+CONFIG_GPIO_DEVRES=y
 CONFIG_GPIO_ACPI=y
-CONFIG_GPIO_CDEV=y
-CONFIG_GPIO_CDEV_V1=y
+# CONFIG_GPIO_SYSFS is not set
 
 #
@@ -2892,21 +2451,18 @@
 # CONFIG_GPIO_AMDPT is not set
 # CONFIG_GPIO_DWAPB is not set
-# CONFIG_GPIO_EXAR is not set
 # CONFIG_GPIO_GENERIC_PLATFORM is not set
-# CONFIG_GPIO_MB86S7X is not set
+# CONFIG_GPIO_ICH is not set
+# CONFIG_GPIO_LYNXPOINT is not set
 # CONFIG_GPIO_VX855 is not set
-# CONFIG_GPIO_AMD_FCH is not set
-# end of Memory mapped GPIO drivers
+# CONFIG_GPIO_ZX is not set
 
 #
 # Port-mapped I/O GPIO drivers
 #
+# CONFIG_GPIO_104_IDIO_16 is not set
 # CONFIG_GPIO_F7188X is not set
 # CONFIG_GPIO_IT87 is not set
 # CONFIG_GPIO_SCH is not set
 # CONFIG_GPIO_SCH311X is not set
-# CONFIG_GPIO_WINBOND is not set
-# CONFIG_GPIO_WS16C48 is not set
-# end of Port-mapped I/O GPIO drivers
 
 #
@@ -2917,13 +2473,9 @@
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
-# CONFIG_GPIO_PCA9570 is not set
 # CONFIG_GPIO_PCF857X is not set
-# CONFIG_GPIO_TPIC2810 is not set
-# end of I2C GPIO expanders
 
 #
 # MFD GPIO expanders
 #
-# end of MFD GPIO expanders
 
 #
@@ -2932,37 +2484,26 @@
 # CONFIG_GPIO_AMD8111 is not set
 # CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_INTEL_MID is not set
 # CONFIG_GPIO_ML_IOH is not set
 # CONFIG_GPIO_PCH is not set
-# CONFIG_GPIO_PCI_IDIO_16 is not set
-# CONFIG_GPIO_PCIE_IDIO_24 is not set
 # CONFIG_GPIO_RDC321X is not set
-# end of PCI GPIO expanders
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
 
 #
 # USB GPIO expanders
 #
-# end of USB GPIO expanders
-
-#
-# Virtual GPIO drivers
-#
-# CONFIG_GPIO_AGGREGATOR is not set
-# CONFIG_GPIO_MOCKUP is not set
-# end of Virtual GPIO drivers
-
 # CONFIG_W1 is not set
-CONFIG_POWER_RESET=y
-# CONFIG_POWER_RESET_RESTART is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_POWER_SUPPLY_DEBUG is not set
 # CONFIG_PDA_POWER is not set
 # CONFIG_TEST_POWER is not set
-# CONFIG_CHARGER_ADP5061 is not set
-# CONFIG_BATTERY_CW2015 is not set
 # CONFIG_BATTERY_DS2780 is not set
 # CONFIG_BATTERY_DS2781 is not set
 # CONFIG_BATTERY_DS2782 is not set
 # CONFIG_BATTERY_SBS is not set
-# CONFIG_CHARGER_SBS is not set
 # CONFIG_BATTERY_BQ27XXX is not set
 # CONFIG_BATTERY_MAX17040 is not set
@@ -2971,19 +2512,15 @@
 # CONFIG_CHARGER_LP8727 is not set
 # CONFIG_CHARGER_GPIO is not set
-# CONFIG_CHARGER_LT3651 is not set
-# CONFIG_CHARGER_LTC4162L is not set
 # CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
 # CONFIG_CHARGER_BQ24257 is not set
 # CONFIG_CHARGER_BQ24735 is not set
-# CONFIG_CHARGER_BQ2515X is not set
 # CONFIG_CHARGER_BQ25890 is not set
-# CONFIG_CHARGER_BQ25980 is not set
-# CONFIG_CHARGER_BQ256XX is not set
 # CONFIG_CHARGER_SMB347 is not set
 # CONFIG_BATTERY_GAUGE_LTC2941 is not set
-# CONFIG_BATTERY_GOLDFISH is not set
-# CONFIG_BATTERY_RT5033 is not set
 # CONFIG_CHARGER_RT9455 is not set
-# CONFIG_CHARGER_BD99954 is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_AVS is not set
 CONFIG_HWMON=m
 CONFIG_HWMON_VID=m
@@ -3002,5 +2539,4 @@
 CONFIG_SENSORS_ADM1029=m
 CONFIG_SENSORS_ADM1031=m
-# CONFIG_SENSORS_ADM1177 is not set
 CONFIG_SENSORS_ADM9240=m
 CONFIG_SENSORS_ADT7X10=m
@@ -3010,8 +2546,5 @@
 CONFIG_SENSORS_ADT7470=m
 CONFIG_SENSORS_ADT7475=m
-# CONFIG_SENSORS_AHT10 is not set
-# CONFIG_SENSORS_AS370 is not set
 CONFIG_SENSORS_ASC7621=m
-# CONFIG_SENSORS_AXI_FAN_CONTROL is not set
 CONFIG_SENSORS_K8TEMP=m
 CONFIG_SENSORS_K10TEMP=m
@@ -3019,9 +2552,5 @@
 CONFIG_SENSORS_APPLESMC=m
 CONFIG_SENSORS_ASB100=m
-# CONFIG_SENSORS_ASPEED is not set
 CONFIG_SENSORS_ATXP1=m
-# CONFIG_SENSORS_CORSAIR_CPRO is not set
-# CONFIG_SENSORS_CORSAIR_PSU is not set
-# CONFIG_SENSORS_DRIVETEMP is not set
 CONFIG_SENSORS_DS620=m
 CONFIG_SENSORS_DS1621=m
@@ -3036,4 +2565,5 @@
 CONFIG_SENSORS_G760A=m
 CONFIG_SENSORS_G762=m
+CONFIG_SENSORS_GPIO_FAN=m
 CONFIG_SENSORS_HIH6130=m
 CONFIG_SENSORS_IBMAEM=m
@@ -3046,7 +2576,4 @@
 CONFIG_SENSORS_LINEAGE=m
 CONFIG_SENSORS_LTC2945=m
-# CONFIG_SENSORS_LTC2947_I2C is not set
-# CONFIG_SENSORS_LTC2990 is not set
-# CONFIG_SENSORS_LTC2992 is not set
 CONFIG_SENSORS_LTC4151=m
 CONFIG_SENSORS_LTC4215=m
@@ -3055,11 +2582,8 @@
 CONFIG_SENSORS_LTC4260=m
 CONFIG_SENSORS_LTC4261=m
-# CONFIG_SENSORS_MAX127 is not set
 CONFIG_SENSORS_MAX16065=m
 CONFIG_SENSORS_MAX1619=m
 CONFIG_SENSORS_MAX1668=m
 CONFIG_SENSORS_MAX197=m
-# CONFIG_SENSORS_MAX31730 is not set
-# CONFIG_SENSORS_MAX6621 is not set
 CONFIG_SENSORS_MAX6639=m
 CONFIG_SENSORS_MAX6642=m
@@ -3067,8 +2591,6 @@
 CONFIG_SENSORS_MAX6697=m
 CONFIG_SENSORS_MAX31790=m
+CONFIG_SENSORS_HTU21=m
 CONFIG_SENSORS_MCP3021=m
-# CONFIG_SENSORS_TC654 is not set
-# CONFIG_SENSORS_TPS23861 is not set
-# CONFIG_SENSORS_MR75203 is not set
 CONFIG_SENSORS_LM63=m
 CONFIG_SENSORS_LM73=m
@@ -3092,51 +2614,21 @@
 CONFIG_SENSORS_NCT6775=m
 CONFIG_SENSORS_NCT7802=m
-# CONFIG_SENSORS_NPCM7XX is not set
-# CONFIG_SENSORS_NZXT_KRAKEN2 is not set
+CONFIG_SENSORS_NCT7904=m
 CONFIG_SENSORS_PCF8591=m
 CONFIG_PMBUS=m
 CONFIG_SENSORS_PMBUS=m
-# CONFIG_SENSORS_ADM1266 is not set
 CONFIG_SENSORS_ADM1275=m
-# CONFIG_SENSORS_BEL_PFE is not set
-# CONFIG_SENSORS_BPA_RS600 is not set
-# CONFIG_SENSORS_FSP_3Y is not set
-# CONFIG_SENSORS_IBM_CFFPS is not set
-# CONFIG_SENSORS_DPS920AB is not set
-# CONFIG_SENSORS_INSPUR_IPSPS is not set
-# CONFIG_SENSORS_IR35221 is not set
-# CONFIG_SENSORS_IR36021 is not set
-# CONFIG_SENSORS_IR38064 is not set
-# CONFIG_SENSORS_IRPS5401 is not set
-# CONFIG_SENSORS_ISL68137 is not set
 CONFIG_SENSORS_LM25066=m
 CONFIG_SENSORS_LTC2978=m
-# CONFIG_SENSORS_LTC3815 is not set
-# CONFIG_SENSORS_MAX15301 is not set
 CONFIG_SENSORS_MAX16064=m
-# CONFIG_SENSORS_MAX16601 is not set
-# CONFIG_SENSORS_MAX20730 is not set
 # CONFIG_SENSORS_MAX20751 is not set
-# CONFIG_SENSORS_MAX31785 is not set
 CONFIG_SENSORS_MAX34440=m
 CONFIG_SENSORS_MAX8688=m
-# CONFIG_SENSORS_MP2888 is not set
-# CONFIG_SENSORS_MP2975 is not set
-# CONFIG_SENSORS_PIM4328 is not set
-# CONFIG_SENSORS_PM6764TR is not set
-# CONFIG_SENSORS_PXE1610 is not set
-# CONFIG_SENSORS_Q54SJ108A2 is not set
-# CONFIG_SENSORS_STPDDC60 is not set
 # CONFIG_SENSORS_TPS40422 is not set
-# CONFIG_SENSORS_TPS53679 is not set
 CONFIG_SENSORS_UCD9000=m
 CONFIG_SENSORS_UCD9200=m
-# CONFIG_SENSORS_XDPE122 is not set
 CONFIG_SENSORS_ZL6100=m
-# CONFIG_SENSORS_SBTSI is not set
 CONFIG_SENSORS_SHT15=m
 CONFIG_SENSORS_SHT21=m
-# CONFIG_SENSORS_SHT3x is not set
-# CONFIG_SENSORS_SHT4x is not set
 CONFIG_SENSORS_SHTC1=m
 CONFIG_SENSORS_SIS5595=m
@@ -3148,25 +2640,22 @@
 CONFIG_SENSORS_SMSC47M192=m
 CONFIG_SENSORS_SMSC47B397=m
-# CONFIG_SENSORS_STTS751 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
 CONFIG_SENSORS_SMM665=m
 CONFIG_SENSORS_ADC128D818=m
+CONFIG_SENSORS_ADS1015=m
 CONFIG_SENSORS_ADS7828=m
 CONFIG_SENSORS_AMC6821=m
 CONFIG_SENSORS_INA209=m
 CONFIG_SENSORS_INA2XX=m
-# CONFIG_SENSORS_INA3221 is not set
 CONFIG_SENSORS_TC74=m
 CONFIG_SENSORS_THMC50=m
 CONFIG_SENSORS_TMP102=m
 CONFIG_SENSORS_TMP103=m
-# CONFIG_SENSORS_TMP108 is not set
 CONFIG_SENSORS_TMP401=m
 CONFIG_SENSORS_TMP421=m
-# CONFIG_SENSORS_TMP513 is not set
 CONFIG_SENSORS_VIA_CPUTEMP=m
 CONFIG_SENSORS_VIA686A=m
 CONFIG_SENSORS_VT1211=m
 CONFIG_SENSORS_VT8231=m
-# CONFIG_SENSORS_W83773G is not set
 CONFIG_SENSORS_W83781D=m
 CONFIG_SENSORS_W83791D=m
@@ -3186,46 +2675,41 @@
 CONFIG_SENSORS_ATK0110=m
 CONFIG_THERMAL=y
-# CONFIG_THERMAL_NETLINK is not set
-# CONFIG_THERMAL_STATISTICS is not set
-CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
 CONFIG_THERMAL_WRITABLE_TRIPS=y
 CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
 # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
 # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
 # CONFIG_THERMAL_GOV_FAIR_SHARE is not set
 CONFIG_THERMAL_GOV_STEP_WISE=y
 # CONFIG_THERMAL_GOV_BANG_BANG is not set
 CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_DEVFREQ_THERMAL is not set
+# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
 # CONFIG_THERMAL_EMULATION is not set
-
-#
-# Intel thermal drivers
-#
 # CONFIG_INTEL_POWERCLAMP is not set
-CONFIG_X86_THERMAL_VECTOR=y
 CONFIG_X86_PKG_TEMP_THERMAL=m
 # CONFIG_INTEL_SOC_DTS_THERMAL is not set
-
-#
-# ACPI INT340X thermal drivers
-#
 # CONFIG_INT340X_THERMAL is not set
-# end of ACPI INT340X thermal drivers
-
 CONFIG_INTEL_PCH_THERMAL=m
-# CONFIG_INTEL_TCC_COOLING is not set
-# end of Intel thermal drivers
-
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
 CONFIG_SSB=m
 CONFIG_SSB_SPROM=y
 CONFIG_SSB_PCIHOST_POSSIBLE=y
 CONFIG_SSB_PCIHOST=y
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+# CONFIG_SSB_HOST_SOC is not set
+# CONFIG_SSB_DEBUG is not set
 CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
 CONFIG_SSB_DRIVER_PCICORE=y
 # CONFIG_SSB_DRIVER_GPIO is not set
 CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
 # CONFIG_BCMA is not set
 
@@ -3236,30 +2720,15 @@
 # CONFIG_MFD_CS5535 is not set
 # CONFIG_MFD_BCM590XX is not set
-# CONFIG_MFD_BD9571MWV is not set
-# CONFIG_MFD_AXP20X_I2C is not set
-# CONFIG_MFD_MADERA is not set
-# CONFIG_MFD_DA9062 is not set
-# CONFIG_MFD_DA9063 is not set
-# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_CROS_EC is not set
 # CONFIG_MFD_DLN2 is not set
 # CONFIG_MFD_MC13XXX_I2C is not set
-# CONFIG_MFD_MP2629 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
 # CONFIG_LPC_ICH is not set
 CONFIG_LPC_SCH=m
-# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set
 # CONFIG_MFD_INTEL_LPSS_ACPI is not set
 # CONFIG_MFD_INTEL_LPSS_PCI is not set
-# CONFIG_MFD_INTEL_PMT is not set
-# CONFIG_MFD_IQS62X is not set
 # CONFIG_MFD_JANZ_CMODIO is not set
 # CONFIG_MFD_KEMPLD is not set
-# CONFIG_MFD_88PM800 is not set
-# CONFIG_MFD_88PM805 is not set
-# CONFIG_MFD_MAX14577 is not set
-# CONFIG_MFD_MAX77693 is not set
-# CONFIG_MFD_MAX8907 is not set
-# CONFIG_MFD_MT6360 is not set
 # CONFIG_MFD_MT6397 is not set
 # CONFIG_MFD_MENF21BMC is not set
@@ -3268,47 +2737,28 @@
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_MFD_RDC321X is not set
-# CONFIG_MFD_RT4831 is not set
-# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RN5T618 is not set
 # CONFIG_MFD_SI476X_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_MFD_SKY81452 is not set
+# CONFIG_ABX500_CORE is not set
 CONFIG_MFD_SYSCON=y
 # CONFIG_MFD_TI_AM335X_TSCADC is not set
 # CONFIG_MFD_LP3943 is not set
-# CONFIG_MFD_TI_LMU is not set
 # CONFIG_TPS6105X is not set
 # CONFIG_TPS65010 is not set
 # CONFIG_TPS6507X is not set
-# CONFIG_MFD_TPS65086 is not set
-# CONFIG_MFD_TI_LP873X is not set
-# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS65912 is not set
 # CONFIG_MFD_WL1273_CORE is not set
 # CONFIG_MFD_LM3533 is not set
 # CONFIG_MFD_TIMBERDALE is not set
-# CONFIG_MFD_TQMX86 is not set
+# CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_VX855 is not set
 # CONFIG_MFD_ARIZONA_I2C is not set
 # CONFIG_MFD_WM8994 is not set
-# CONFIG_MFD_ATC260X_I2C is not set
-# end of Multifunction device drivers
-
 # CONFIG_REGULATOR is not set
-CONFIG_RC_CORE=y
-CONFIG_RC_MAP=y
-# CONFIG_LIRC is not set
-CONFIG_RC_DECODERS=y
-CONFIG_IR_NEC_DECODER=y
-CONFIG_IR_RC5_DECODER=y
-CONFIG_IR_RC6_DECODER=y
-CONFIG_IR_JVC_DECODER=y
-CONFIG_IR_SONY_DECODER=y
-CONFIG_IR_SANYO_DECODER=y
-CONFIG_IR_SHARP_DECODER=y
-CONFIG_IR_MCE_KBD_DECODER=y
-CONFIG_IR_XMP_DECODER=y
-# CONFIG_IR_IMON_DECODER is not set
-# CONFIG_IR_RCMM_DECODER is not set
-# CONFIG_RC_DEVICES is not set
-# CONFIG_MEDIA_CEC_SUPPORT is not set
 # CONFIG_MEDIA_SUPPORT is not set
 
@@ -3323,23 +2773,23 @@
 
 #
-# ARM devices
-#
-# end of ARM devices
-
-CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
-
-#
 # Frame buffer Devices
 #
-CONFIG_FB_CMDLINE=y
-CONFIG_FB_NOTIFY=y
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_CMDLINE=y
+# CONFIG_FB_DDC is not set
 CONFIG_FB_BOOT_VESA_SUPPORT=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
 # CONFIG_FB_FOREIGN_ENDIAN is not set
-CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
@@ -3390,17 +2840,10 @@
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
 CONFIG_FB_HYPERV=m
 CONFIG_FB_SIMPLE=y
-# CONFIG_FB_SSD1307 is not set
 # CONFIG_FB_SM712 is not set
-# end of Frame buffer Devices
-
-#
-# Backlight & LCD device support
-#
-# CONFIG_LCD_CLASS_DEVICE is not set
-# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
-# end of Backlight & LCD device support
-
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 CONFIG_VGASTATE=m
 
@@ -3409,4 +2852,6 @@
 #
 CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=16
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=80
@@ -3415,10 +2860,6 @@
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
-# end of Console display driver support
-
+CONFIG_FB_CON_DECOR=y
 # CONFIG_LOGO is not set
-# end of Graphics support
-
 # CONFIG_SOUND is not set
 
@@ -3436,24 +2877,17 @@
 #
 # CONFIG_HID_A4TECH is not set
-# CONFIG_HID_ACCUTOUCH is not set
 # CONFIG_HID_ACRUX is not set
 # CONFIG_HID_APPLE is not set
 # CONFIG_HID_APPLEIR is not set
-# CONFIG_HID_ASUS is not set
 # CONFIG_HID_AUREAL is not set
 # CONFIG_HID_BELKIN is not set
 # CONFIG_HID_BETOP_FF is not set
-# CONFIG_HID_BIGBEN_FF is not set
 # CONFIG_HID_CHERRY is not set
 # CONFIG_HID_CHICONY is not set
 # CONFIG_HID_CORSAIR is not set
-# CONFIG_HID_COUGAR is not set
-# CONFIG_HID_MACALLY is not set
-# CONFIG_HID_CMEDIA is not set
-# CONFIG_HID_CREATIVE_SB0540 is not set
+# CONFIG_HID_CP2112 is not set
 # CONFIG_HID_CYPRESS is not set
 # CONFIG_HID_DRAGONRISE is not set
 # CONFIG_HID_EMS_FF is not set
-# CONFIG_HID_ELAN is not set
 # CONFIG_HID_ELECOM is not set
 # CONFIG_HID_ELO is not set
@@ -3461,7 +2895,5 @@
 # CONFIG_HID_GEMBIRD is not set
 # CONFIG_HID_GFRM is not set
-# CONFIG_HID_GLORIOUS is not set
 # CONFIG_HID_HOLTEK is not set
-# CONFIG_HID_VIVALDI is not set
 # CONFIG_HID_GT683R is not set
 # CONFIG_HID_KEYTOUCH is not set
@@ -3469,23 +2901,15 @@
 # CONFIG_HID_UCLOGIC is not set
 # CONFIG_HID_WALTOP is not set
-# CONFIG_HID_VIEWSONIC is not set
 # CONFIG_HID_GYRATION is not set
 # CONFIG_HID_ICADE is not set
-CONFIG_HID_ITE=y
-# CONFIG_HID_JABRA is not set
 # CONFIG_HID_TWINHAN is not set
 # CONFIG_HID_KENSINGTON is not set
 # CONFIG_HID_LCPOWER is not set
-# CONFIG_HID_LED is not set
 # CONFIG_HID_LENOVO is not set
 # CONFIG_HID_LOGITECH is not set
 # CONFIG_HID_MAGICMOUSE is not set
-# CONFIG_HID_MALTRON is not set
-# CONFIG_HID_MAYFLASH is not set
-CONFIG_HID_REDRAGON=y
 # CONFIG_HID_MICROSOFT is not set
 # CONFIG_HID_MONTEREY is not set
 # CONFIG_HID_MULTITOUCH is not set
-# CONFIG_HID_NTI is not set
 # CONFIG_HID_NTRIG is not set
 # CONFIG_HID_ORTEK is not set
@@ -3495,14 +2919,10 @@
 # CONFIG_HID_PICOLCD is not set
 # CONFIG_HID_PLANTRONICS is not set
-# CONFIG_HID_PLAYSTATION is not set
 # CONFIG_HID_PRIMAX is not set
-# CONFIG_HID_RETRODE is not set
 # CONFIG_HID_ROCCAT is not set
 # CONFIG_HID_SAITEK is not set
 # CONFIG_HID_SAMSUNG is not set
-# CONFIG_HID_SEMITEK is not set
 # CONFIG_HID_SONY is not set
 # CONFIG_HID_SPEEDLINK is not set
-# CONFIG_HID_STEAM is not set
 # CONFIG_HID_STEELSERIES is not set
 # CONFIG_HID_SUNPLUS is not set
@@ -3515,6 +2935,4 @@
 # CONFIG_HID_THINGM is not set
 # CONFIG_HID_THRUSTMASTER is not set
-# CONFIG_HID_UDRAW_PS3 is not set
-# CONFIG_HID_U2FZERO is not set
 # CONFIG_HID_WACOM is not set
 # CONFIG_HID_WIIMOTE is not set
@@ -3523,7 +2941,4 @@
 # CONFIG_HID_ZYDACRON is not set
 # CONFIG_HID_SENSOR_HUB is not set
-# CONFIG_HID_ALPS is not set
-# CONFIG_HID_MCP2221 is not set
-# end of Special HID drivers
 
 #
@@ -3533,21 +2948,14 @@
 # CONFIG_HID_PID is not set
 CONFIG_USB_HIDDEV=y
-# end of USB HID support
 
 #
 # I2C HID support
 #
-# CONFIG_I2C_HID_ACPI is not set
-# end of I2C HID support
-# end of HID support
-
+# CONFIG_I2C_HID is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_COMMON=m
-# CONFIG_USB_ULPI_BUS is not set
-# CONFIG_USB_CONN_GPIO is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB=m
-CONFIG_USB_PCI=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 
@@ -3556,10 +2964,10 @@
 #
 CONFIG_USB_DEFAULT_PERSIST=y
-# CONFIG_USB_FEW_INIT_RETRIES is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-# CONFIG_USB_OTG_PRODUCTLIST is not set
-CONFIG_USB_AUTOSUSPEND_DELAY=2
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_ULPI_BUS is not set
 CONFIG_USB_MON=m
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
@@ -3568,7 +2976,5 @@
 CONFIG_USB_C67X00_HCD=m
 CONFIG_USB_XHCI_HCD=m
-# CONFIG_USB_XHCI_DBGCAP is not set
 CONFIG_USB_XHCI_PCI=m
-# CONFIG_USB_XHCI_PCI_RENESAS is not set
 CONFIG_USB_XHCI_PLATFORM=m
 CONFIG_USB_EHCI_HCD=m
@@ -3576,8 +2982,8 @@
 CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_EHCI_PCI=m
-# CONFIG_USB_EHCI_FSL is not set
 CONFIG_USB_EHCI_HCD_PLATFORM=m
 CONFIG_USB_OXU210HP_HCD=m
 CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1362_HCD=m
 CONFIG_USB_FOTG210_HCD=m
 CONFIG_USB_OHCI_HCD=m
@@ -3630,5 +3036,4 @@
 # CONFIG_USB_MICROTEK is not set
 # CONFIG_USBIP_CORE is not set
-# CONFIG_USB_CDNS_SUPPORT is not set
 # CONFIG_USB_MUSB_HDRC is not set
 # CONFIG_USB_DWC3 is not set
@@ -3659,5 +3064,4 @@
 CONFIG_USB_SERIAL_EDGEPORT_TI=m
 CONFIG_USB_SERIAL_F81232=m
-# CONFIG_USB_SERIAL_F8153X is not set
 CONFIG_USB_SERIAL_GARMIN=m
 CONFIG_USB_SERIAL_IPW=m
@@ -3665,4 +3069,16 @@
 CONFIG_USB_SERIAL_KEYSPAN_PDA=m
 CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
 CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_KOBIL_SCT=m
@@ -3684,4 +3100,5 @@
 CONFIG_USB_SERIAL_TI=m
 CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
 CONFIG_USB_SERIAL_WWAN=m
 CONFIG_USB_SERIAL_OPTION=m
@@ -3692,6 +3109,4 @@
 CONFIG_USB_SERIAL_SSU100=m
 # CONFIG_USB_SERIAL_QT2 is not set
-# CONFIG_USB_SERIAL_UPD78F0730 is not set
-# CONFIG_USB_SERIAL_XR is not set
 # CONFIG_USB_SERIAL_DEBUG is not set
 
@@ -3703,6 +3118,8 @@
 # CONFIG_USB_ADUTUX is not set
 # CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -3710,5 +3127,4 @@
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_APPLE_MFI_FASTCHARGE is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
@@ -3720,7 +3136,5 @@
 # CONFIG_USB_YUREX is not set
 CONFIG_USB_EZUSB_FX2=m
-# CONFIG_USB_HUB_USB251XB is not set
 # CONFIG_USB_HSIC_USB3503 is not set
-# CONFIG_USB_HSIC_USB4604 is not set
 # CONFIG_USB_LINK_LAYER_TEST is not set
 # CONFIG_USB_CHAOSKEY is not set
@@ -3729,12 +3143,10 @@
 # USB Physical Layer drivers
 #
+# CONFIG_USB_PHY is not set
 # CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_USB_ISP1301 is not set
-# end of USB Physical Layer drivers
-
 # CONFIG_USB_GADGET is not set
-# CONFIG_TYPEC is not set
-# CONFIG_USB_ROLE_SWITCH is not set
+# CONFIG_UWB is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
@@ -3742,19 +3154,18 @@
 CONFIG_LEDS_CLASS=m
 # CONFIG_LEDS_CLASS_FLASH is not set
-# CONFIG_LEDS_CLASS_MULTICOLOR is not set
-# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
 
 #
 # LED drivers
 #
-# CONFIG_LEDS_APU is not set
 # CONFIG_LEDS_LM3530 is not set
-# CONFIG_LEDS_LM3532 is not set
 # CONFIG_LEDS_LM3642 is not set
 # CONFIG_LEDS_PCA9532 is not set
 # CONFIG_LEDS_GPIO is not set
 # CONFIG_LEDS_LP3944 is not set
-# CONFIG_LEDS_LP3952 is not set
-# CONFIG_LEDS_LP50XX is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LP5562 is not set
+# CONFIG_LEDS_LP8501 is not set
+# CONFIG_LEDS_LP8860 is not set
 # CONFIG_LEDS_CLEVO_MAIL is not set
 # CONFIG_LEDS_PCA955X is not set
@@ -3772,13 +3183,4 @@
 #
 # CONFIG_LEDS_BLINKM is not set
-# CONFIG_LEDS_MLXCPLD is not set
-# CONFIG_LEDS_MLXREG is not set
-# CONFIG_LEDS_USER is not set
-# CONFIG_LEDS_NIC78BX is not set
-# CONFIG_LEDS_TI_LMU_COMMON is not set
-
-#
-# Flash and Torch LED drivers
-#
 
 #
@@ -3794,5 +3196,7 @@
 # CONFIG_EDAC_DEBUG is not set
 CONFIG_EDAC_DECODE_MCE=y
+CONFIG_EDAC_MM_EDAC=m
 CONFIG_EDAC_AMD64=m
+# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set
 CONFIG_EDAC_AMD76X=m
 CONFIG_EDAC_E7XXX=m
@@ -3812,5 +3216,4 @@
 CONFIG_EDAC_I7300=m
 CONFIG_RTC_LIB=y
-CONFIG_RTC_MC146818_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -3819,5 +3222,4 @@
 CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
 # CONFIG_RTC_DEBUG is not set
-CONFIG_RTC_NVMEM=y
 
 #
@@ -3834,18 +3236,19 @@
 #
 # CONFIG_RTC_DRV_ABB5ZES3 is not set
-# CONFIG_RTC_DRV_ABEOZ9 is not set
 # CONFIG_RTC_DRV_ABX80X is not set
 # CONFIG_RTC_DRV_DS1307 is not set
 # CONFIG_RTC_DRV_DS1374 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
 # CONFIG_RTC_DRV_MAX6900 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_ISL12057 is not set
 # CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
 # CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF85063 is not set
-# CONFIG_RTC_DRV_PCF85363 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
@@ -3853,25 +3256,13 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
-# CONFIG_RTC_DRV_RX8010 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
 # CONFIG_RTC_DRV_RX8025 is not set
 # CONFIG_RTC_DRV_EM3027 is not set
-# CONFIG_RTC_DRV_RV3028 is not set
-# CONFIG_RTC_DRV_RV3032 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
 # CONFIG_RTC_DRV_RV8803 is not set
-# CONFIG_RTC_DRV_SD3078 is not set
 
 #
 # SPI RTC drivers
 #
-CONFIG_RTC_I2C_AND_SPI=m
-
-#
-# SPI and I2C RTC drivers
-#
-# CONFIG_RTC_DRV_DS3232 is not set
-# CONFIG_RTC_DRV_PCF2127 is not set
-# CONFIG_RTC_DRV_RV3029C2 is not set
-# CONFIG_RTC_DRV_RX6110 is not set
 
 #
@@ -3897,10 +3288,9 @@
 # on-CPU RTC drivers
 #
-# CONFIG_RTC_DRV_FTRTC010 is not set
 
 #
 # HID Sensor RTC drivers
 #
-# CONFIG_RTC_DRV_GOLDFISH is not set
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
 CONFIG_DMADEVICES=y
 # CONFIG_DMADEVICES_DEBUG is not set
@@ -3910,20 +3300,11 @@
 #
 CONFIG_DMA_ENGINE=y
-CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_VIRTUAL_CHANNELS=m
 CONFIG_DMA_ACPI=y
-# CONFIG_ALTERA_MSGDMA is not set
 CONFIG_INTEL_IDMA64=m
 CONFIG_PCH_DMA=m
-# CONFIG_PLX_DMA is not set
-# CONFIG_QCOM_HIDMA_MGMT is not set
-# CONFIG_QCOM_HIDMA is not set
-CONFIG_DW_DMAC_CORE=y
+CONFIG_DW_DMAC_CORE=m
 CONFIG_DW_DMAC=m
-CONFIG_DW_DMAC_PCI=y
-# CONFIG_DW_EDMA is not set
-# CONFIG_DW_EDMA_PCIE is not set
-CONFIG_HSU_DMA=y
-# CONFIG_SF_PDMA is not set
-# CONFIG_INTEL_LDMA is not set
+CONFIG_DW_DMAC_PCI=m
 
 #
@@ -3932,12 +3313,4 @@
 # CONFIG_ASYNC_TX_DMA is not set
 # CONFIG_DMATEST is not set
-
-#
-# DMABUF options
-#
-# CONFIG_SYNC_FILE is not set
-# CONFIG_DMABUF_HEAPS is not set
-# end of DMABUF options
-
 # CONFIG_AUXDISPLAY is not set
 CONFIG_UIO=m
@@ -3951,13 +3324,12 @@
 # CONFIG_UIO_PRUSS is not set
 # CONFIG_UIO_MF624 is not set
-# CONFIG_UIO_HV_GENERIC is not set
 # CONFIG_VFIO is not set
 CONFIG_IRQ_BYPASS_MANAGER=m
 CONFIG_VIRT_DRIVERS=y
-# CONFIG_VBOXGUEST is not set
-# CONFIG_NITRO_ENCLAVES is not set
-CONFIG_VIRTIO=m
-CONFIG_VIRTIO_PCI_LIB=m
-CONFIG_VIRTIO_MENU=y
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
 CONFIG_VIRTIO_PCI=m
 CONFIG_VIRTIO_PCI_LEGACY=y
@@ -3966,11 +3338,4 @@
 CONFIG_VIRTIO_MMIO=m
 # CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
-# CONFIG_VDPA is not set
-CONFIG_VHOST_IOTLB=m
-CONFIG_VHOST=m
-CONFIG_VHOST_MENU=y
-CONFIG_VHOST_NET=m
-# CONFIG_VHOST_VSOCK is not set
-# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
 
 #
@@ -3978,41 +3343,23 @@
 #
 CONFIG_HYPERV=m
-CONFIG_HYPERV_TIMER=y
 CONFIG_HYPERV_UTILS=m
 CONFIG_HYPERV_BALLOON=m
-# end of Microsoft Hyper-V guest support
-
-# CONFIG_GREYBUS is not set
-# CONFIG_COMEDI is not set
 # CONFIG_STAGING is not set
 # CONFIG_X86_PLATFORM_DEVICES is not set
-CONFIG_PMC_ATOM=y
 # CONFIG_CHROME_PLATFORMS is not set
-# CONFIG_MELLANOX_PLATFORM is not set
-CONFIG_SURFACE_PLATFORMS=y
-# CONFIG_SURFACE_3_BUTTON is not set
-# CONFIG_SURFACE_3_POWER_OPREGION is not set
-# CONFIG_SURFACE_GPE is not set
-# CONFIG_SURFACE_HOTPLUG is not set
-# CONFIG_SURFACE_PRO3_BUTTON is not set
-CONFIG_HAVE_CLK=y
+CONFIG_CLKDEV_LOOKUP=y
 CONFIG_HAVE_CLK_PREPARE=y
 CONFIG_COMMON_CLK=y
 
 #
-# Clock driver for ARM Reference designs
-#
-# CONFIG_ICST is not set
-# CONFIG_CLK_SP810 is not set
-# end of Clock driver for ARM Reference designs
-
-# CONFIG_COMMON_CLK_MAX9485 is not set
-# CONFIG_COMMON_CLK_SI5341 is not set
+# Common Clock Framework
+#
 # CONFIG_COMMON_CLK_SI5351 is not set
-# CONFIG_COMMON_CLK_SI544 is not set
+# CONFIG_COMMON_CLK_PXA is not set
 # CONFIG_COMMON_CLK_CDCE706 is not set
-# CONFIG_COMMON_CLK_CS2000_CP is not set
-# CONFIG_XILINX_VCU is not set
-# CONFIG_HWSPINLOCK is not set
+
+#
+# Hardware Spinlock drivers
+#
 
 #
@@ -4023,9 +3370,10 @@
 CONFIG_I8253_LOCK=y
 CONFIG_CLKBLD_I8253=y
-# end of Clock Source drivers
-
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
 # CONFIG_MAILBOX is not set
-CONFIG_IOMMU_IOVA=y
-CONFIG_IOASID=y
 CONFIG_IOMMU_API=y
 CONFIG_IOMMU_SUPPORT=y
@@ -4034,72 +3382,25 @@
 # Generic IOMMU Pagetable Support
 #
-# end of Generic IOMMU Pagetable Support
-
-# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
-CONFIG_IOMMU_DMA=y
+CONFIG_IOMMU_IOVA=y
 CONFIG_DMAR_TABLE=y
 CONFIG_INTEL_IOMMU=y
+CONFIG_INTEL_IOMMU_SVM=y
 CONFIG_INTEL_IOMMU_DEFAULT_ON=y
 CONFIG_INTEL_IOMMU_FLOPPY_WA=y
-# CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON is not set
-CONFIG_HYPERV_IOMMU=y
-# CONFIG_VIRTIO_IOMMU is not set
 
 #
 # Remoteproc drivers
 #
-# CONFIG_REMOTEPROC is not set
-# end of Remoteproc drivers
+# CONFIG_STE_MODEM_RPROC is not set
 
 #
 # Rpmsg drivers
 #
-# CONFIG_RPMSG_VIRTIO is not set
-# end of Rpmsg drivers
-
-# CONFIG_SOUNDWIRE is not set
 
 #
 # SOC (System On Chip) specific Drivers
 #
-
-#
-# Amlogic SoC drivers
-#
-# end of Amlogic SoC drivers
-
-#
-# Broadcom SoC drivers
-#
-# end of Broadcom SoC drivers
-
-#
-# NXP/Freescale QorIQ SoC drivers
-#
-# end of NXP/Freescale QorIQ SoC drivers
-
-#
-# i.MX SoC drivers
-#
-# end of i.MX SoC drivers
-
-#
-# Enable LiteX SoC Builder specific drivers
-#
-# end of Enable LiteX SoC Builder specific drivers
-
-#
-# Qualcomm SoC drivers
-#
-# end of Qualcomm SoC drivers
-
+# CONFIG_SUNXI_SRAM is not set
 # CONFIG_SOC_TI is not set
-
-#
-# Xilinx SoC drivers
-#
-# end of Xilinx SoC drivers
-# end of SOC (System On Chip) specific Drivers
-
 CONFIG_PM_DEVFREQ=y
 
@@ -4111,5 +3412,4 @@
 CONFIG_DEVFREQ_GOV_POWERSAVE=y
 CONFIG_DEVFREQ_GOV_USERSPACE=y
-# CONFIG_DEVFREQ_GOV_PASSIVE is not set
 
 #
@@ -4123,13 +3423,7 @@
 # CONFIG_VME_BUS is not set
 # CONFIG_PWM is not set
-
-#
-# IRQ chip support
-#
-# end of IRQ chip support
-
 # CONFIG_IPACK_BUS is not set
 CONFIG_RESET_CONTROLLER=y
-# CONFIG_RESET_TI_SYSCON is not set
+# CONFIG_FMC is not set
 
 #
@@ -4137,12 +3431,7 @@
 #
 CONFIG_GENERIC_PHY=y
-# CONFIG_USB_LGM_PHY is not set
-# CONFIG_PHY_CAN_TRANSCEIVER is not set
-# CONFIG_BCM_KONA_USB2_PHY is not set
 # CONFIG_PHY_PXA_28NM_HSIC is not set
 # CONFIG_PHY_PXA_28NM_USB2 is not set
-# CONFIG_PHY_INTEL_LGM_EMMC is not set
-# end of PHY Subsystem
-
+# CONFIG_BCM_KONA_USB2_PHY is not set
 # CONFIG_POWERCAP is not set
 # CONFIG_MCB is not set
@@ -4151,8 +3440,6 @@
 # Performance monitor support
 #
-# end of Performance monitor support
-
 CONFIG_RAS=y
-# CONFIG_USB4 is not set
+# CONFIG_THUNDERBOLT is not set
 
 #
@@ -4160,29 +3447,37 @@
 #
 # CONFIG_ANDROID is not set
-# end of Android
-
 # CONFIG_LIBNVDIMM is not set
-CONFIG_DAX=m
-# CONFIG_DEV_DAX is not set
-CONFIG_NVMEM=y
-CONFIG_NVMEM_SYSFS=y
-# CONFIG_NVMEM_RMEM is not set
-
-#
-# HW tracing support
-#
+# CONFIG_NVMEM is not set
 # CONFIG_STM is not set
+# CONFIG_STM_DUMMY is not set
+# CONFIG_STM_SOURCE_CONSOLE is not set
 # CONFIG_INTEL_TH is not set
-# end of HW tracing support
-
+
+#
+# FPGA Configuration Support
+#
 # CONFIG_FPGA is not set
-# CONFIG_TEE is not set
-CONFIG_PM_OPP=y
-# CONFIG_SIOX is not set
-# CONFIG_SLIMBUS is not set
-# CONFIG_INTERCONNECT is not set
-# CONFIG_COUNTER is not set
-# CONFIG_MOST is not set
-# end of Device Drivers
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+# CONFIG_DELL_RBU is not set
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# EFI (Extensible Firmware Interface) Support
+#
+# CONFIG_EFI_VARS is not set
+CONFIG_EFI_ESRT=y
+# CONFIG_EFI_RUNTIME_MAP is not set
+# CONFIG_EFI_FAKE_MEMMAP is not set
+CONFIG_EFI_RUNTIME_WRAPPERS=y
 
 #
@@ -4190,6 +3485,4 @@
 #
 CONFIG_DCACHE_WORD_ACCESS=y
-# CONFIG_VALIDATE_FS_PARSER is not set
-CONFIG_FS_IOMAP=y
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
@@ -4198,4 +3491,5 @@
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_ENCRYPTION is not set
 # CONFIG_EXT4_DEBUG is not set
 CONFIG_JBD2=y
@@ -4205,9 +3499,7 @@
 # CONFIG_JFS_FS is not set
 CONFIG_XFS_FS=y
-CONFIG_XFS_SUPPORT_V4=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
-# CONFIG_XFS_ONLINE_SCRUB is not set
 # CONFIG_XFS_WARN is not set
 # CONFIG_XFS_DEBUG is not set
@@ -4220,9 +3512,5 @@
 CONFIG_FS_POSIX_ACL=y
 CONFIG_EXPORTFS=y
-# CONFIG_EXPORTFS_BLOCK_OPS is not set
 CONFIG_FILE_LOCKING=y
-CONFIG_MANDATORY_FILE_LOCKING=y
-# CONFIG_FS_ENCRYPTION is not set
-# CONFIG_FS_VERITY is not set
 CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
@@ -4233,8 +3521,6 @@
 CONFIG_QUOTACTL=y
 # CONFIG_AUTOFS4_FS is not set
-# CONFIG_AUTOFS_FS is not set
 CONFIG_FUSE_FS=m
 CONFIG_CUSE=m
-# CONFIG_VIRTIO_FS is not set
 # CONFIG_OVERLAY_FS is not set
 
@@ -4242,6 +3528,4 @@
 # Caches
 #
-CONFIG_NETFS_SUPPORT=m
-# CONFIG_NETFS_STATS is not set
 CONFIG_FSCACHE=m
 # CONFIG_FSCACHE_STATS is not set
@@ -4252,5 +3536,4 @@
 # CONFIG_CACHEFILES_DEBUG is not set
 # CONFIG_CACHEFILES_HISTOGRAM is not set
-# end of Caches
 
 #
@@ -4261,8 +3544,8 @@
 CONFIG_ZISOFS=y
 CONFIG_UDF_FS=y
-# end of CD-ROM/DVD Filesystems
-
-#
-# DOS/FAT/EXFAT/NT Filesystems
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
 #
 CONFIG_FAT_FS=m
@@ -4271,10 +3554,7 @@
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_FAT_DEFAULT_UTF8 is not set
-# CONFIG_EXFAT_FS is not set
 CONFIG_NTFS_FS=m
 # CONFIG_NTFS_DEBUG is not set
 CONFIG_NTFS_RW=y
-# end of DOS/FAT/EXFAT/NT Filesystems
 
 #
@@ -4286,5 +3566,4 @@
 CONFIG_PROC_PAGE_MONITOR=y
 # CONFIG_PROC_CHILDREN is not set
-CONFIG_PROC_PID_ARCH_STATUS=y
 CONFIG_KERNFS=y
 CONFIG_SYSFS=y
@@ -4294,11 +3573,7 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
-CONFIG_MEMFD_CREATE=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_EFIVAR_FS=m
-# end of Pseudo filesystems
-
 CONFIG_MISC_FILESYSTEMS=y
-# CONFIG_ORANGEFS_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
@@ -4311,4 +3586,5 @@
 # CONFIG_JFFS2_FS is not set
 # CONFIG_UBIFS_FS is not set
+# CONFIG_LOGFS is not set
 # CONFIG_CRAMFS is not set
 CONFIG_SQUASHFS=y
@@ -4323,5 +3599,4 @@
 # CONFIG_SQUASHFS_LZO is not set
 # CONFIG_SQUASHFS_XZ is not set
-# CONFIG_SQUASHFS_ZSTD is not set
 # CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
 # CONFIG_SQUASHFS_EMBEDDED is not set
@@ -4339,5 +3614,4 @@
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_EROFS_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
@@ -4357,6 +3631,4 @@
 # CONFIG_NFS_USE_LEGACY_DNS is not set
 CONFIG_NFS_USE_KERNEL_DNS=y
-CONFIG_NFS_DISABLE_UDP_SUPPORT=y
-# CONFIG_NFS_V4_2_READ_PLUS is not set
 CONFIG_NFSD=m
 CONFIG_NFSD_V2_ACL=y
@@ -4364,8 +3636,5 @@
 CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
-# CONFIG_NFSD_BLOCKLAYOUT is not set
-# CONFIG_NFSD_SCSILAYOUT is not set
-# CONFIG_NFSD_FLEXFILELAYOUT is not set
-# CONFIG_NFSD_V4_2_INTER_SSC is not set
+# CONFIG_NFSD_PNFS is not set
 CONFIG_GRACE_PERIOD=m
 CONFIG_LOCKD=m
@@ -4373,5 +3642,4 @@
 CONFIG_NFS_ACL_SUPPORT=m
 CONFIG_NFS_COMMON=y
-CONFIG_NFS_V4_2_SSC_HELPER=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
@@ -4381,16 +3649,17 @@
 # CONFIG_CEPH_FS is not set
 CONFIG_CIFS=m
-# CONFIG_CIFS_STATS2 is not set
-CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
+# CONFIG_CIFS_STATS is not set
 # CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_UPCALL is not set
 CONFIG_CIFS_XATTR=y
-# CONFIG_CIFS_POSIX is not set
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_ACL=y
 CONFIG_CIFS_DEBUG=y
 # CONFIG_CIFS_DEBUG2 is not set
-# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set
 # CONFIG_CIFS_DFS_UPCALL is not set
-# CONFIG_CIFS_SWN_UPCALL is not set
+CONFIG_CIFS_SMB2=y
+# CONFIG_CIFS_SMB311 is not set
 CONFIG_CIFS_FSCACHE=y
+# CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -4447,7 +3716,121 @@
 CONFIG_NLS_UTF8=y
 # CONFIG_DLM is not set
-# CONFIG_UNICODE is not set
-CONFIG_IO_WQ=y
-# end of File systems
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_SCHED_INFO=y
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+CONFIG_MEMTEST=y
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+# CONFIG_EARLY_PRINTK_EFI is not set
+# CONFIG_X86_PTDUMP_CORE is not set
+# CONFIG_EFI_PGT_DUMP is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+CONFIG_DOUBLEFAULT=y
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_OPTIMIZE_INLINING is not set
+# CONFIG_PUNIT_ATOM_DEBUG is not set
 
 #
@@ -4455,39 +3838,13 @@
 #
 CONFIG_KEYS=y
-# CONFIG_KEYS_REQUEST_CACHE is not set
 # CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
 # CONFIG_ENCRYPTED_KEYS is not set
-# CONFIG_KEY_DH_OPERATIONS is not set
 # CONFIG_SECURITY_DMESG_RESTRICT is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-CONFIG_PAGE_TABLE_ISOLATION=y
 # CONFIG_INTEL_TXT is not set
-CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
-# CONFIG_HARDENED_USERCOPY is not set
-# CONFIG_FORTIFY_SOURCE is not set
-# CONFIG_STATIC_USERMODEHELPER is not set
-# CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT is not set
 CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf"
-
-#
-# Kernel hardening options
-#
-
-#
-# Memory initialization
-#
-CONFIG_INIT_STACK_NONE=y
-# CONFIG_GCC_PLUGIN_STRUCTLEAK_USER is not set
-# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF is not set
-# CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL is not set
-# CONFIG_GCC_PLUGIN_STACKLEAK is not set
-# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
-# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
-# end of Memory initialization
-# end of Kernel hardening options
-# end of Security options
-
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_XOR_BLOCKS=m
 CONFIG_ASYNC_CORE=m
@@ -4505,6 +3862,6 @@
 CONFIG_CRYPTO_AEAD=m
 CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_SKCIPHER=y
-CONFIG_CRYPTO_SKCIPHER2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
@@ -4512,9 +3869,9 @@
 CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
 CONFIG_CRYPTO_AKCIPHER2=y
 CONFIG_CRYPTO_AKCIPHER=m
-CONFIG_CRYPTO_KPP2=y
-CONFIG_CRYPTO_KPP=m
-CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
@@ -4524,22 +3881,12 @@
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_NULL2=y
-CONFIG_CRYPTO_PCRYPT=m
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_MCRYPTD is not set
 CONFIG_CRYPTO_AUTHENC=m
 # CONFIG_CRYPTO_TEST is not set
-CONFIG_CRYPTO_SIMD=m
-CONFIG_CRYPTO_ENGINE=m
-
-#
-# Public-key cryptography
-#
-CONFIG_CRYPTO_RSA=m
-CONFIG_CRYPTO_DH=m
-CONFIG_CRYPTO_ECC=m
-CONFIG_CRYPTO_ECDH=m
-# CONFIG_CRYPTO_ECDSA is not set
-# CONFIG_CRYPTO_ECRDSA is not set
-# CONFIG_CRYPTO_SM2 is not set
-# CONFIG_CRYPTO_CURVE25519 is not set
+CONFIG_CRYPTO_ABLK_HELPER=m
+CONFIG_CRYPTO_GLUE_HELPER_X86=m
 
 #
@@ -4548,6 +3895,5 @@
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-# CONFIG_CRYPTO_AEGIS128 is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
 CONFIG_CRYPTO_SEQIV=m
 CONFIG_CRYPTO_ECHAINIV=m
@@ -4557,15 +3903,11 @@
 #
 CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CFB is not set
 CONFIG_CRYPTO_CTR=m
 CONFIG_CRYPTO_CTS=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_LRW=m
-# CONFIG_CRYPTO_OFB is not set
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-# CONFIG_CRYPTO_ADIANTUM is not set
-CONFIG_CRYPTO_ESSIV=m
+# CONFIG_CRYPTO_KEYWRAP is not set
 
 #
@@ -4584,20 +3926,18 @@
 CONFIG_CRYPTO_CRC32=m
 CONFIG_CRYPTO_CRC32_PCLMUL=m
-# CONFIG_CRYPTO_XXHASH is not set
-# CONFIG_CRYPTO_BLAKE2B is not set
-# CONFIG_CRYPTO_BLAKE2S is not set
 CONFIG_CRYPTO_CRCT10DIF=y
 CONFIG_CRYPTO_GHASH=m
-CONFIG_CRYPTO_POLY1305=m
+# CONFIG_CRYPTO_POLY1305 is not set
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_SHA3=m
-# CONFIG_CRYPTO_SM3 is not set
-# CONFIG_CRYPTO_STREEBOG is not set
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 
@@ -4606,5 +3946,5 @@
 #
 CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_AES_586=m
 CONFIG_CRYPTO_AES_NI_INTEL=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -4619,9 +3959,10 @@
 CONFIG_CRYPTO_FCRYPT=m
 CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_CHACHA20=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SALSA20_586=m
+# CONFIG_CRYPTO_CHACHA20 is not set
 CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SERPENT_SSE2_586=m
-# CONFIG_CRYPTO_SM4 is not set
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -4633,9 +3974,9 @@
 #
 CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
-CONFIG_CRYPTO_842=m
+# CONFIG_CRYPTO_842 is not set
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ZSTD is not set
 
 #
@@ -4652,27 +3993,7 @@
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
-CONFIG_CRYPTO_USER_API_RNG=m
-# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
-CONFIG_CRYPTO_USER_API_AEAD=m
-CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y
-# CONFIG_CRYPTO_STATS is not set
-
-#
-# Crypto library routines
-#
-CONFIG_CRYPTO_LIB_AES=y
-CONFIG_CRYPTO_LIB_ARC4=m
-CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=m
-CONFIG_CRYPTO_LIB_BLAKE2S=m
-CONFIG_CRYPTO_LIB_CHACHA_GENERIC=m
-CONFIG_CRYPTO_LIB_CHACHA=m
-CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=m
-CONFIG_CRYPTO_LIB_CURVE25519=m
-CONFIG_CRYPTO_LIB_DES=m
-CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
-CONFIG_CRYPTO_LIB_POLY1305_GENERIC=m
-CONFIG_CRYPTO_LIB_POLY1305=m
-CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m
-CONFIG_CRYPTO_LIB_SHA256=m
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HASH_INFO=y
 CONFIG_CRYPTO_HW=y
 CONFIG_CRYPTO_DEV_PADLOCK=m
@@ -4680,29 +4001,39 @@
 CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
 CONFIG_CRYPTO_DEV_GEODE=m
-# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set
-# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set
 CONFIG_CRYPTO_DEV_CCP=y
 CONFIG_CRYPTO_DEV_CCP_DD=m
-CONFIG_CRYPTO_DEV_SP_CCP=y
 CONFIG_CRYPTO_DEV_CCP_CRYPTO=m
-# CONFIG_CRYPTO_DEV_CCP_DEBUGFS is not set
 # CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set
-# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set
-# CONFIG_CRYPTO_DEV_QAT_C62X is not set
-# CONFIG_CRYPTO_DEV_QAT_4XXX is not set
 # CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set
-# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set
-# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set
-# CONFIG_CRYPTO_DEV_CHELSIO is not set
-CONFIG_CRYPTO_DEV_VIRTIO=m
-# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
-# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
-# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_PUBLIC_KEY_ALGO_RSA=m
+CONFIG_X509_CERTIFICATE_PARSER=m
+# CONFIG_PKCS7_MESSAGE_PARSER is not set
 
 #
 # Certificates for signature checking
 #
-# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
-# end of Certificates for signature checking
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_IRQFD=y
+CONFIG_HAVE_KVM_IRQ_ROUTING=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_APIC_ARCHITECTURE=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_HAVE_KVM_MSI=y
+CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
+CONFIG_KVM_VFIO=y
+CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
+CONFIG_HAVE_KVM_IRQ_BYPASS=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+# CONFIG_KVM_DEVICE_ASSIGNMENT is not set
+# CONFIG_LGUEST is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
@@ -4710,18 +4041,15 @@
 #
 CONFIG_RAID6_PQ=m
-CONFIG_RAID6_PQ_BENCHMARK=y
-# CONFIG_PACKING is not set
 CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
 CONFIG_GENERIC_STRNCPY_FROM_USER=y
 CONFIG_GENERIC_STRNLEN_USER=y
 CONFIG_GENERIC_NET_UTILS=y
 CONFIG_GENERIC_FIND_FIRST_BIT=y
-CONFIG_CORDIC=m
-# CONFIG_PRIME_NUMBERS is not set
-CONFIG_RATIONAL=y
 CONFIG_GENERIC_PCI_IOMAP=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
 CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
-CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=y
@@ -4734,21 +4062,16 @@
 # CONFIG_CRC32_SARWATE is not set
 # CONFIG_CRC32_BIT is not set
-CONFIG_CRC64=m
-# CONFIG_CRC4 is not set
 # CONFIG_CRC7 is not set
 CONFIG_LIBCRC32C=y
 CONFIG_CRC8=m
-CONFIG_XXHASH=y
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
 # CONFIG_RANDOM32_SELFTEST is not set
-CONFIG_842_COMPRESS=m
-CONFIG_842_DECOMPRESS=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=m
-CONFIG_LZO_DECOMPRESS=m
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_LZ4_COMPRESS=m
 CONFIG_LZ4HC_COMPRESS=m
 CONFIG_LZ4_DECOMPRESS=m
-CONFIG_ZSTD_DECOMPRESS=y
 CONFIG_XZ_DEC=y
 CONFIG_XZ_DEC_X86=y
@@ -4762,5 +4085,4 @@
 CONFIG_DECOMPRESS_GZIP=y
 CONFIG_DECOMPRESS_XZ=y
-CONFIG_DECOMPRESS_ZSTD=y
 CONFIG_GENERIC_ALLOCATOR=y
 CONFIG_BCH=m
@@ -4770,18 +4092,8 @@
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
-CONFIG_BTREE=y
-CONFIG_INTERVAL_TREE=y
-CONFIG_XARRAY_MULTI=y
 CONFIG_ASSOCIATIVE_ARRAY=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT_MAP=y
 CONFIG_HAS_DMA=y
-CONFIG_DMA_OPS=y
-CONFIG_NEED_SG_DMA_LENGTH=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_SWIOTLB=y
-# CONFIG_DMA_API_DEBUG is not set
-CONFIG_SGL_ALLOC=y
 CONFIG_CHECK_SIGNATURE=y
 CONFIG_CPU_RMAP=y
@@ -4790,211 +4102,16 @@
 # CONFIG_GLOB_SELFTEST is not set
 CONFIG_NLATTR=y
-CONFIG_LRU_CACHE=m
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
 CONFIG_CLZ_TAB=y
-CONFIG_IRQ_POLL=y
+CONFIG_CORDIC=m
+# CONFIG_DDR is not set
 CONFIG_MPILIB=m
-CONFIG_DIMLIB=y
 CONFIG_OID_REGISTRY=m
 CONFIG_UCS2_STRING=y
-CONFIG_HAVE_GENERIC_VDSO=y
-CONFIG_GENERIC_GETTIMEOFDAY=y
-CONFIG_GENERIC_VDSO_32=y
-CONFIG_GENERIC_VDSO_TIME_NS=y
 CONFIG_FONT_SUPPORT=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-CONFIG_SG_POOL=y
-CONFIG_ARCH_STACKWALK=y
-CONFIG_SBITMAP=y
-# end of Library routines
-
-#
-# Kernel hacking
-#
-
-#
-# printk and dmesg options
-#
-CONFIG_PRINTK_TIME=y
-# CONFIG_PRINTK_CALLER is not set
-# CONFIG_STACKTRACE_BUILD_ID is not set
-CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
-CONFIG_CONSOLE_LOGLEVEL_QUIET=4
-CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
-# CONFIG_DYNAMIC_DEBUG is not set
-# CONFIG_DYNAMIC_DEBUG_CORE is not set
-CONFIG_SYMBOLIC_ERRNAME=y
-CONFIG_DEBUG_BUGVERBOSE=y
-# end of printk and dmesg options
-
-#
-# Compile-time checks and compiler options
-#
-CONFIG_FRAME_WARN=1024
-CONFIG_STRIP_ASM_SYMS=y
-# CONFIG_HEADERS_INSTALL is not set
-# CONFIG_DEBUG_SECTION_MISMATCH is not set
-CONFIG_SECTION_MISMATCH_WARN_ONLY=y
-CONFIG_FRAME_POINTER=y
-# end of Compile-time checks and compiler options
-
-#
-# Generic Kernel Debugging Instruments
-#
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
-CONFIG_MAGIC_SYSRQ_SERIAL=y
-CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
-# CONFIG_DEBUG_FS is not set
-CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
-# CONFIG_UBSAN is not set
-# end of Generic Kernel Debugging Instruments
-
-# CONFIG_DEBUG_KERNEL is not set
-
-#
-# Memory Debugging
-#
-# CONFIG_PAGE_EXTENSION is not set
-# CONFIG_PAGE_POISONING is not set
-CONFIG_DEBUG_RODATA_TEST=y
-CONFIG_ARCH_HAS_DEBUG_WX=y
-# CONFIG_DEBUG_WX is not set
-CONFIG_GENERIC_PTDUMP=y
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y
-CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
-CONFIG_CC_HAS_KASAN_GENERIC=y
-CONFIG_HAVE_ARCH_KFENCE=y
-# CONFIG_KFENCE is not set
-# end of Memory Debugging
-
-#
-# Debug Oops, Lockups and Hangs
-#
-# CONFIG_PANIC_ON_OOPS is not set
-CONFIG_PANIC_ON_OOPS_VALUE=0
-CONFIG_PANIC_TIMEOUT=0
-# CONFIG_TEST_LOCKUP is not set
-# end of Debug Oops, Lockups and Hangs
-
-#
-# Scheduler Debugging
-#
-CONFIG_SCHED_INFO=y
-# end of Scheduler Debugging
-
-# CONFIG_DEBUG_TIMEKEEPING is not set
-
-#
-# Lock Debugging (spinlocks, mutexes, etc...)
-#
-CONFIG_LOCK_DEBUGGING_SUPPORT=y
-# CONFIG_WW_MUTEX_SELFTEST is not set
-# end of Lock Debugging (spinlocks, mutexes, etc...)
-
-# CONFIG_DEBUG_IRQFLAGS is not set
-# CONFIG_STACKTRACE is not set
-# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
-
-#
-# Debug kernel data structures
-#
-# CONFIG_BUG_ON_DATA_CORRUPTION is not set
-# end of Debug kernel data structures
-
-#
-# RCU Debugging
-#
-CONFIG_RCU_CPU_STALL_TIMEOUT=60
-# end of RCU Debugging
-
-CONFIG_USER_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
-CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_TRACING_SUPPORT=y
-# CONFIG_FTRACE is not set
-# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
-# CONFIG_SAMPLES is not set
-CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
-CONFIG_STRICT_DEVMEM=y
-# CONFIG_IO_STRICT_DEVMEM is not set
-
-#
-# x86 Debugging
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
-# CONFIG_X86_VERBOSE_BOOTUP is not set
-CONFIG_EARLY_PRINTK=y
-# CONFIG_EARLY_PRINTK_DBGP is not set
-# CONFIG_EARLY_PRINTK_USB_XDBC is not set
-# CONFIG_EFI_PGT_DUMP is not set
-CONFIG_HAVE_MMIOTRACE_SUPPORT=y
-CONFIG_IO_DELAY_0X80=y
-# CONFIG_IO_DELAY_0XED is not set
-# CONFIG_IO_DELAY_UDELAY is not set
-# CONFIG_IO_DELAY_NONE is not set
-# CONFIG_PUNIT_ATOM_DEBUG is not set
-CONFIG_UNWINDER_FRAME_POINTER=y
-# end of x86 Debugging
-
-#
-# Kernel Testing and Coverage
-#
-# CONFIG_KUNIT is not set
-CONFIG_RUNTIME_TESTING_MENU=y
-# CONFIG_TEST_MIN_HEAP is not set
-# CONFIG_TEST_SORT is not set
-# CONFIG_TEST_DIV64 is not set
-# CONFIG_REED_SOLOMON_TEST is not set
-# CONFIG_ATOMIC64_SELFTEST is not set
-# CONFIG_ASYNC_RAID6_TEST is not set
-# CONFIG_TEST_HEXDUMP is not set
-# CONFIG_STRING_SELFTEST is not set
-# CONFIG_TEST_STRING_HELPERS is not set
-# CONFIG_TEST_STRSCPY is not set
-# CONFIG_TEST_KSTRTOX is not set
-# CONFIG_TEST_PRINTF is not set
-# CONFIG_TEST_SCANF is not set
-# CONFIG_TEST_BITMAP is not set
-# CONFIG_TEST_UUID is not set
-# CONFIG_TEST_XARRAY is not set
-# CONFIG_TEST_OVERFLOW is not set
-# CONFIG_TEST_RHASHTABLE is not set
-# CONFIG_TEST_HASH is not set
-# CONFIG_TEST_IDA is not set
-# CONFIG_TEST_LKM is not set
-# CONFIG_TEST_BITOPS is not set
-# CONFIG_TEST_VMALLOC is not set
-# CONFIG_TEST_USER_COPY is not set
-# CONFIG_TEST_BPF is not set
-# CONFIG_TEST_BLACKHOLE_DEV is not set
-# CONFIG_FIND_BIT_BENCHMARK is not set
-# CONFIG_TEST_FIRMWARE is not set
-# CONFIG_TEST_SYSCTL is not set
-# CONFIG_TEST_UDELAY is not set
-# CONFIG_TEST_STATIC_KEYS is not set
-# CONFIG_TEST_KMOD is not set
-# CONFIG_TEST_MEMCAT_P is not set
-# CONFIG_TEST_STACKINIT is not set
-# CONFIG_TEST_MEMINIT is not set
-# CONFIG_TEST_FREE_PAGES is not set
-# CONFIG_TEST_FPU is not set
-# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set
-CONFIG_ARCH_USE_MEMTEST=y
-CONFIG_MEMTEST=y
-# end of Kernel Testing and Coverage
-# end of Kernel hacking
+# CONFIG_SG_SPLIT is not set
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_MMIO_FLUSH=y
Index: npl/kernel/linux_src/fbcondecor-3.19.patch
===================================================================
--- npl/kernel/linux_src/fbcondecor-3.19.patch	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
+++ npl/kernel/linux_src/fbcondecor-3.19.patch	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -0,0 +1,2119 @@
+diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX
+index fe85e7c..2230930 100644
+--- a/Documentation/fb/00-INDEX
++++ b/Documentation/fb/00-INDEX
+@@ -23,6 +23,8 @@ ep93xx-fb.txt
+ 	- info on the driver for EP93xx LCD controller.
+ fbcon.txt
+ 	- intro to and usage guide for the framebuffer console (fbcon).
++fbcondecor.txt
++	- info on the Framebuffer Console Decoration
+ framebuffer.txt
+ 	- introduction to frame buffer devices.
+ gxfb.txt
+diff --git a/Documentation/fb/fbcondecor.txt b/Documentation/fb/fbcondecor.txt
+new file mode 100644
+index 0000000..3388c61
+--- /dev/null
++++ b/Documentation/fb/fbcondecor.txt
+@@ -0,0 +1,207 @@
++What is it?
++-----------
++
++The framebuffer decorations are a kernel feature which allows displaying a 
++background picture on selected consoles.
++
++What do I need to get it to work?
++---------------------------------
++
++To get fbcondecor up-and-running you will have to:
++ 1) get a copy of splashutils [1] or a similar program
++ 2) get some fbcondecor themes
++ 3) build the kernel helper program
++ 4) build your kernel with the FB_CON_DECOR option enabled.
++
++To get fbcondecor operational right after fbcon initialization is finished, you
++will have to include a theme and the kernel helper into your initramfs image.
++Please refer to splashutils documentation for instructions on how to do that.
++
++[1] The splashutils package can be downloaded from:
++    http://github.com/alanhaggai/fbsplash
++
++The userspace helper
++--------------------
++
++The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the
++kernel whenever an important event occurs and the kernel needs some kind of
++job to be carried out. Important events include console switches and video
++mode switches (the kernel requests background images and configuration
++parameters for the current console). The fbcondecor helper must be accessible at
++all times. If it's not, fbcondecor will be switched off automatically.
++
++It's possible to set path to the fbcondecor helper by writing it to
++/proc/sys/kernel/fbcondecor.
++
++*****************************************************************************
++
++The information below is mostly technical stuff. There's probably no need to
++read it unless you plan to develop a userspace helper.
++
++The fbcondecor protocol
++-----------------------
++
++The fbcondecor protocol defines a communication interface between the kernel and
++the userspace fbcondecor helper.
++
++The kernel side is responsible for:
++
++ * rendering console text, using an image as a background (instead of a
++   standard solid color fbcon uses),
++ * accepting commands from the user via ioctls on the fbcondecor device,
++ * calling the userspace helper to set things up as soon as the fb subsystem 
++   is initialized.
++
++The userspace helper is responsible for everything else, including parsing
++configuration files, decompressing the image files whenever the kernel needs
++it, and communicating with the kernel if necessary.
++
++The fbcondecor protocol specifies how communication is done in both ways:
++kernel->userspace and userspace->helper.
++  
++Kernel -> Userspace
++-------------------
++
++The kernel communicates with the userspace helper by calling it and specifying
++the task to be done in a series of arguments.
++
++The arguments follow the pattern:
++<fbcondecor protocol version> <command> <parameters>
++
++All commands defined in fbcondecor protocol v2 have the following parameters:
++ virtual console
++ framebuffer number
++ theme
++
++Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the
++framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used.
++
++Fbcondecor protocol v2 specifies the following commands:
++
++getpic
++------
++ The kernel issues this command to request image data. It's up to the 
++ userspace  helper to find a background image appropriate for the specified 
++ theme and the current resolution. The userspace helper should respond by 
++ issuing the FBIOCONDECOR_SETPIC ioctl.
++
++init
++----
++ The kernel issues this command after the fbcondecor device is created and
++ the fbcondecor interface is initialized. Upon receiving 'init', the userspace
++ helper should parse the kernel command line (/proc/cmdline) or otherwise
++ decide whether fbcondecor is to be activated.
++
++ To activate fbcondecor on the first console the helper should issue the
++ FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands,
++ in the above-mentioned order.
++
++ When the userspace helper is called in an early phase of the boot process
++ (right after the initialization of fbcon), no filesystems will be mounted.
++ The helper program should mount sysfs and then create the appropriate
++ framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get
++ current display settings and to be able to communicate with the kernel side.
++ It should probably also mount the procfs to be able to parse the kernel
++ command line parameters.
++
++ Note that the console sem is not held when the kernel calls fbcondecor_helper
++ with the 'init' command. The fbcondecor helper should perform all ioctls with
++ origin set to FBCON_DECOR_IO_ORIG_USER.
++
++modechange
++----------
++ The kernel issues this command on a mode change. The helper's response should
++ be similar to the response to the 'init' command. Note that this time the
++ console sem is held and all ioctls must be performed with origin set to
++ FBCON_DECOR_IO_ORIG_KERNEL.
++
++
++Userspace -> Kernel
++-------------------
++
++Userspace programs can communicate with fbcondecor via ioctls on the
++fbcondecor device. These ioctls are to be used by both the userspace helper
++(called only by the kernel) and userspace configuration tools (run by the users).
++
++The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL
++when doing the appropriate ioctls. All userspace configuration tools should
++use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin
++field when performing ioctls from the kernel helper will most likely result
++in a console deadlock.
++
++FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console
++semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire
++the console sem.
++
++The framebuffer console decoration provides the following ioctls (all defined in 
++linux/fb.h):
++
++FBIOCONDECOR_SETPIC
++description: loads a background picture for a virtual console
++argument: struct fbcon_decor_iowrapper*; data: struct fb_image*
++notes: 
++If called for consoles other than the current foreground one, the picture data
++will be ignored.
++
++If the current virtual console is running in a 8-bpp mode, the cmap substruct
++of fb_image has to be filled appropriately: start should be set to 16 (first
++16 colors are reserved for fbcon), len to a value <= 240 and red, green and
++blue should point to valid cmap data. The transp field is ingored. The fields
++dx, dy, bg_color, fg_color in fb_image are ignored as well.
++
++FBIOCONDECOR_SETCFG
++description: sets the fbcondecor config for a virtual console
++argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
++notes: The structure has to be filled with valid data.
++
++FBIOCONDECOR_GETCFG
++description: gets the fbcondecor config for a virtual console
++argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
++
++FBIOCONDECOR_SETSTATE
++description: sets the fbcondecor state for a virtual console
++argument: struct fbcon_decor_iowrapper*; data: unsigned int*
++          values: 0 = disabled, 1 = enabled.
++
++FBIOCONDECOR_GETSTATE
++description: gets the fbcondecor state for a virtual console
++argument: struct fbcon_decor_iowrapper*; data: unsigned int*
++          values: as in FBIOCONDECOR_SETSTATE
++
++Info on used structures:
++
++Definition of struct vc_decor can be found in linux/console_decor.h. It's
++heavily commented. Note that the 'theme' field should point to a string
++no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is
++performed, the theme field should point to a char buffer of length
++FBCON_DECOR_THEME_LEN.
++
++Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h.
++The fields in this struct have the following meaning:
++
++vc: 
++Virtual console number.
++
++origin: 
++Specifies if the ioctl is performed as a response to a kernel request. The
++fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace
++programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to
++avoid console semaphore deadlocks.
++
++data: 
++Pointer to a data structure appropriate for the performed ioctl. Type of
++the data struct is specified in the ioctls description.
++
++*****************************************************************************
++
++Credit
++------
++
++Original 'bootsplash' project & implementation by:
++  Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>,
++  Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>,
++  Ken Wimer <wimer@suse.de>.
++
++Fbcondecor, fbcondecor protocol design, current implementation & docs by:
++  Michal Januszewski <michalj+fbcondecor@gmail.com>
++
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 7183b6a..d576148 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -17,6 +17,10 @@ obj-y				+= pwm/
+ obj-$(CONFIG_PCI)		+= pci/
+ obj-$(CONFIG_PARISC)		+= parisc/
+ obj-$(CONFIG_RAPIDIO)		+= rapidio/
++# tty/ comes before char/ so that the VT console is the boot-time
++# default.
++obj-y				+= tty/
++obj-y				+= char/
+ obj-y				+= video/
+ obj-y				+= idle/
+ 
+@@ -42,11 +46,6 @@ obj-$(CONFIG_REGULATOR)		+= regulator/
+ # reset controllers early, since gpu drivers might rely on them to initialize
+ obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
+ 
+-# tty/ comes before char/ so that the VT console is the boot-time
+-# default.
+-obj-y				+= tty/
+-obj-y				+= char/
+-
+ # iommu/ comes before gpu as gpu are using iommu controllers
+ obj-$(CONFIG_IOMMU_SUPPORT) += iommu/
+
+diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
+index fe1cd01..6d2e87a 100644
+--- a/drivers/video/console/Kconfig
++++ b/drivers/video/console/Kconfig
+@@ -126,6 +126,19 @@ config FRAMEBUFFER_CONSOLE_ROTATION
+          such that other users of the framebuffer will remain normally
+          oriented.
+ 
++config FB_CON_DECOR
++	bool "Support for the Framebuffer Console Decorations"
++	depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING
++	default n
++	---help---
++	  This option enables support for framebuffer console decorations which
++	  makes it possible to display images in the background of the system
++	  consoles.  Note that userspace utilities are necessary in order to take 
++	  advantage of these features. Refer to Documentation/fb/fbcondecor.txt 
++	  for more information.
++
++	  If unsure, say N.
++
+ config STI_CONSOLE
+         bool "STI text console"
+         depends on PARISC
+diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
+index 43bfa48..cc104b6f 100644
+--- a/drivers/video/console/Makefile
++++ b/drivers/video/console/Makefile
+@@ -16,4 +16,5 @@ obj-$(CONFIG_FRAMEBUFFER_CONSOLE)     += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \
+                                          fbcon_ccw.o
+ endif
+ 
++obj-$(CONFIG_FB_CON_DECOR)     	  += fbcondecor.o cfbcondecor.o
+ obj-$(CONFIG_FB_STI)              += sticore.o
+diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
+index 61b182b..984384b 100644
+--- a/drivers/video/console/bitblit.c
++++ b/drivers/video/console/bitblit.c
+@@ -18,6 +18,7 @@
+ #include <linux/console.h>
+ #include <asm/types.h>
+ #include "fbcon.h"
++#include "fbcondecor.h"
+ 
+ /*
+  * Accelerated handlers.
+@@ -55,6 +56,13 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ 	area.height = height * vc->vc_font.height;
+ 	area.width = width * vc->vc_font.width;
+ 
++	if (fbcon_decor_active(info, vc)) {
++ 		area.sx += vc->vc_decor.tx;
++ 		area.sy += vc->vc_decor.ty;
++ 		area.dx += vc->vc_decor.tx;
++ 		area.dy += vc->vc_decor.ty;
++ 	}
++
+ 	info->fbops->fb_copyarea(info, &area);
+ }
+ 
+@@ -380,11 +388,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ 	cursor.image.depth = 1;
+ 	cursor.rop = ROP_XOR;
+ 
+-	if (info->fbops->fb_cursor)
+-		err = info->fbops->fb_cursor(info, &cursor);
++	if (fbcon_decor_active(info, vc)) {
++		fbcon_decor_cursor(info, &cursor);
++	} else {
++		if (info->fbops->fb_cursor)
++			err = info->fbops->fb_cursor(info, &cursor);
+ 
+-	if (err)
+-		soft_cursor(info, &cursor);
++		if (err)
++			soft_cursor(info, &cursor);
++	}
+ 
+ 	ops->cursor_reset = 0;
+ }
+diff --git a/drivers/video/console/cfbcondecor.c b/drivers/video/console/cfbcondecor.c
+new file mode 100644
+index 0000000..a2b4497
+--- /dev/null
++++ b/drivers/video/console/cfbcondecor.c
+@@ -0,0 +1,471 @@
++/*
++ *  linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions
++ *
++ *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
++ *
++ *  Code based upon "Bootdecor" (C) 2001-2003
++ *       Volker Poplawski <volker@poplawski.de>,
++ *       Stefan Reinauer <stepan@suse.de>,
++ *       Steffen Winterfeldt <snwint@suse.de>,
++ *       Michael Schroeder <mls@suse.de>,
++ *       Ken Wimer <wimer@suse.de>.
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License.  See the file COPYING in the main directory of this archive for
++ *  more details.
++ */
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/fb.h>
++#include <linux/selection.h>
++#include <linux/slab.h>
++#include <linux/vt_kern.h>
++#include <asm/irq.h>
++
++#include "fbcon.h"
++#include "fbcondecor.h"
++
++#define parse_pixel(shift,bpp,type)						\
++	do {									\
++		if (d & (0x80 >> (shift)))					\
++			dd2[(shift)] = fgx;					\
++		else								\
++			dd2[(shift)] = transparent ? *(type *)decor_src : bgx;	\
++		decor_src += (bpp);						\
++	} while (0)								\
++
++extern int get_color(struct vc_data *vc, struct fb_info *info,
++		     u16 c, int is_fg);
++
++void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
++{
++	int i, j, k;
++	int minlen = min(min(info->var.red.length, info->var.green.length),
++			     info->var.blue.length);
++	u32 col;
++
++	for (j = i = 0; i < 16; i++) {
++		k = color_table[i];
++
++		col = ((vc->vc_palette[j++]  >> (8-minlen))
++			<< info->var.red.offset);
++		col |= ((vc->vc_palette[j++] >> (8-minlen))
++			<< info->var.green.offset);
++		col |= ((vc->vc_palette[j++] >> (8-minlen))
++			<< info->var.blue.offset);
++			((u32 *)info->pseudo_palette)[k] = col;
++	}
++}
++
++void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height,
++		      int width, u8* src, u32 fgx, u32 bgx, u8 transparent)
++{
++	unsigned int x, y;
++	u32 dd;
++	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
++	unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
++	unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
++	u16 dd2[4];
++
++	u8* decor_src = (u8 *)(info->bgdecor.data + ds);
++	u8* dst = (u8 *)(info->screen_base + d);
++
++	if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
++		return;
++
++	for (y = 0; y < height; y++) {
++		switch (info->var.bits_per_pixel) {
++
++		case 32:
++			for (x = 0; x < width; x++) {
++
++				if ((x & 7) == 0)
++					d = *src++;
++				if (d & 0x80)
++					dd = fgx;
++				else
++					dd = transparent ?
++					     *(u32 *)decor_src : bgx;
++
++				d <<= 1;
++				decor_src += 4;
++				fb_writel(dd, dst);
++				dst += 4;
++			}
++			break;
++		case 24:
++			for (x = 0; x < width; x++) {
++
++				if ((x & 7) == 0)
++					d = *src++;
++				if (d & 0x80)
++					dd = fgx;
++				else
++					dd = transparent ?
++					     (*(u32 *)decor_src & 0xffffff) : bgx;
++
++				d <<= 1;
++				decor_src += 3;
++#ifdef __LITTLE_ENDIAN
++				fb_writew(dd & 0xffff, dst);
++				dst += 2;
++				fb_writeb((dd >> 16), dst);
++#else
++				fb_writew(dd >> 8, dst);
++				dst += 2;
++				fb_writeb(dd & 0xff, dst);
++#endif
++				dst++;
++			}
++			break;
++		case 16:
++			for (x = 0; x < width; x += 2) {
++				if ((x & 7) == 0)
++					d = *src++;
++
++				parse_pixel(0, 2, u16);
++				parse_pixel(1, 2, u16);
++#ifdef __LITTLE_ENDIAN
++				dd = dd2[0] | (dd2[1] << 16);
++#else
++				dd = dd2[1] | (dd2[0] << 16);
++#endif
++				d <<= 2;
++				fb_writel(dd, dst);
++				dst += 4;
++			}
++			break;
++
++		case 8:
++			for (x = 0; x < width; x += 4) {
++				if ((x & 7) == 0)
++					d = *src++;
++
++				parse_pixel(0, 1, u8);
++				parse_pixel(1, 1, u8);
++				parse_pixel(2, 1, u8);
++				parse_pixel(3, 1, u8);
++
++#ifdef __LITTLE_ENDIAN
++				dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
++#else
++				dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
++#endif
++				d <<= 4;
++				fb_writel(dd, dst);
++				dst += 4;
++			}
++		}
++
++		dst += info->fix.line_length - width * bytespp;
++		decor_src += (info->var.xres - width) * bytespp;
++	}
++}
++
++#define cc2cx(a) 						\
++	((info->fix.visual == FB_VISUAL_TRUECOLOR || 		\
++	  info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? 		\
++	 ((u32*)info->pseudo_palette)[a] : a)
++
++void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info,
++		   const unsigned short *s, int count, int yy, int xx)
++{
++	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
++	struct fbcon_ops *ops = info->fbcon_par;
++	int fg_color, bg_color, transparent;
++	u8 *src;
++	u32 bgx, fgx;
++	u16 c = scr_readw(s);
++
++	fg_color = get_color(vc, info, c, 1);
++        bg_color = get_color(vc, info, c, 0);
++
++	/* Don't paint the background image if console is blanked */
++	transparent = ops->blank_state ? 0 :
++		(vc->vc_decor.bg_color == bg_color);
++
++	xx = xx * vc->vc_font.width + vc->vc_decor.tx;
++	yy = yy * vc->vc_font.height + vc->vc_decor.ty;
++
++	fgx = cc2cx(fg_color);
++	bgx = cc2cx(bg_color);
++
++	while (count--) {
++		c = scr_readw(s++);
++		src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
++		      ((vc->vc_font.width + 7) >> 3);
++
++		fbcon_decor_renderc(info, yy, xx, vc->vc_font.height,
++			       vc->vc_font.width, src, fgx, bgx, transparent);
++		xx += vc->vc_font.width;
++	}
++}
++
++void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor)
++{
++	int i;
++	unsigned int dsize, s_pitch;
++	struct fbcon_ops *ops = info->fbcon_par;
++	struct vc_data* vc;
++	u8 *src;
++
++	/* we really don't need any cursors while the console is blanked */
++	if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
++		return;
++
++	vc = vc_cons[ops->currcon].d;
++
++	src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
++	if (!src)
++		return;
++
++	s_pitch = (cursor->image.width + 7) >> 3;
++	dsize = s_pitch * cursor->image.height;
++	if (cursor->enable) {
++		switch (cursor->rop) {
++		case ROP_XOR:
++			for (i = 0; i < dsize; i++)
++				src[i] = cursor->image.data[i] ^ cursor->mask[i];
++                        break;
++		case ROP_COPY:
++		default:
++			for (i = 0; i < dsize; i++)
++				src[i] = cursor->image.data[i] & cursor->mask[i];
++			break;
++		}
++	} else
++		memcpy(src, cursor->image.data, dsize);
++
++	fbcon_decor_renderc(info,
++			cursor->image.dy + vc->vc_decor.ty,
++			cursor->image.dx + vc->vc_decor.tx,
++			cursor->image.height,
++			cursor->image.width,
++			(u8*)src,
++			cc2cx(cursor->image.fg_color),
++			cc2cx(cursor->image.bg_color),
++			cursor->image.bg_color == vc->vc_decor.bg_color);
++
++	kfree(src);
++}
++
++static void decorset(u8 *dst, int height, int width, int dstbytes,
++		        u32 bgx, int bpp)
++{
++	int i;
++
++	if (bpp == 8)
++		bgx |= bgx << 8;
++	if (bpp == 16 || bpp == 8)
++		bgx |= bgx << 16;
++
++	while (height-- > 0) {
++		u8 *p = dst;
++
++		switch (bpp) {
++
++		case 32:
++			for (i=0; i < width; i++) {
++				fb_writel(bgx, p); p += 4;
++			}
++			break;
++		case 24:
++			for (i=0; i < width; i++) {
++#ifdef __LITTLE_ENDIAN
++				fb_writew((bgx & 0xffff),(u16*)p); p += 2;
++				fb_writeb((bgx >> 16),p++);
++#else
++				fb_writew((bgx >> 8),(u16*)p); p += 2;
++				fb_writeb((bgx & 0xff),p++);
++#endif
++			}
++		case 16:
++			for (i=0; i < width/4; i++) {
++				fb_writel(bgx,p); p += 4;
++				fb_writel(bgx,p); p += 4;
++			}
++			if (width & 2) {
++				fb_writel(bgx,p); p += 4;
++			}
++			if (width & 1)
++				fb_writew(bgx,(u16*)p);
++			break;
++		case 8:
++			for (i=0; i < width/4; i++) {
++				fb_writel(bgx,p); p += 4;
++			}
++
++			if (width & 2) {
++				fb_writew(bgx,p); p += 2;
++			}
++			if (width & 1)
++				fb_writeb(bgx,(u8*)p);
++			break;
++
++		}
++		dst += dstbytes;
++	}
++}
++
++void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
++		   int srclinebytes, int bpp)
++{
++	int i;
++
++	while (height-- > 0) {
++		u32 *p = (u32 *)dst;
++		u32 *q = (u32 *)src;
++
++		switch (bpp) {
++
++		case 32:
++			for (i=0; i < width; i++)
++				fb_writel(*q++, p++);
++			break;
++		case 24:
++			for (i=0; i < (width*3/4); i++)
++				fb_writel(*q++, p++);
++			if ((width*3) % 4) {
++				if (width & 2) {
++					fb_writeb(*(u8*)q, (u8*)p);
++				} else if (width & 1) {
++					fb_writew(*(u16*)q, (u16*)p);
++					fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2));
++				}
++			}
++			break;
++		case 16:
++			for (i=0; i < width/4; i++) {
++				fb_writel(*q++, p++);
++				fb_writel(*q++, p++);
++			}
++			if (width & 2)
++				fb_writel(*q++, p++);
++			if (width & 1)
++				fb_writew(*(u16*)q, (u16*)p);
++			break;
++		case 8:
++			for (i=0; i < width/4; i++)
++				fb_writel(*q++, p++);
++
++			if (width & 2) {
++				fb_writew(*(u16*)q, (u16*)p);
++				q = (u32*) ((u16*)q + 1);
++				p = (u32*) ((u16*)p + 1);
++			}
++			if (width & 1)
++				fb_writeb(*(u8*)q, (u8*)p);
++			break;
++		}
++
++		dst += linebytes;
++		src += srclinebytes;
++	}
++}
++
++static void decorfill(struct fb_info *info, int sy, int sx, int height,
++		       int width)
++{
++	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
++	int d  = sy * info->fix.line_length + sx * bytespp;
++	int ds = (sy * info->var.xres + sx) * bytespp;
++
++	fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds),
++		    height, width, info->fix.line_length, info->var.xres * bytespp,
++		    info->var.bits_per_pixel);
++}
++
++void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
++		    int height, int width)
++{
++	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
++	struct fbcon_ops *ops = info->fbcon_par;
++	u8 *dst;
++	int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info);
++
++	transparent = (vc->vc_decor.bg_color == bg_color);
++	sy = sy * vc->vc_font.height + vc->vc_decor.ty;
++	sx = sx * vc->vc_font.width + vc->vc_decor.tx;
++	height *= vc->vc_font.height;
++	width *= vc->vc_font.width;
++
++	/* Don't paint the background image if console is blanked */
++	if (transparent && !ops->blank_state) {
++		decorfill(info, sy, sx, height, width);
++	} else {
++		dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
++			     sx * ((info->var.bits_per_pixel + 7) >> 3));
++		decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
++			  info->var.bits_per_pixel);
++	}
++}
++
++void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info,
++			    int bottom_only)
++{
++	unsigned int tw = vc->vc_cols*vc->vc_font.width;
++	unsigned int th = vc->vc_rows*vc->vc_font.height;
++
++	if (!bottom_only) {
++		/* top margin */
++		decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres);
++		/* left margin */
++		decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx);
++		/* right margin */
++		decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th, 
++			   info->var.xres - vc->vc_decor.tx - tw);
++	}
++	decorfill(info, vc->vc_decor.ty + th, 0, 
++		   info->var.yres - vc->vc_decor.ty - th, info->var.xres);
++}
++
++void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, 
++			   int sx, int dx, int width)
++{
++	u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
++	u16 *s = d + (dx - sx);
++	u16 *start = d;
++	u16 *ls = d;
++	u16 *le = d + width;
++	u16 c;
++	int x = dx;
++	u16 attr = 1;
++
++	do {
++		c = scr_readw(d);
++		if (attr != (c & 0xff00)) {
++			attr = c & 0xff00;
++			if (d > start) {
++				fbcon_decor_putcs(vc, info, start, d - start, y, x);
++				x += d - start;
++				start = d;
++			}
++		}
++		if (s >= ls && s < le && c == scr_readw(s)) {
++			if (d > start) {
++				fbcon_decor_putcs(vc, info, start, d - start, y, x);
++				x += d - start + 1;
++				start = d + 1;
++			} else {
++				x++;
++				start++;
++			}
++		}
++		s++;
++		d++;
++	} while (d < le);
++	if (d > start)
++		fbcon_decor_putcs(vc, info, start, d - start, y, x);
++}
++
++void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank)
++{
++	if (blank) {
++		decorset((u8 *)info->screen_base, info->var.yres, info->var.xres,
++			  info->fix.line_length, 0, info->var.bits_per_pixel);
++	} else {
++		update_screen(vc);
++		fbcon_decor_clear_margins(vc, info, 0);
++	}
++}
++
+diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
+index f447734..da50d61 100644
+--- a/drivers/video/console/fbcon.c
++++ b/drivers/video/console/fbcon.c
+@@ -79,6 +79,7 @@
+ #include <asm/irq.h>
+ 
+ #include "fbcon.h"
++#include "../console/fbcondecor.h"
+ 
+ #ifdef FBCONDEBUG
+ #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+@@ -94,7 +95,7 @@ enum {
+ 
+ static struct display fb_display[MAX_NR_CONSOLES];
+ 
+-static signed char con2fb_map[MAX_NR_CONSOLES];
++signed char con2fb_map[MAX_NR_CONSOLES];
+ static signed char con2fb_map_boot[MAX_NR_CONSOLES];
+ 
+ static int logo_lines;
+@@ -286,7 +287,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
+ 		!vt_force_oops_output(vc);
+ }
+ 
+-static int get_color(struct vc_data *vc, struct fb_info *info,
++int get_color(struct vc_data *vc, struct fb_info *info,
+ 	      u16 c, int is_fg)
+ {
+ 	int depth = fb_get_color_depth(&info->var, &info->fix);
+@@ -551,6 +552,9 @@ static int do_fbcon_takeover(int show_logo)
+ 		info_idx = -1;
+ 	} else {
+ 		fbcon_has_console_bind = 1;
++#ifdef CONFIG_FB_CON_DECOR
++		fbcon_decor_init();
++#endif
+ 	}
+ 
+ 	return err;
+@@ -1007,6 +1011,12 @@ static const char *fbcon_startup(void)
+ 	rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ 	cols /= vc->vc_font.width;
+ 	rows /= vc->vc_font.height;
++
++	if (fbcon_decor_active(info, vc)) {
++		cols = vc->vc_decor.twidth / vc->vc_font.width;
++		rows = vc->vc_decor.theight / vc->vc_font.height;
++	}
++
+ 	vc_resize(vc, cols, rows);
+ 
+ 	DPRINTK("mode:   %s\n", info->fix.id);
+@@ -1036,7 +1046,7 @@ static void fbcon_init(struct vc_data *vc, int init)
+ 	cap = info->flags;
+ 
+ 	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
+-	    (info->fix.type == FB_TYPE_TEXT))
++	    (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc))
+ 		logo = 0;
+ 
+ 	if (var_to_display(p, &info->var, info))
+@@ -1260,6 +1270,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
+ 		fbcon_clear_margins(vc, 0);
+ 	}
+ 
++ 	if (fbcon_decor_active(info, vc)) {
++ 		fbcon_decor_clear(vc, info, sy, sx, height, width);
++ 		return;
++ 	}
++
+ 	/* Split blits that cross physical y_wrap boundary */
+ 
+ 	y_break = p->vrows - p->yscroll;
+@@ -1279,10 +1294,15 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
+ 	struct display *p = &fb_display[vc->vc_num];
+ 	struct fbcon_ops *ops = info->fbcon_par;
+ 
+-	if (!fbcon_is_inactive(vc, info))
+-		ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
+-			   get_color(vc, info, scr_readw(s), 1),
+-			   get_color(vc, info, scr_readw(s), 0));
++	if (!fbcon_is_inactive(vc, info)) {
++
++		if (fbcon_decor_active(info, vc))
++			fbcon_decor_putcs(vc, info, s, count, ypos, xpos);
++		else
++			ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
++				   get_color(vc, info, scr_readw(s), 1),
++				   get_color(vc, info, scr_readw(s), 0));
++	}
+ }
+ 
+ static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
+@@ -1298,8 +1318,13 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
+ 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+ 	struct fbcon_ops *ops = info->fbcon_par;
+ 
+-	if (!fbcon_is_inactive(vc, info))
+-		ops->clear_margins(vc, info, bottom_only);
++	if (!fbcon_is_inactive(vc, info)) {
++	 	if (fbcon_decor_active(info, vc)) {
++	 		fbcon_decor_clear_margins(vc, info, bottom_only);
++ 		} else {
++			ops->clear_margins(vc, info, bottom_only);
++		}
++	}
+ }
+ 
+ static void fbcon_cursor(struct vc_data *vc, int mode)
+@@ -1819,7 +1844,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
+ 			count = vc->vc_rows;
+ 		if (softback_top)
+ 			fbcon_softback_note(vc, t, count);
+-		if (logo_shown >= 0)
++		if (logo_shown >= 0 || fbcon_decor_active(info, vc))
+ 			goto redraw_up;
+ 		switch (p->scrollmode) {
+ 		case SCROLL_MOVE:
+@@ -1912,6 +1937,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
+ 			count = vc->vc_rows;
+ 		if (logo_shown >= 0)
+ 			goto redraw_down;
++		if (fbcon_decor_active(info, vc))
++			goto redraw_down;
+ 		switch (p->scrollmode) {
+ 		case SCROLL_MOVE:
+ 			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+@@ -2060,6 +2087,13 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s
+ 		}
+ 		return;
+ 	}
++
++	if (fbcon_decor_active(info, vc) && sy == dy && height == 1) {
++ 		/* must use slower redraw bmove to keep background pic intact */
++ 		fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width);
++ 		return;
++ 	}
++
+ 	ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
+ 		   height, width);
+ }
+@@ -2130,8 +2164,8 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
+ 	var.yres = virt_h * virt_fh;
+ 	x_diff = info->var.xres - var.xres;
+ 	y_diff = info->var.yres - var.yres;
+-	if (x_diff < 0 || x_diff > virt_fw ||
+-	    y_diff < 0 || y_diff > virt_fh) {
++	if ((x_diff < 0 || x_diff > virt_fw ||
++		y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) {
+ 		const struct fb_videomode *mode;
+ 
+ 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
+@@ -2167,6 +2201,21 @@ static int fbcon_switch(struct vc_data *vc)
+ 
+ 	info = registered_fb[con2fb_map[vc->vc_num]];
+ 	ops = info->fbcon_par;
++	prev_console = ops->currcon;
++	if (prev_console != -1)
++		old_info = registered_fb[con2fb_map[prev_console]];
++
++#ifdef CONFIG_FB_CON_DECOR
++	if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
++		struct vc_data *vc_curr = vc_cons[prev_console].d;
++		if (vc_curr && fbcon_decor_active_vc(vc_curr)) {
++			/* Clear the screen to avoid displaying funky colors during
++			 * palette updates. */
++			memset((u8*)info->screen_base + info->fix.line_length * info->var.yoffset,
++			       0, info->var.yres * info->fix.line_length);
++		}
++	}
++#endif
+ 
+ 	if (softback_top) {
+ 		if (softback_lines)
+@@ -2185,9 +2234,6 @@ static int fbcon_switch(struct vc_data *vc)
+ 		logo_shown = FBCON_LOGO_CANSHOW;
+ 	}
+ 
+-	prev_console = ops->currcon;
+-	if (prev_console != -1)
+-		old_info = registered_fb[con2fb_map[prev_console]];
+ 	/*
+ 	 * FIXME: If we have multiple fbdev's loaded, we need to
+ 	 * update all info->currcon.  Perhaps, we can place this
+@@ -2231,6 +2277,18 @@ static int fbcon_switch(struct vc_data *vc)
+ 			fbcon_del_cursor_timer(old_info);
+ 	}
+ 
++	if (fbcon_decor_active_vc(vc)) {
++		struct vc_data *vc_curr = vc_cons[prev_console].d;
++
++		if (!vc_curr->vc_decor.theme ||
++			strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) ||
++			(fbcon_decor_active_nores(info, vc_curr) &&
++			 !fbcon_decor_active(info, vc_curr))) {
++			fbcon_decor_disable(vc, 0);
++			fbcon_decor_call_helper("modechange", vc->vc_num);
++		}
++	}
++
+ 	if (fbcon_is_inactive(vc, info) ||
+ 	    ops->blank_state != FB_BLANK_UNBLANK)
+ 		fbcon_del_cursor_timer(info);
+@@ -2339,15 +2397,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
+ 		}
+ 	}
+ 
+- 	if (!fbcon_is_inactive(vc, info)) {
++	if (!fbcon_is_inactive(vc, info)) {
+ 		if (ops->blank_state != blank) {
+ 			ops->blank_state = blank;
+ 			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
+ 			ops->cursor_flash = (!blank);
+ 
+-			if (!(info->flags & FBINFO_MISC_USEREVENT))
+-				if (fb_blank(info, blank))
+-					fbcon_generic_blank(vc, info, blank);
++			if (!(info->flags & FBINFO_MISC_USEREVENT)) {
++				if (fb_blank(info, blank)) {
++					if (fbcon_decor_active(info, vc))
++						fbcon_decor_blank(vc, info, blank);
++					else
++						fbcon_generic_blank(vc, info, blank);
++				}
++			}
+ 		}
+ 
+ 		if (!blank)
+@@ -2522,13 +2585,22 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
+ 	}
+ 
+ 	if (resize) {
++		/* reset wrap/pan */
+ 		int cols, rows;
+ 
+ 		cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+ 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++
++		if (fbcon_decor_active(info, vc)) {
++			info->var.xoffset = info->var.yoffset = p->yscroll = 0;
++			cols = vc->vc_decor.twidth;
++			rows = vc->vc_decor.theight;
++		}
+ 		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)
+@@ -2657,7 +2729,11 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
+ 	int i, j, k, depth;
+ 	u8 val;
+ 
+-	if (fbcon_is_inactive(vc, info))
++	if (fbcon_is_inactive(vc, info)
++#ifdef CONFIG_FB_CON_DECOR
++			|| vc->vc_num != fg_console
++#endif
++		)
+ 		return -EINVAL;
+ 
+ 	if (!CON_IS_VISIBLE(vc))
+@@ -2683,14 +2759,56 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
+ 	} else
+ 		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
+ 
+-	return fb_set_cmap(&palette_cmap, info);
++	if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
++	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
++
++		u16 *red, *green, *blue;
++		int minlen = min(min(info->var.red.length, info->var.green.length),
++				     info->var.blue.length);
++		int h;
++
++		struct fb_cmap cmap = {
++			.start = 0,
++			.len = (1 << minlen),
++			.red = NULL,
++			.green = NULL,
++			.blue = NULL,
++			.transp = NULL
++		};
++
++		red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
++
++		if (!red)
++			goto out;
++
++		green = red + 256;
++		blue = green + 256;
++		cmap.red = red;
++		cmap.green = green;
++		cmap.blue = blue;
++
++		for (i = 0; i < cmap.len; i++) {
++			red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
++		}
++
++		h = fb_set_cmap(&cmap, info);
++		fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
++		kfree(red);
++
++		return h;
++
++	} else if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
++		   info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL)
++		fb_set_cmap(&info->bgdecor.cmap, info);
++
++out:	return fb_set_cmap(&palette_cmap, info);
+ }
+ 
+ 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;
+@@ -2909,7 +3027,14 @@ static void fbcon_modechanged(struct fb_info *info)
+ 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ 		cols /= vc->vc_font.width;
+ 		rows /= vc->vc_font.height;
+-		vc_resize(vc, cols, rows);
++
++		if (!fbcon_decor_active_nores(info, vc)) {
++			vc_resize(vc, cols, rows);
++		} else {
++			fbcon_decor_disable(vc, 0);
++			fbcon_decor_call_helper("modechange", vc->vc_num);
++		}
++
+ 		updatescrollmode(p, info, vc);
+ 		scrollback_max = 0;
+ 		scrollback_current = 0;
+@@ -2954,7 +3079,9 @@ static void fbcon_set_all_vcs(struct fb_info *info)
+ 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ 		cols /= vc->vc_font.width;
+ 		rows /= vc->vc_font.height;
+-		vc_resize(vc, cols, rows);
++		if (!fbcon_decor_active_nores(info, vc)) {
++			vc_resize(vc, cols, rows);
++		}
+ 	}
+ 
+ 	if (fg != -1)
+@@ -3596,6 +3723,7 @@ static void fbcon_exit(void)
+ 		}
+ 	}
+ 
++	fbcon_decor_exit();
+ 	fbcon_has_exited = 1;
+ }
+ 
+diff --git a/drivers/video/console/fbcondecor.c b/drivers/video/console/fbcondecor.c
+new file mode 100644
+index 0000000..babc8c5
+--- /dev/null
++++ b/drivers/video/console/fbcondecor.c
+@@ -0,0 +1,555 @@
++/*
++ *  linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations
++ *
++ *  Copyright (C) 2004-2009 Michal Januszewski <michalj+fbcondecor@gmail.com>
++ *
++ *  Code based upon "Bootsplash" (C) 2001-2003
++ *       Volker Poplawski <volker@poplawski.de>,
++ *       Stefan Reinauer <stepan@suse.de>,
++ *       Steffen Winterfeldt <snwint@suse.de>,
++ *       Michael Schroeder <mls@suse.de>,
++ *       Ken Wimer <wimer@suse.de>.
++ *
++ *  Compat ioctl support by Thorsten Klein <TK@Thorsten-Klein.de>.
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License.  See the file COPYING in the main directory of this archive for
++ *  more details.
++ *
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/fb.h>
++#include <linux/vt_kern.h>
++#include <linux/vmalloc.h>
++#include <linux/unistd.h>
++#include <linux/syscalls.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/workqueue.h>
++#include <linux/kmod.h>
++#include <linux/miscdevice.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/compat.h>
++#include <linux/console.h>
++
++#include <asm/uaccess.h>
++#include <asm/irq.h>
++
++#include "fbcon.h"
++#include "fbcondecor.h"
++
++extern signed char con2fb_map[];
++static int fbcon_decor_enable(struct vc_data *vc);
++char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper";
++static int initialized = 0;
++
++int fbcon_decor_call_helper(char* cmd, unsigned short vc)
++{
++	char *envp[] = {
++		"HOME=/",
++		"PATH=/sbin:/bin",
++		NULL
++	};
++
++	char tfb[5];
++	char tcons[5];
++	unsigned char fb = (int) con2fb_map[vc];
++
++	char *argv[] = {
++		fbcon_decor_path,
++		"2",
++		cmd,
++		tcons,
++		tfb,
++		vc_cons[vc].d->vc_decor.theme,
++		NULL
++	};
++
++	snprintf(tfb,5,"%d",fb);
++	snprintf(tcons,5,"%d",vc);
++
++	return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC);
++}
++
++/* Disables fbcondecor on a virtual console; called with console sem held. */
++int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw)
++{
++	struct fb_info* info;
++
++	if (!vc->vc_decor.state)
++		return -EINVAL;
++
++	info = registered_fb[(int) con2fb_map[vc->vc_num]];
++
++	if (info == NULL)
++		return -EINVAL;
++
++	vc->vc_decor.state = 0;
++	vc_resize(vc, info->var.xres / vc->vc_font.width,
++		  info->var.yres / vc->vc_font.height);
++
++	if (fg_console == vc->vc_num && redraw) {
++		redraw_screen(vc, 0);
++		update_region(vc, vc->vc_origin +
++			      vc->vc_size_row * vc->vc_top,
++			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
++	}
++
++	printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n",
++			 vc->vc_num);
++
++	return 0;
++}
++
++/* Enables fbcondecor on a virtual console; called with console sem held. */
++static int fbcon_decor_enable(struct vc_data *vc)
++{
++	struct fb_info* info;
++
++	info = registered_fb[(int) con2fb_map[vc->vc_num]];
++
++	if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 ||
++	    info == NULL || vc->vc_decor.state || (!info->bgdecor.data &&
++	    vc->vc_num == fg_console))
++		return -EINVAL;
++
++	vc->vc_decor.state = 1;
++	vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width,
++		  vc->vc_decor.theight / vc->vc_font.height);
++
++	if (fg_console == vc->vc_num) {
++		redraw_screen(vc, 0);
++		update_region(vc, vc->vc_origin +
++			      vc->vc_size_row * vc->vc_top,
++			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
++		fbcon_decor_clear_margins(vc, info, 0);
++	}
++
++	printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n",
++			 vc->vc_num);
++
++	return 0;
++}
++
++static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin)
++{
++	int ret;
++
++//	if (origin == FBCON_DECOR_IO_ORIG_USER)
++		console_lock();
++	if (!state)
++		ret = fbcon_decor_disable(vc, 1);
++	else
++		ret = fbcon_decor_enable(vc);
++//	if (origin == FBCON_DECOR_IO_ORIG_USER)
++		console_unlock();
++
++	return ret;
++}
++
++static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state)
++{
++	*state = vc->vc_decor.state;
++}
++
++static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin)
++{
++	struct fb_info *info;
++	int len;
++	char *tmp;
++
++	info = registered_fb[(int) con2fb_map[vc->vc_num]];
++
++	if (info == NULL || !cfg->twidth || !cfg->theight ||
++	    cfg->tx + cfg->twidth  > info->var.xres ||
++	    cfg->ty + cfg->theight > info->var.yres)
++		return -EINVAL;
++
++	len = strlen_user(cfg->theme);
++	if (!len || len > FBCON_DECOR_THEME_LEN)
++		return -EINVAL;
++	tmp = kmalloc(len, GFP_KERNEL);
++	if (!tmp)
++		return -ENOMEM;
++	if (copy_from_user(tmp, (void __user *)cfg->theme, len))
++		return -EFAULT;
++	cfg->theme = tmp;
++	cfg->state = 0;
++
++	/* If this ioctl is a response to a request from kernel, the console sem
++	 * is already held; we also don't need to disable decor because either the
++	 * new config and background picture will be successfully loaded, and the
++	 * decor will stay on, or in case of a failure it'll be turned off in fbcon. */
++//	if (origin == FBCON_DECOR_IO_ORIG_USER) {
++		console_lock();
++		if (vc->vc_decor.state)
++			fbcon_decor_disable(vc, 1);
++//	}
++
++	if (vc->vc_decor.theme)
++		kfree(vc->vc_decor.theme);
++
++	vc->vc_decor = *cfg;
++
++//	if (origin == FBCON_DECOR_IO_ORIG_USER)
++		console_unlock();
++
++	printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n",
++			 vc->vc_num, vc->vc_decor.theme);
++	return 0;
++}
++
++static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc, struct vc_decor *decor)
++{
++	char __user *tmp;
++
++	tmp = decor->theme;
++	*decor = vc->vc_decor;
++	decor->theme = tmp;
++
++	if (vc->vc_decor.theme) {
++		if (copy_to_user(tmp, vc->vc_decor.theme, strlen(vc->vc_decor.theme) + 1))
++			return -EFAULT;
++	} else
++		if (put_user(0, tmp))
++			return -EFAULT;
++
++	return 0;
++}
++
++static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img, unsigned char origin)
++{
++	struct fb_info *info;
++	int len;
++	u8 *tmp;
++
++	if (vc->vc_num != fg_console)
++		return -EINVAL;
++
++	info = registered_fb[(int) con2fb_map[vc->vc_num]];
++
++	if (info == NULL)
++		return -EINVAL;
++
++	if (img->width != info->var.xres || img->height != info->var.yres) {
++		printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n");
++		printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height, info->var.xres, info->var.yres);
++		return -EINVAL;
++	}
++
++	if (img->depth != info->var.bits_per_pixel) {
++		printk(KERN_ERR "fbcondecor: picture depth mismatch\n");
++		return -EINVAL;
++	}
++
++	if (img->depth == 8) {
++		if (!img->cmap.len || !img->cmap.red || !img->cmap.green ||
++		    !img->cmap.blue)
++			return -EINVAL;
++
++		tmp = vmalloc(img->cmap.len * 3 * 2);
++		if (!tmp)
++			return -ENOMEM;
++
++		if (copy_from_user(tmp,
++			    	   (void __user*)img->cmap.red, (img->cmap.len << 1)) ||
++		    copy_from_user(tmp + (img->cmap.len << 1),
++			    	   (void __user*)img->cmap.green, (img->cmap.len << 1)) ||
++		    copy_from_user(tmp + (img->cmap.len << 2),
++			    	   (void __user*)img->cmap.blue, (img->cmap.len << 1))) {
++			vfree(tmp);
++			return -EFAULT;
++		}
++
++		img->cmap.transp = NULL;
++		img->cmap.red = (u16*)tmp;
++		img->cmap.green = img->cmap.red + img->cmap.len;
++		img->cmap.blue = img->cmap.green + img->cmap.len;
++	} else {
++		img->cmap.red = NULL;
++	}
++
++	len = ((img->depth + 7) >> 3) * img->width * img->height;
++
++	/*
++	 * Allocate an additional byte so that we never go outside of the
++	 * buffer boundaries in the rendering functions in a 24 bpp mode.
++	 */
++	tmp = vmalloc(len + 1);
++
++	if (!tmp)
++		goto out;
++
++	if (copy_from_user(tmp, (void __user*)img->data, len))
++		goto out;
++
++	img->data = tmp;
++
++	/* If this ioctl is a response to a request from kernel, the console sem
++	 * is already held. */
++//	if (origin == FBCON_DECOR_IO_ORIG_USER)
++		console_lock();
++
++	if (info->bgdecor.data)
++		vfree((u8*)info->bgdecor.data);
++	if (info->bgdecor.cmap.red)
++		vfree(info->bgdecor.cmap.red);
++
++	info->bgdecor = *img;
++
++	if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) {
++		redraw_screen(vc, 0);
++		update_region(vc, vc->vc_origin +
++			      vc->vc_size_row * vc->vc_top,
++			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
++		fbcon_decor_clear_margins(vc, info, 0);
++	}
++
++//	if (origin == FBCON_DECOR_IO_ORIG_USER)
++		console_unlock();
++
++	return 0;
++
++out:	if (img->cmap.red)
++		vfree(img->cmap.red);
++
++	if (tmp)
++		vfree(tmp);
++	return -ENOMEM;
++}
++
++static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg)
++{
++	struct fbcon_decor_iowrapper __user *wrapper = (void __user*) arg;
++	struct vc_data *vc = NULL;
++	unsigned short vc_num = 0;
++	unsigned char origin = 0;
++	void __user *data = NULL;
++
++	if (!access_ok(VERIFY_READ, wrapper,
++			sizeof(struct fbcon_decor_iowrapper)))
++		return -EFAULT;
++
++	__get_user(vc_num, &wrapper->vc);
++	__get_user(origin, &wrapper->origin);
++	__get_user(data, &wrapper->data);
++
++	if (!vc_cons_allocated(vc_num))
++		return -EINVAL;
++
++	vc = vc_cons[vc_num].d;
++
++	switch (cmd) {
++	case FBIOCONDECOR_SETPIC:
++	{
++		struct fb_image img;
++		if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image)))
++			return -EFAULT;
++
++		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
++	}
++	case FBIOCONDECOR_SETCFG:
++	{
++		struct vc_decor cfg;
++		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
++			return -EFAULT;
++
++		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
++	}
++	case FBIOCONDECOR_GETCFG:
++	{
++		int rval;
++		struct vc_decor cfg;
++
++		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
++			return -EFAULT;
++
++		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
++
++		if (copy_to_user(data, &cfg, sizeof(struct vc_decor)))
++			return -EFAULT;
++		return rval;
++	}
++	case FBIOCONDECOR_SETSTATE:
++	{
++		unsigned int state = 0;
++		if (get_user(state, (unsigned int __user *)data))
++			return -EFAULT;
++		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
++	}
++	case FBIOCONDECOR_GETSTATE:
++	{
++		unsigned int state = 0;
++		fbcon_decor_ioctl_dogetstate(vc, &state);
++		return put_user(state, (unsigned int __user *)data);
++	}
++
++	default:
++		return -ENOIOCTLCMD;
++	}
++}
++
++#ifdef CONFIG_COMPAT
++
++static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
++
++	struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg;
++	struct vc_data *vc = NULL;
++	unsigned short vc_num = 0;
++	unsigned char origin = 0;
++	compat_uptr_t data_compat = 0;
++	void __user *data = NULL;
++
++	if (!access_ok(VERIFY_READ, wrapper,
++                       sizeof(struct fbcon_decor_iowrapper32)))
++		return -EFAULT;
++
++	__get_user(vc_num, &wrapper->vc);
++	__get_user(origin, &wrapper->origin);
++	__get_user(data_compat, &wrapper->data);
++	data = compat_ptr(data_compat);
++
++	if (!vc_cons_allocated(vc_num))
++		return -EINVAL;
++
++	vc = vc_cons[vc_num].d;
++
++	switch (cmd) {
++	case FBIOCONDECOR_SETPIC32:
++	{
++		struct fb_image32 img_compat;
++		struct fb_image img;
++
++		if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32)))
++			return -EFAULT;
++
++		fb_image_from_compat(img, img_compat);
++
++		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
++	}
++
++	case FBIOCONDECOR_SETCFG32:
++	{
++		struct vc_decor32 cfg_compat;
++		struct vc_decor cfg;
++
++		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
++			return -EFAULT;
++
++		vc_decor_from_compat(cfg, cfg_compat);
++
++		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
++	}
++
++	case FBIOCONDECOR_GETCFG32:
++	{
++		int rval;
++		struct vc_decor32 cfg_compat;
++		struct vc_decor cfg;
++
++		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
++			return -EFAULT;
++		cfg.theme = compat_ptr(cfg_compat.theme);
++
++		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
++
++		vc_decor_to_compat(cfg_compat, cfg);
++
++		if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32)))
++			return -EFAULT;
++		return rval;
++	}
++
++	case FBIOCONDECOR_SETSTATE32:
++	{
++		compat_uint_t state_compat = 0;
++		unsigned int state = 0;
++
++		if (get_user(state_compat, (compat_uint_t __user *)data))
++			return -EFAULT;
++
++		state = (unsigned int)state_compat;
++
++		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
++	}
++
++	case FBIOCONDECOR_GETSTATE32:
++	{
++		compat_uint_t state_compat = 0;
++		unsigned int state = 0;
++
++		fbcon_decor_ioctl_dogetstate(vc, &state);
++		state_compat = (compat_uint_t)state;
++
++		return put_user(state_compat, (compat_uint_t __user *)data);
++	}
++
++	default:
++		return -ENOIOCTLCMD;
++	}
++}
++#else
++  #define fbcon_decor_compat_ioctl NULL
++#endif
++
++static struct file_operations fbcon_decor_ops = {
++	.owner = THIS_MODULE,
++	.unlocked_ioctl = fbcon_decor_ioctl,
++	.compat_ioctl = fbcon_decor_compat_ioctl
++};
++
++static struct miscdevice fbcon_decor_dev = {
++	.minor = MISC_DYNAMIC_MINOR,
++	.name = "fbcondecor",
++	.fops = &fbcon_decor_ops
++};
++
++void fbcon_decor_reset(void)
++{
++	int i;
++
++	for (i = 0; i < num_registered_fb; i++) {
++		registered_fb[i]->bgdecor.data = NULL;
++		registered_fb[i]->bgdecor.cmap.red = NULL;
++	}
++
++	for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
++		vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth =
++						vc_cons[i].d->vc_decor.theight = 0;
++		vc_cons[i].d->vc_decor.theme = NULL;
++	}
++
++	return;
++}
++
++int fbcon_decor_init(void)
++{
++	int i;
++
++	fbcon_decor_reset();
++
++	if (initialized)
++		return 0;
++
++	i = misc_register(&fbcon_decor_dev);
++	if (i) {
++		printk(KERN_ERR "fbcondecor: failed to register device\n");
++		return i;
++	}
++
++	fbcon_decor_call_helper("init", 0);
++	initialized = 1;
++	return 0;
++}
++
++int fbcon_decor_exit(void)
++{
++	fbcon_decor_reset();
++	return 0;
++}
++
++EXPORT_SYMBOL(fbcon_decor_path);
+diff --git a/drivers/video/console/fbcondecor.h b/drivers/video/console/fbcondecor.h
+new file mode 100644
+index 0000000..3b3724b
+--- /dev/null
++++ b/drivers/video/console/fbcondecor.h
+@@ -0,0 +1,78 @@
++/* 
++ *  linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers
++ *
++ *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
++ *
++ */
++
++#ifndef __FBCON_DECOR_H
++#define __FBCON_DECOR_H
++
++#ifndef _LINUX_FB_H
++#include <linux/fb.h>
++#endif
++
++/* This is needed for vc_cons in fbcmap.c */
++#include <linux/vt_kern.h>
++
++struct fb_cursor;
++struct fb_info;
++struct vc_data;
++
++#ifdef CONFIG_FB_CON_DECOR
++/* fbcondecor.c */
++int fbcon_decor_init(void);
++int fbcon_decor_exit(void);
++int fbcon_decor_call_helper(char* cmd, unsigned short cons);
++int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw);
++
++/* cfbcondecor.c */
++void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
++void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor);
++void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
++void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
++void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank);
++void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
++void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp);
++void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc);
++
++/* vt.c */
++void acquire_console_sem(void);
++void release_console_sem(void);
++void do_unblank_screen(int entering_gfx);
++
++/* struct vc_data *y */
++#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme) 
++
++/* struct fb_info *x, struct vc_data *y */
++#define fbcon_decor_active_nores(x,y) (x->bgdecor.data && fbcon_decor_active_vc(y))
++
++/* struct fb_info *x, struct vc_data *y */
++#define fbcon_decor_active(x,y) (fbcon_decor_active_nores(x,y) &&		\
++			      x->bgdecor.width == x->var.xres && 	\
++			      x->bgdecor.height == x->var.yres &&	\
++			      x->bgdecor.depth == x->var.bits_per_pixel)
++
++
++#else /* CONFIG_FB_CON_DECOR */
++
++static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
++static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
++static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
++static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
++static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
++static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
++static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
++static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {}
++static inline int fbcon_decor_call_helper(char* cmd, unsigned short cons) { return 0; }
++static inline int fbcon_decor_init(void) { return 0; }
++static inline int fbcon_decor_exit(void) { return 0; }
++static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
++
++#define fbcon_decor_active_vc(y) (0)
++#define fbcon_decor_active_nores(x,y) (0)
++#define fbcon_decor_active(x,y) (0)
++
++#endif /* CONFIG_FB_CON_DECOR */
++
++#endif /* __FBCON_DECOR_H */
+diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
+index e1f4727..2952e33 100644
+--- a/drivers/video/fbdev/Kconfig
++++ b/drivers/video/fbdev/Kconfig
+@@ -1204,7 +1204,6 @@ config FB_MATROX
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+-	select FB_TILEBLITTING
+ 	select FB_MACMODES if PPC_PMAC
+ 	---help---
+ 	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
+diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
+index f89245b..05e036c 100644
+--- a/drivers/video/fbdev/core/fbcmap.c
++++ b/drivers/video/fbdev/core/fbcmap.c
+@@ -17,6 +17,8 @@
+ #include <linux/slab.h>
+ #include <linux/uaccess.h>
+ 
++#include "../../console/fbcondecor.h"
++
+ static u16 red2[] __read_mostly = {
+     0x0000, 0xaaaa
+ };
+@@ -249,14 +251,17 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
+ 			if (transp)
+ 				htransp = *transp++;
+ 			if (info->fbops->fb_setcolreg(start++,
+-						      hred, hgreen, hblue,
++						      hred, hgreen, hblue, 
+ 						      htransp, info))
+ 				break;
+ 		}
+ 	}
+-	if (rc == 0)
++	if (rc == 0) {
+ 		fb_copy_cmap(cmap, &info->cmap);
+-
++		if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
++		    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
++			fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
++	}
+ 	return rc;
+ }
+ 
+diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
+index b6d5008..d6703f2 100644
+--- a/drivers/video/fbdev/core/fbmem.c
++++ b/drivers/video/fbdev/core/fbmem.c
+@@ -1250,15 +1250,6 @@ struct fb_fix_screeninfo32 {
+ 	u16			reserved[3];
+ };
+ 
+-struct fb_cmap32 {
+-	u32			start;
+-	u32			len;
+-	compat_caddr_t	red;
+-	compat_caddr_t	green;
+-	compat_caddr_t	blue;
+-	compat_caddr_t	transp;
+-};
+-
+ static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
+ 			  unsigned long arg)
+ {
+diff --git a/include/linux/console_decor.h b/include/linux/console_decor.h
+new file mode 100644
+index 0000000..04b8d80
+--- /dev/null
++++ b/include/linux/console_decor.h
+@@ -0,0 +1,46 @@
++#ifndef _LINUX_CONSOLE_DECOR_H_
++#define _LINUX_CONSOLE_DECOR_H_ 1
++
++/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */
++struct vc_decor {
++	__u8 bg_color;				/* The color that is to be treated as transparent */
++	__u8 state;				/* Current decor state: 0 = off, 1 = on */
++	__u16 tx, ty;				/* Top left corner coordinates of the text field */
++	__u16 twidth, theight;			/* Width and height of the text field */
++	char* theme;
++};
++
++#ifdef __KERNEL__
++#ifdef CONFIG_COMPAT
++#include <linux/compat.h>
++
++struct vc_decor32 {
++	__u8 bg_color;				/* The color that is to be treated as transparent */
++	__u8 state;				/* Current decor state: 0 = off, 1 = on */
++	__u16 tx, ty;				/* Top left corner coordinates of the text field */
++	__u16 twidth, theight;			/* Width and height of the text field */
++	compat_uptr_t theme;
++};
++
++#define vc_decor_from_compat(to, from) \
++	(to).bg_color = (from).bg_color; \
++	(to).state    = (from).state; \
++	(to).tx       = (from).tx; \
++	(to).ty       = (from).ty; \
++	(to).twidth   = (from).twidth; \
++	(to).theight  = (from).theight; \
++	(to).theme    = compat_ptr((from).theme)
++
++#define vc_decor_to_compat(to, from) \
++	(to).bg_color = (from).bg_color; \
++	(to).state    = (from).state; \
++	(to).tx       = (from).tx; \
++	(to).ty       = (from).ty; \
++	(to).twidth   = (from).twidth; \
++	(to).theight  = (from).theight; \
++	(to).theme    = ptr_to_compat((from).theme)
++
++#endif /* CONFIG_COMPAT */
++#endif /* __KERNEL__ */
++
++#endif
+diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
+index 7f0c329..98f5d60 100644
+--- a/include/linux/console_struct.h
++++ b/include/linux/console_struct.h
+@@ -19,6 +19,7 @@
+ struct vt_struct;
+ 
+ #define NPAR 16
++#include <linux/console_decor.h>
+ 
+ struct vc_data {
+ 	struct tty_port port;			/* Upper level data */
+@@ -107,6 +108,8 @@ struct vc_data {
+ 	unsigned long	vc_uni_pagedir;
+ 	unsigned long	*vc_uni_pagedir_loc;  /* [!] Location of uni_pagedir variable for this console */
+ 	bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
++
++	struct vc_decor vc_decor;
+ 	/* additional information is in vt_kern.h */
+ };
+ 
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index fe6ac95..1e36b03 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -219,6 +219,34 @@ struct fb_deferred_io {
+ };
+ #endif
+ 
++#ifdef __KERNEL__
++#ifdef CONFIG_COMPAT
++struct fb_image32 {
++	__u32 dx;			/* Where to place image */
++	__u32 dy;
++	__u32 width;			/* Size of image */
++	__u32 height;
++	__u32 fg_color;			/* Only used when a mono bitmap */
++	__u32 bg_color;
++	__u8  depth;			/* Depth of the image */
++	const compat_uptr_t data;	/* Pointer to image data */
++	struct fb_cmap32 cmap;		/* color map info */
++};
++
++#define fb_image_from_compat(to, from) \
++	(to).dx       = (from).dx; \
++	(to).dy       = (from).dy; \
++	(to).width    = (from).width; \
++	(to).height   = (from).height; \
++	(to).fg_color = (from).fg_color; \
++	(to).bg_color = (from).bg_color; \
++	(to).depth    = (from).depth; \
++	(to).data     = compat_ptr((from).data); \
++	fb_cmap_from_compat((to).cmap, (from).cmap)
++
++#endif /* CONFIG_COMPAT */
++#endif /* __KERNEL__ */
++
+ /*
+  * Frame buffer operations
+  *
+@@ -489,6 +517,9 @@ struct fb_info {
+ #define FBINFO_STATE_SUSPENDED	1
+ 	u32 state;			/* Hardware state i.e suspend */
+ 	void *fbcon_par;                /* fbcon use-only private area */
++
++	struct fb_image bgdecor;
++
+ 	/* From here on everything is device dependent */
+ 	void *par;
+ 	/* we need the PCI or similar aperture base/size not
+diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h
+index fb795c3..dc77a03 100644
+--- a/include/uapi/linux/fb.h
++++ b/include/uapi/linux/fb.h
+@@ -8,6 +8,25 @@
+ 
+ #define FB_MAX			32	/* sufficient for now */
+ 
++struct fbcon_decor_iowrapper
++{
++	unsigned short vc;		/* Virtual console */
++	unsigned char origin;		/* Point of origin of the request */
++	void *data;
++};
++
++#ifdef __KERNEL__
++#ifdef CONFIG_COMPAT
++#include <linux/compat.h>
++struct fbcon_decor_iowrapper32
++{
++	unsigned short vc;		/* Virtual console */
++	unsigned char origin;		/* Point of origin of the request */
++	compat_uptr_t data;
++};
++#endif /* CONFIG_COMPAT */
++#endif /* __KERNEL__ */
++
+ /* ioctls
+    0x46 is 'F'								*/
+ #define FBIOGET_VSCREENINFO	0x4600
+@@ -35,6 +54,25 @@
+ #define FBIOGET_DISPINFO        0x4618
+ #define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
+ 
++#define FBIOCONDECOR_SETCFG	_IOWR('F', 0x19, struct fbcon_decor_iowrapper)
++#define FBIOCONDECOR_GETCFG	_IOR('F', 0x1A, struct fbcon_decor_iowrapper)
++#define FBIOCONDECOR_SETSTATE	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
++#define FBIOCONDECOR_GETSTATE	_IOR('F', 0x1C, struct fbcon_decor_iowrapper)
++#define FBIOCONDECOR_SETPIC 	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
++#ifdef __KERNEL__
++#ifdef CONFIG_COMPAT
++#define FBIOCONDECOR_SETCFG32	_IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
++#define FBIOCONDECOR_GETCFG32	_IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
++#define FBIOCONDECOR_SETSTATE32	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
++#define FBIOCONDECOR_GETSTATE32	_IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
++#define FBIOCONDECOR_SETPIC32	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
++#endif /* CONFIG_COMPAT */
++#endif /* __KERNEL__ */
++
++#define FBCON_DECOR_THEME_LEN		128	/* Maximum lenght of a theme name */
++#define FBCON_DECOR_IO_ORIG_KERNEL	0	/* Kernel ioctl origin */
++#define FBCON_DECOR_IO_ORIG_USER	1	/* User ioctl origin */
++ 
+ #define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/
+ #define FB_TYPE_PLANES			1	/* Non interleaved planes */
+ #define FB_TYPE_INTERLEAVED_PLANES	2	/* Interleaved planes	*/
+@@ -277,6 +315,29 @@ struct fb_var_screeninfo {
+ 	__u32 reserved[4];		/* Reserved for future compatibility */
+ };
+ 
++#ifdef __KERNEL__
++#ifdef CONFIG_COMPAT
++struct fb_cmap32 {
++	__u32 start;
++	__u32 len;			/* Number of entries */
++	compat_uptr_t red;		/* Red values	*/
++	compat_uptr_t green;
++	compat_uptr_t blue;
++	compat_uptr_t transp;		/* transparency, can be NULL */
++};
++
++#define fb_cmap_from_compat(to, from) \
++	(to).start  = (from).start; \
++	(to).len    = (from).len; \
++	(to).red    = compat_ptr((from).red); \
++	(to).green  = compat_ptr((from).green); \
++	(to).blue   = compat_ptr((from).blue); \
++	(to).transp = compat_ptr((from).transp)
++
++#endif /* CONFIG_COMPAT */
++#endif /* __KERNEL__ */
++
++
+ struct fb_cmap {
+ 	__u32 start;			/* First entry	*/
+ 	__u32 len;			/* Number of entries */
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 74f5b58..6386ab0 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -146,6 +146,10 @@ static const int cap_last_cap = CAP_LAST_CAP;
+ static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
+ #endif
+ 
++#ifdef CONFIG_FB_CON_DECOR
++extern char fbcon_decor_path[];
++#endif
++
+ #ifdef CONFIG_INOTIFY_USER
+ #include <linux/inotify.h>
+ #endif
+@@ -255,6 +259,15 @@ static struct ctl_table sysctl_base_table[] = {
+ 		.mode		= 0555,
+ 		.child		= dev_table,
+ 	},
++#ifdef CONFIG_FB_CON_DECOR
++	{
++		.procname	= "fbcondecor",
++		.data		= &fbcon_decor_path,
++		.maxlen		= KMOD_PATH_LEN,
++		.mode		= 0644,
++		.proc_handler	= &proc_dostring,
++	},
++#endif
+ 	{ }
+ };
+ 
Index: npl/kernel/linux_src/fbcondecor-5.10.patch
===================================================================
--- npl/kernel/linux_src/fbcondecor-5.10.patch	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ 	(revision )
@@ -1,2057 +1,0 @@
-diff -Naur vanilla-5.10/Documentation/fb/fbcondecor.txt linux-5.10/Documentation/fb/fbcondecor.txt
---- vanilla-5.10/Documentation/fb/fbcondecor.txt	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.10/Documentation/fb/fbcondecor.txt	2019-10-19 18:35:55.881917873 +0200
-@@ -0,0 +1,207 @@
-+What is it?
-+-----------
-+
-+The framebuffer decorations are a kernel feature which allows displaying a
-+background picture on selected consoles.
-+
-+What do I need to get it to work?
-+---------------------------------
-+
-+To get fbcondecor up-and-running you will have to:
-+ 1) get a copy of splashutils [1] or a similar program
-+ 2) get some fbcondecor themes
-+ 3) build the kernel helper program
-+ 4) build your kernel with the FB_CON_DECOR option enabled.
-+
-+To get fbcondecor operational right after fbcon initialization is finished, you
-+will have to include a theme and the kernel helper into your initramfs image.
-+Please refer to splashutils documentation for instructions on how to do that.
-+
-+[1] The splashutils package can be downloaded from:
-+    http://github.com/alanhaggai/fbsplash
-+
-+The userspace helper
-+--------------------
-+
-+The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the
-+kernel whenever an important event occurs and the kernel needs some kind of
-+job to be carried out. Important events include console switches and video
-+mode switches (the kernel requests background images and configuration
-+parameters for the current console). The fbcondecor helper must be accessible at
-+all times. If it's not, fbcondecor will be switched off automatically.
-+
-+It's possible to set path to the fbcondecor helper by writing it to
-+/proc/sys/kernel/fbcondecor.
-+
-+*****************************************************************************
-+
-+The information below is mostly technical stuff. There's probably no need to
-+read it unless you plan to develop a userspace helper.
-+
-+The fbcondecor protocol
-+-----------------------
-+
-+The fbcondecor protocol defines a communication interface between the kernel and
-+the userspace fbcondecor helper.
-+
-+The kernel side is responsible for:
-+
-+ * rendering console text, using an image as a background (instead of a
-+   standard solid color fbcon uses),
-+ * accepting commands from the user via ioctls on the fbcondecor device,
-+ * calling the userspace helper to set things up as soon as the fb subsystem
-+   is initialized.
-+
-+The userspace helper is responsible for everything else, including parsing
-+configuration files, decompressing the image files whenever the kernel needs
-+it, and communicating with the kernel if necessary.
-+
-+The fbcondecor protocol specifies how communication is done in both ways:
-+kernel->userspace and userspace->helper.
-+
-+Kernel -> Userspace
-+-------------------
-+
-+The kernel communicates with the userspace helper by calling it and specifying
-+the task to be done in a series of arguments.
-+
-+The arguments follow the pattern:
-+<fbcondecor protocol version> <command> <parameters>
-+
-+All commands defined in fbcondecor protocol v2 have the following parameters:
-+ virtual console
-+ framebuffer number
-+ theme
-+
-+Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the
-+framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used.
-+
-+Fbcondecor protocol v2 specifies the following commands:
-+
-+getpic
-+------
-+ The kernel issues this command to request image data. It's up to the
-+ userspace  helper to find a background image appropriate for the specified
-+ theme and the current resolution. The userspace helper should respond by
-+ issuing the FBIOCONDECOR_SETPIC ioctl.
-+
-+init
-+----
-+ The kernel issues this command after the fbcondecor device is created and
-+ the fbcondecor interface is initialized. Upon receiving 'init', the userspace
-+ helper should parse the kernel command line (/proc/cmdline) or otherwise
-+ decide whether fbcondecor is to be activated.
-+
-+ To activate fbcondecor on the first console the helper should issue the
-+ FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands,
-+ in the above-mentioned order.
-+
-+ When the userspace helper is called in an early phase of the boot process
-+ (right after the initialization of fbcon), no filesystems will be mounted.
-+ The helper program should mount sysfs and then create the appropriate
-+ framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get
-+ current display settings and to be able to communicate with the kernel side.
-+ It should probably also mount the procfs to be able to parse the kernel
-+ command line parameters.
-+
-+ Note that the console sem is not held when the kernel calls fbcondecor_helper
-+ with the 'init' command. The fbcondecor helper should perform all ioctls with
-+ origin set to FBCON_DECOR_IO_ORIG_USER.
-+
-+modechange
-+----------
-+ The kernel issues this command on a mode change. The helper's response should
-+ be similar to the response to the 'init' command. Note that this time the
-+ console sem is held and all ioctls must be performed with origin set to
-+ FBCON_DECOR_IO_ORIG_KERNEL.
-+
-+
-+Userspace -> Kernel
-+-------------------
-+
-+Userspace programs can communicate with fbcondecor via ioctls on the
-+fbcondecor device. These ioctls are to be used by both the userspace helper
-+(called only by the kernel) and userspace configuration tools (run by the users).
-+
-+The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL
-+when doing the appropriate ioctls. All userspace configuration tools should
-+use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin
-+field when performing ioctls from the kernel helper will most likely result
-+in a console deadlock.
-+
-+FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console
-+semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire
-+the console sem.
-+
-+The framebuffer console decoration provides the following ioctls (all defined in
-+linux/fb.h):
-+
-+FBIOCONDECOR_SETPIC
-+description: loads a background picture for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: struct fb_image*
-+notes:
-+If called for consoles other than the current foreground one, the picture data
-+will be ignored.
-+
-+If the current virtual console is running in a 8-bpp mode, the cmap substruct
-+of fb_image has to be filled appropriately: start should be set to 16 (first
-+16 colors are reserved for fbcon), len to a value <= 240 and red, green and
-+blue should point to valid cmap data. The transp field is ingored. The fields
-+dx, dy, bg_color, fg_color in fb_image are ignored as well.
-+
-+FBIOCONDECOR_SETCFG
-+description: sets the fbcondecor config for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
-+notes: The structure has to be filled with valid data.
-+
-+FBIOCONDECOR_GETCFG
-+description: gets the fbcondecor config for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
-+
-+FBIOCONDECOR_SETSTATE
-+description: sets the fbcondecor state for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: unsigned int*
-+          values: 0 = disabled, 1 = enabled.
-+
-+FBIOCONDECOR_GETSTATE
-+description: gets the fbcondecor state for a virtual console
-+argument: struct fbcon_decor_iowrapper*; data: unsigned int*
-+          values: as in FBIOCONDECOR_SETSTATE
-+
-+Info on used structures:
-+
-+Definition of struct vc_decor can be found in linux/console_decor.h. It's
-+heavily commented. Note that the 'theme' field should point to a string
-+no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is
-+performed, the theme field should point to a char buffer of length
-+FBCON_DECOR_THEME_LEN.
-+
-+Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h.
-+The fields in this struct have the following meaning:
-+
-+vc:
-+Virtual console number.
-+
-+origin:
-+Specifies if the ioctl is performed as a response to a kernel request. The
-+fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace
-+programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to
-+avoid console semaphore deadlocks.
-+
-+data:
-+Pointer to a data structure appropriate for the performed ioctl. Type of
-+the data struct is specified in the ioctls description.
-+
-+*****************************************************************************
-+
-+Credit
-+------
-+
-+Original 'bootsplash' project & implementation by:
-+  Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>,
-+  Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>,
-+  Ken Wimer <wimer@suse.de>.
-+
-+Fbcondecor, fbcondecor protocol design, current implementation & docs by:
-+  Michal Januszewski <michalj+fbcondecor@gmail.com>
-+
-diff -Naur vanilla-5.10/drivers/Makefile linux-5.10/drivers/Makefile
---- vanilla-5.10/drivers/Makefile	2019-10-19 17:30:51.445233502 +0200
-+++ linux-5.10/drivers/Makefile	2019-10-19 18:35:55.881917873 +0200
-@@ -20,6 +20,10 @@
- 
- obj-$(CONFIG_PARISC)		+= parisc/
- obj-$(CONFIG_RAPIDIO)		+= rapidio/
-+# tty/ comes before char/ so that the VT console is the boot-time
-+# default.
-+obj-y				+= tty/
-+obj-y				+= char/
- obj-y				+= video/
- obj-y				+= idle/
- 
-@@ -51,11 +55,6 @@
- # reset controllers early, since gpu drivers might rely on them to initialize
- obj-$(CONFIG_RESET_CONTROLLER)	+= reset/
- 
--# tty/ comes before char/ so that the VT console is the boot-time
--# default.
--obj-y				+= tty/
--obj-y				+= char/
--
- # iommu/ comes before gpu as gpu are using iommu controllers
- obj-y				+= iommu/
- 
-diff -Naur vanilla-5.10/drivers/video/console/Kconfig linux-5.10/drivers/video/console/Kconfig
---- vanilla-5.10/drivers/video/console/Kconfig	2019-09-07 14:46:06.886775017 +0200
-+++ linux-5.10/drivers/video/console/Kconfig	2019-10-19 18:35:55.881917873 +0200
-@@ -115,6 +115,19 @@
- 	  by the firmware in place, rather then replacing the contents with a
- 	  black screen as soon as fbcon loads.
- 
-+config FB_CON_DECOR
-+	bool "Support for the Framebuffer Console Decorations"
-+	depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING
-+	default n
-+	help
-+	  This option enables support for framebuffer console decorations which
-+	  makes it possible to display images in the background of the system
-+	  consoles.  Note that userspace utilities are necessary in order to take
-+	  advantage of these features. Refer to Documentation/fb/fbcondecor.txt
-+	  for more information.
-+
-+	  If unsure, say N.
-+
- config STI_CONSOLE
- 	bool "STI text console"
- 	depends on PARISC && HAS_IOMEM
-diff -Naur vanilla-5.10/drivers/video/console/Makefile linux-5.10/drivers/video/console/Makefile
---- vanilla-5.10/drivers/video/console/Makefile	2018-10-22 08:37:37.000000000 +0200
-+++ linux-5.10/drivers/video/console/Makefile	2019-10-19 18:35:55.881917873 +0200
-@@ -9,4 +9,5 @@
- obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
- obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
- 
-+obj-$(CONFIG_FB_CON_DECOR)     	  += fbcondecor.o cfbcondecor.o
- obj-$(CONFIG_FB_STI)              += sticore.o
-diff -Naur vanilla-5.10/drivers/video/console/cfbcondecor.c linux-5.10/drivers/video/console/cfbcondecor.c
---- vanilla-5.10/drivers/video/console/cfbcondecor.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.10/drivers/video/console/cfbcondecor.c	2019-10-19 18:35:55.881917873 +0200
-@@ -0,0 +1,473 @@
-+/*
-+ *  linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions
-+ *
-+ *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
-+ *
-+ *  Code based upon "Bootdecor" (C) 2001-2003
-+ *       Volker Poplawski <volker@poplawski.de>,
-+ *       Stefan Reinauer <stepan@suse.de>,
-+ *       Steffen Winterfeldt <snwint@suse.de>,
-+ *       Michael Schroeder <mls@suse.de>,
-+ *       Ken Wimer <wimer@suse.de>.
-+ *
-+ *  This file is subject to the terms and conditions of the GNU General Public
-+ *  License.  See the file COPYING in the main directory of this archive for
-+ *  more details.
-+ */
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/fb.h>
-+#include <linux/selection.h>
-+#include <linux/slab.h>
-+#include <linux/vt_kern.h>
-+#include <asm/irq.h>
-+
-+#include "../fbdev/core/fbcon.h"
-+#include "fbcondecor.h"
-+
-+#define parse_pixel(shift, bpp, type)						\
-+	do {									\
-+		if (d & (0x80 >> (shift)))					\
-+			dd2[(shift)] = fgx;					\
-+		else								\
-+			dd2[(shift)] = transparent ? *(type *)decor_src : bgx;	\
-+		decor_src += (bpp);						\
-+	} while (0)								\
-+
-+extern int get_color(struct vc_data *vc, struct fb_info *info,
-+		     u16 c, int is_fg);
-+
-+void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
-+{
-+	int i, j, k;
-+	int minlen = min(min(info->var.red.length, info->var.green.length),
-+			     info->var.blue.length);
-+	u32 col;
-+
-+	for (j = i = 0; i < 16; i++) {
-+		k = color_table[i];
-+
-+		col = ((vc->vc_palette[j++]  >> (8-minlen))
-+			<< info->var.red.offset);
-+		col |= ((vc->vc_palette[j++] >> (8-minlen))
-+			<< info->var.green.offset);
-+		col |= ((vc->vc_palette[j++] >> (8-minlen))
-+			<< info->var.blue.offset);
-+			((u32 *)info->pseudo_palette)[k] = col;
-+	}
-+}
-+
-+void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height,
-+		      int width, u8 *src, u32 fgx, u32 bgx, u8 transparent)
-+{
-+	unsigned int x, y;
-+	u32 dd;
-+	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
-+	unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
-+	unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
-+	u16 dd2[4];
-+
-+	u8 *decor_src = (u8 *)(info->bgdecor.data + ds);
-+	u8 *dst = (u8 *)(info->screen_base + d);
-+
-+	if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
-+		return;
-+
-+	for (y = 0; y < height; y++) {
-+		switch (info->var.bits_per_pixel) {
-+
-+		case 32:
-+			for (x = 0; x < width; x++) {
-+
-+				if ((x & 7) == 0)
-+					d = *src++;
-+				if (d & 0x80)
-+					dd = fgx;
-+				else
-+					dd = transparent ?
-+					     *(u32 *)decor_src : bgx;
-+
-+				d <<= 1;
-+				decor_src += 4;
-+				fb_writel(dd, dst);
-+				dst += 4;
-+			}
-+			break;
-+		case 24:
-+			for (x = 0; x < width; x++) {
-+
-+				if ((x & 7) == 0)
-+					d = *src++;
-+				if (d & 0x80)
-+					dd = fgx;
-+				else
-+					dd = transparent ?
-+					     (*(u32 *)decor_src & 0xffffff) : bgx;
-+
-+				d <<= 1;
-+				decor_src += 3;
-+#ifdef __LITTLE_ENDIAN
-+				fb_writew(dd & 0xffff, dst);
-+				dst += 2;
-+				fb_writeb((dd >> 16), dst);
-+#else
-+				fb_writew(dd >> 8, dst);
-+				dst += 2;
-+				fb_writeb(dd & 0xff, dst);
-+#endif
-+				dst++;
-+			}
-+			break;
-+		case 16:
-+			for (x = 0; x < width; x += 2) {
-+				if ((x & 7) == 0)
-+					d = *src++;
-+
-+				parse_pixel(0, 2, u16);
-+				parse_pixel(1, 2, u16);
-+#ifdef __LITTLE_ENDIAN
-+				dd = dd2[0] | (dd2[1] << 16);
-+#else
-+				dd = dd2[1] | (dd2[0] << 16);
-+#endif
-+				d <<= 2;
-+				fb_writel(dd, dst);
-+				dst += 4;
-+			}
-+			break;
-+
-+		case 8:
-+			for (x = 0; x < width; x += 4) {
-+				if ((x & 7) == 0)
-+					d = *src++;
-+
-+				parse_pixel(0, 1, u8);
-+				parse_pixel(1, 1, u8);
-+				parse_pixel(2, 1, u8);
-+				parse_pixel(3, 1, u8);
-+
-+#ifdef __LITTLE_ENDIAN
-+				dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
-+#else
-+				dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
-+#endif
-+				d <<= 4;
-+				fb_writel(dd, dst);
-+				dst += 4;
-+			}
-+		}
-+
-+		dst += info->fix.line_length - width * bytespp;
-+		decor_src += (info->var.xres - width) * bytespp;
-+	}
-+}
-+
-+#define cc2cx(a)						\
-+	((info->fix.visual == FB_VISUAL_TRUECOLOR ||		\
-+		info->fix.visual == FB_VISUAL_DIRECTCOLOR) ?	\
-+			((u32 *)info->pseudo_palette)[a] : a)
-+
-+void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info,
-+		   const unsigned short *s, int count, int yy, int xx)
-+{
-+	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-+	struct fbcon_ops *ops = info->fbcon_par;
-+	int fg_color, bg_color, transparent;
-+	u8 *src;
-+	u32 bgx, fgx;
-+	u16 c = scr_readw(s);
-+
-+	fg_color = get_color(vc, info, c, 1);
-+	bg_color = get_color(vc, info, c, 0);
-+
-+	/* Don't paint the background image if console is blanked */
-+	transparent = ops->blank_state ? 0 :
-+		(vc->vc_decor.bg_color == bg_color);
-+
-+	xx = xx * vc->vc_font.width + vc->vc_decor.tx;
-+	yy = yy * vc->vc_font.height + vc->vc_decor.ty;
-+
-+	fgx = cc2cx(fg_color);
-+	bgx = cc2cx(bg_color);
-+
-+	while (count--) {
-+		c = scr_readw(s++);
-+		src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
-+		      ((vc->vc_font.width + 7) >> 3);
-+
-+		fbcon_decor_renderc(info, yy, xx, vc->vc_font.height,
-+			       vc->vc_font.width, src, fgx, bgx, transparent);
-+		xx += vc->vc_font.width;
-+	}
-+}
-+
-+void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor)
-+{
-+	int i;
-+	unsigned int dsize, s_pitch;
-+	struct fbcon_ops *ops = info->fbcon_par;
-+	struct vc_data *vc;
-+	u8 *src;
-+
-+	/* we really don't need any cursors while the console is blanked */
-+	if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
-+		return;
-+
-+	vc = vc_cons[ops->currcon].d;
-+
-+	src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
-+	if (!src)
-+		return;
-+
-+	s_pitch = (cursor->image.width + 7) >> 3;
-+	dsize = s_pitch * cursor->image.height;
-+	if (cursor->enable) {
-+		switch (cursor->rop) {
-+		case ROP_XOR:
-+			for (i = 0; i < dsize; i++)
-+				src[i] = cursor->image.data[i] ^ cursor->mask[i];
-+			break;
-+		case ROP_COPY:
-+		default:
-+			for (i = 0; i < dsize; i++)
-+				src[i] = cursor->image.data[i] & cursor->mask[i];
-+			break;
-+		}
-+	} else
-+		memcpy(src, cursor->image.data, dsize);
-+
-+	fbcon_decor_renderc(info,
-+			cursor->image.dy + vc->vc_decor.ty,
-+			cursor->image.dx + vc->vc_decor.tx,
-+			cursor->image.height,
-+			cursor->image.width,
-+			(u8 *)src,
-+			cc2cx(cursor->image.fg_color),
-+			cc2cx(cursor->image.bg_color),
-+			cursor->image.bg_color == vc->vc_decor.bg_color);
-+
-+	kfree(src);
-+}
-+
-+static void decorset(u8 *dst, int height, int width, int dstbytes,
-+				u32 bgx, int bpp)
-+{
-+	int i;
-+
-+	if (bpp == 8)
-+		bgx |= bgx << 8;
-+	if (bpp == 16 || bpp == 8)
-+		bgx |= bgx << 16;
-+
-+	while (height-- > 0) {
-+		u8 *p = dst;
-+
-+		switch (bpp) {
-+
-+		case 32:
-+			for (i = 0; i < width; i++) {
-+				fb_writel(bgx, p); p += 4;
-+			}
-+			break;
-+		case 24:
-+			for (i = 0; i < width; i++) {
-+#ifdef __LITTLE_ENDIAN
-+				fb_writew((bgx & 0xffff), (u16 *)p); p += 2;
-+				fb_writeb((bgx >> 16), p++);
-+#else
-+				fb_writew((bgx >> 8), (u16 *)p); p += 2;
-+				fb_writeb((bgx & 0xff), p++);
-+#endif
-+			}
-+			break;
-+		case 16:
-+			for (i = 0; i < width/4; i++) {
-+				fb_writel(bgx, p); p += 4;
-+				fb_writel(bgx, p); p += 4;
-+			}
-+			if (width & 2) {
-+				fb_writel(bgx, p); p += 4;
-+			}
-+			if (width & 1)
-+				fb_writew(bgx, (u16 *)p);
-+			break;
-+		case 8:
-+			for (i = 0; i < width/4; i++) {
-+				fb_writel(bgx, p); p += 4;
-+			}
-+
-+			if (width & 2) {
-+				fb_writew(bgx, p); p += 2;
-+			}
-+			if (width & 1)
-+				fb_writeb(bgx, (u8 *)p);
-+			break;
-+
-+		}
-+		dst += dstbytes;
-+	}
-+}
-+
-+void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
-+		   int srclinebytes, int bpp)
-+{
-+	int i;
-+
-+	while (height-- > 0) {
-+		u32 *p = (u32 *)dst;
-+		u32 *q = (u32 *)src;
-+
-+		switch (bpp) {
-+
-+		case 32:
-+			for (i = 0; i < width; i++)
-+				fb_writel(*q++, p++);
-+			break;
-+		case 24:
-+			for (i = 0; i < (width * 3 / 4); i++)
-+				fb_writel(*q++, p++);
-+			if ((width * 3) % 4) {
-+				if (width & 2) {
-+					fb_writeb(*(u8 *)q, (u8 *)p);
-+				} else if (width & 1) {
-+					fb_writew(*(u16 *)q, (u16 *)p);
-+					fb_writeb(*(u8 *)((u16 *)q + 1),
-+							(u8 *)((u16 *)p + 2));
-+				}
-+			}
-+			break;
-+		case 16:
-+			for (i = 0; i < width/4; i++) {
-+				fb_writel(*q++, p++);
-+				fb_writel(*q++, p++);
-+			}
-+			if (width & 2)
-+				fb_writel(*q++, p++);
-+			if (width & 1)
-+				fb_writew(*(u16 *)q, (u16 *)p);
-+			break;
-+		case 8:
-+			for (i = 0; i < width/4; i++)
-+				fb_writel(*q++, p++);
-+
-+			if (width & 2) {
-+				fb_writew(*(u16 *)q, (u16 *)p);
-+				q = (u32 *) ((u16 *)q + 1);
-+				p = (u32 *) ((u16 *)p + 1);
-+			}
-+			if (width & 1)
-+				fb_writeb(*(u8 *)q, (u8 *)p);
-+			break;
-+		}
-+
-+		dst += linebytes;
-+		src += srclinebytes;
-+	}
-+}
-+
-+static void decorfill(struct fb_info *info, int sy, int sx, int height,
-+		       int width)
-+{
-+	int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
-+	int d  = sy * info->fix.line_length + sx * bytespp;
-+	int ds = (sy * info->var.xres + sx) * bytespp;
-+
-+	fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds),
-+		    height, width, info->fix.line_length, info->var.xres * bytespp,
-+		    info->var.bits_per_pixel);
-+}
-+
-+void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
-+		    int height, int width)
-+{
-+	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-+	struct fbcon_ops *ops = info->fbcon_par;
-+	u8 *dst;
-+	int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info);
-+
-+	transparent = (vc->vc_decor.bg_color == bg_color);
-+	sy = sy * vc->vc_font.height + vc->vc_decor.ty;
-+	sx = sx * vc->vc_font.width + vc->vc_decor.tx;
-+	height *= vc->vc_font.height;
-+	width *= vc->vc_font.width;
-+
-+	/* Don't paint the background image if console is blanked */
-+	if (transparent && !ops->blank_state) {
-+		decorfill(info, sy, sx, height, width);
-+	} else {
-+		dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
-+			     sx * ((info->var.bits_per_pixel + 7) >> 3));
-+		decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
-+			  info->var.bits_per_pixel);
-+	}
-+}
-+
-+void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info,
-+			    int bottom_only)
-+{
-+	unsigned int tw = vc->vc_cols*vc->vc_font.width;
-+	unsigned int th = vc->vc_rows*vc->vc_font.height;
-+
-+	if (!bottom_only) {
-+		/* top margin */
-+		decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres);
-+		/* left margin */
-+		decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx);
-+		/* right margin */
-+		decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th,
-+			   info->var.xres - vc->vc_decor.tx - tw);
-+	}
-+	decorfill(info, vc->vc_decor.ty + th, 0,
-+		   info->var.yres - vc->vc_decor.ty - th, info->var.xres);
-+}
-+
-+void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
-+			   int sx, int dx, int width)
-+{
-+	u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
-+	u16 *s = d + (dx - sx);
-+	u16 *start = d;
-+	u16 *ls = d;
-+	u16 *le = d + width;
-+	u16 c;
-+	int x = dx;
-+	u16 attr = 1;
-+
-+	do {
-+		c = scr_readw(d);
-+		if (attr != (c & 0xff00)) {
-+			attr = c & 0xff00;
-+			if (d > start) {
-+				fbcon_decor_putcs(vc, info, start, d - start, y, x);
-+				x += d - start;
-+				start = d;
-+			}
-+		}
-+		if (s >= ls && s < le && c == scr_readw(s)) {
-+			if (d > start) {
-+				fbcon_decor_putcs(vc, info, start, d - start, y, x);
-+				x += d - start + 1;
-+				start = d + 1;
-+			} else {
-+				x++;
-+				start++;
-+			}
-+		}
-+		s++;
-+		d++;
-+	} while (d < le);
-+	if (d > start)
-+		fbcon_decor_putcs(vc, info, start, d - start, y, x);
-+}
-+
-+void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank)
-+{
-+	if (blank) {
-+		decorset((u8 *)info->screen_base, info->var.yres, info->var.xres,
-+			  info->fix.line_length, 0, info->var.bits_per_pixel);
-+	} else {
-+		update_screen(vc);
-+		fbcon_decor_clear_margins(vc, info, 0);
-+	}
-+}
-+
-diff -Naur vanilla-5.10/drivers/video/console/fbcondecor.c linux-5.10/drivers/video/console/fbcondecor.c
---- vanilla-5.10/drivers/video/console/fbcondecor.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.10/drivers/video/console/fbcondecor.c	2019-10-19 18:35:55.881917873 +0200
-@@ -0,0 +1,549 @@
-+/*
-+ *  linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations
-+ *
-+ *  Copyright (C) 2004-2009 Michal Januszewski <michalj+fbcondecor@gmail.com>
-+ *
-+ *  Code based upon "Bootsplash" (C) 2001-2003
-+ *       Volker Poplawski <volker@poplawski.de>,
-+ *       Stefan Reinauer <stepan@suse.de>,
-+ *       Steffen Winterfeldt <snwint@suse.de>,
-+ *       Michael Schroeder <mls@suse.de>,
-+ *       Ken Wimer <wimer@suse.de>.
-+ *
-+ *  Compat ioctl support by Thorsten Klein <TK@Thorsten-Klein.de>.
-+ *
-+ *  This file is subject to the terms and conditions of the GNU General Public
-+ *  License.  See the file COPYING in the main directory of this archive for
-+ *  more details.
-+ *
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/fb.h>
-+#include <linux/vt_kern.h>
-+#include <linux/vmalloc.h>
-+#include <linux/unistd.h>
-+#include <linux/syscalls.h>
-+#include <linux/init.h>
-+#include <linux/proc_fs.h>
-+#include <linux/workqueue.h>
-+#include <linux/kmod.h>
-+#include <linux/miscdevice.h>
-+#include <linux/device.h>
-+#include <linux/fs.h>
-+#include <linux/compat.h>
-+#include <linux/console.h>
-+#include <linux/binfmts.h>
-+#include <linux/uaccess.h>
-+#include <asm/irq.h>
-+
-+#include "../fbdev/core/fbcon.h"
-+#include "fbcondecor.h"
-+
-+extern signed char con2fb_map[];
-+static int fbcon_decor_enable(struct vc_data *vc);
-+
-+static int initialized;
-+
-+char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper";
-+EXPORT_SYMBOL(fbcon_decor_path);
-+
-+int fbcon_decor_call_helper(char *cmd, unsigned short vc)
-+{
-+	char *envp[] = {
-+		"HOME=/",
-+		"PATH=/sbin:/bin",
-+		NULL
-+	};
-+
-+	char tfb[5];
-+	char tcons[5];
-+	unsigned char fb = (int) con2fb_map[vc];
-+
-+	char *argv[] = {
-+		fbcon_decor_path,
-+		"2",
-+		cmd,
-+		tcons,
-+		tfb,
-+		vc_cons[vc].d->vc_decor.theme,
-+		NULL
-+	};
-+
-+	snprintf(tfb, 5, "%d", fb);
-+	snprintf(tcons, 5, "%d", vc);
-+
-+	return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC);
-+}
-+
-+/* Disables fbcondecor on a virtual console; called with console sem held. */
-+int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw)
-+{
-+	struct fb_info *info;
-+
-+	if (!vc->vc_decor.state)
-+		return -EINVAL;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (info == NULL)
-+		return -EINVAL;
-+
-+	vc->vc_decor.state = 0;
-+	vc_resize(vc, info->var.xres / vc->vc_font.width,
-+		  info->var.yres / vc->vc_font.height);
-+
-+	if (fg_console == vc->vc_num && redraw) {
-+		redraw_screen(vc, 0);
-+		update_region(vc, vc->vc_origin +
-+			      vc->vc_size_row * vc->vc_top,
-+			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-+	}
-+
-+	printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n",
-+			 vc->vc_num);
-+
-+	return 0;
-+}
-+
-+/* Enables fbcondecor on a virtual console; called with console sem held. */
-+static int fbcon_decor_enable(struct vc_data *vc)
-+{
-+	struct fb_info *info;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 ||
-+	    info == NULL || vc->vc_decor.state || (!info->bgdecor.data &&
-+	    vc->vc_num == fg_console))
-+		return -EINVAL;
-+
-+	vc->vc_decor.state = 1;
-+	vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width,
-+		  vc->vc_decor.theight / vc->vc_font.height);
-+
-+	if (fg_console == vc->vc_num) {
-+		redraw_screen(vc, 0);
-+		update_region(vc, vc->vc_origin +
-+			      vc->vc_size_row * vc->vc_top,
-+			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-+		fbcon_decor_clear_margins(vc, info, 0);
-+	}
-+
-+	printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n",
-+			 vc->vc_num);
-+
-+	return 0;
-+}
-+
-+static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin)
-+{
-+	int ret;
-+
-+	console_lock();
-+	if (!state)
-+		ret = fbcon_decor_disable(vc, 1);
-+	else
-+		ret = fbcon_decor_enable(vc);
-+	console_unlock();
-+
-+	return ret;
-+}
-+
-+static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state)
-+{
-+	*state = vc->vc_decor.state;
-+}
-+
-+static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin)
-+{
-+	struct fb_info *info;
-+	int len;
-+	char *tmp;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (info == NULL || !cfg->twidth || !cfg->theight ||
-+	    cfg->tx + cfg->twidth  > info->var.xres ||
-+	    cfg->ty + cfg->theight > info->var.yres)
-+		return -EINVAL;
-+
-+	len = strnlen_user(cfg->theme, MAX_ARG_STRLEN);
-+	if (!len || len > FBCON_DECOR_THEME_LEN)
-+		return -EINVAL;
-+	tmp = kmalloc(len, GFP_KERNEL);
-+	if (!tmp)
-+		return -ENOMEM;
-+	if (copy_from_user(tmp, (void __user *)cfg->theme, len))
-+		return -EFAULT;
-+	cfg->theme = tmp;
-+	cfg->state = 0;
-+
-+	console_lock();
-+	if (vc->vc_decor.state)
-+		fbcon_decor_disable(vc, 1);
-+	kfree(vc->vc_decor.theme);
-+	vc->vc_decor = *cfg;
-+	console_unlock();
-+
-+	printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n",
-+			 vc->vc_num, vc->vc_decor.theme);
-+	return 0;
-+}
-+
-+static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc,
-+					struct vc_decor *decor)
-+{
-+	char __user *tmp;
-+
-+	tmp = decor->theme;
-+	*decor = vc->vc_decor;
-+	decor->theme = tmp;
-+
-+	if (vc->vc_decor.theme) {
-+		if (copy_to_user(tmp, vc->vc_decor.theme,
-+					strlen(vc->vc_decor.theme) + 1))
-+			return -EFAULT;
-+	} else
-+		if (put_user(0, tmp))
-+			return -EFAULT;
-+
-+	return 0;
-+}
-+
-+static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img,
-+						unsigned char origin)
-+{
-+	struct fb_info *info;
-+	int len;
-+	u8 *tmp;
-+
-+	if (vc->vc_num != fg_console)
-+		return -EINVAL;
-+
-+	info = registered_fb[(int) con2fb_map[vc->vc_num]];
-+
-+	if (info == NULL)
-+		return -EINVAL;
-+
-+	if (img->width != info->var.xres || img->height != info->var.yres) {
-+		printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n");
-+		printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height,
-+				info->var.xres, info->var.yres);
-+		return -EINVAL;
-+	}
-+
-+	if (img->depth != info->var.bits_per_pixel) {
-+		printk(KERN_ERR "fbcondecor: picture depth mismatch\n");
-+		return -EINVAL;
-+	}
-+
-+	if (img->depth == 8) {
-+		if (!img->cmap.len || !img->cmap.red || !img->cmap.green ||
-+		    !img->cmap.blue)
-+			return -EINVAL;
-+
-+		tmp = vmalloc(img->cmap.len * 3 * 2);
-+		if (!tmp)
-+			return -ENOMEM;
-+
-+		if (copy_from_user(tmp,
-+				(void __user *)img->cmap.red,
-+						(img->cmap.len << 1)) ||
-+			copy_from_user(tmp + (img->cmap.len << 1),
-+				(void __user *)img->cmap.green,
-+						(img->cmap.len << 1)) ||
-+			copy_from_user(tmp + (img->cmap.len << 2),
-+				(void __user *)img->cmap.blue,
-+						(img->cmap.len << 1))) {
-+			vfree(tmp);
-+			return -EFAULT;
-+		}
-+
-+		img->cmap.transp = NULL;
-+		img->cmap.red = (u16 *)tmp;
-+		img->cmap.green = img->cmap.red + img->cmap.len;
-+		img->cmap.blue = img->cmap.green + img->cmap.len;
-+	} else {
-+		img->cmap.red = NULL;
-+	}
-+
-+	len = ((img->depth + 7) >> 3) * img->width * img->height;
-+
-+	/*
-+	 * Allocate an additional byte so that we never go outside of the
-+	 * buffer boundaries in the rendering functions in a 24 bpp mode.
-+	 */
-+	tmp = vmalloc(len + 1);
-+
-+	if (!tmp)
-+		goto out;
-+
-+	if (copy_from_user(tmp, (void __user *)img->data, len))
-+		goto out;
-+
-+	img->data = tmp;
-+
-+	console_lock();
-+
-+	if (info->bgdecor.data)
-+		vfree((u8 *)info->bgdecor.data);
-+	if (info->bgdecor.cmap.red)
-+		vfree(info->bgdecor.cmap.red);
-+
-+	info->bgdecor = *img;
-+
-+	if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) {
-+		redraw_screen(vc, 0);
-+		update_region(vc, vc->vc_origin +
-+			      vc->vc_size_row * vc->vc_top,
-+			      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-+		fbcon_decor_clear_margins(vc, info, 0);
-+	}
-+
-+	console_unlock();
-+
-+	return 0;
-+
-+out:
-+	if (img->cmap.red)
-+		vfree(img->cmap.red);
-+
-+	if (tmp)
-+		vfree(tmp);
-+	return -ENOMEM;
-+}
-+
-+static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg)
-+{
-+	struct fbcon_decor_iowrapper __user *wrapper = (void __user *) arg;
-+	struct vc_data *vc = NULL;
-+	unsigned short vc_num = 0;
-+	unsigned char origin = 0;
-+	void __user *data = NULL;
-+
-+	if (!access_ok(wrapper,
-+			sizeof(struct fbcon_decor_iowrapper)))
-+		return -EFAULT;
-+
-+	__get_user(vc_num, &wrapper->vc);
-+	__get_user(origin, &wrapper->origin);
-+	__get_user(data, &wrapper->data);
-+
-+	if (!vc_cons_allocated(vc_num))
-+		return -EINVAL;
-+
-+	vc = vc_cons[vc_num].d;
-+
-+	switch (cmd) {
-+	case FBIOCONDECOR_SETPIC:
-+	{
-+		struct fb_image img;
-+
-+		if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image)))
-+			return -EFAULT;
-+
-+		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
-+	}
-+	case FBIOCONDECOR_SETCFG:
-+	{
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
-+			return -EFAULT;
-+
-+		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
-+	}
-+	case FBIOCONDECOR_GETCFG:
-+	{
-+		int rval;
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
-+			return -EFAULT;
-+
-+		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
-+
-+		if (copy_to_user(data, &cfg, sizeof(struct vc_decor)))
-+			return -EFAULT;
-+		return rval;
-+	}
-+	case FBIOCONDECOR_SETSTATE:
-+	{
-+		unsigned int state = 0;
-+
-+		if (get_user(state, (unsigned int __user *)data))
-+			return -EFAULT;
-+		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
-+	}
-+	case FBIOCONDECOR_GETSTATE:
-+	{
-+		unsigned int state = 0;
-+
-+		fbcon_decor_ioctl_dogetstate(vc, &state);
-+		return put_user(state, (unsigned int __user *)data);
-+	}
-+
-+	default:
-+		return -ENOIOCTLCMD;
-+	}
-+}
-+
-+#ifdef CONFIG_COMPAT
-+
-+static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-+{
-+	struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg;
-+	struct vc_data *vc = NULL;
-+	unsigned short vc_num = 0;
-+	unsigned char origin = 0;
-+	compat_uptr_t data_compat = 0;
-+	void __user *data = NULL;
-+
-+	if (!access_ok(wrapper,
-+			sizeof(struct fbcon_decor_iowrapper32)))
-+		return -EFAULT;
-+
-+	__get_user(vc_num, &wrapper->vc);
-+	__get_user(origin, &wrapper->origin);
-+	__get_user(data_compat, &wrapper->data);
-+	data = compat_ptr(data_compat);
-+
-+	if (!vc_cons_allocated(vc_num))
-+		return -EINVAL;
-+
-+	vc = vc_cons[vc_num].d;
-+
-+	switch (cmd) {
-+	case FBIOCONDECOR_SETPIC32:
-+	{
-+		struct fb_image32 img_compat;
-+		struct fb_image img;
-+
-+		if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32)))
-+			return -EFAULT;
-+
-+		fb_image_from_compat(img, img_compat);
-+
-+		return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
-+	}
-+
-+	case FBIOCONDECOR_SETCFG32:
-+	{
-+		struct vc_decor32 cfg_compat;
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
-+			return -EFAULT;
-+
-+		vc_decor_from_compat(cfg, cfg_compat);
-+
-+		return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
-+	}
-+
-+	case FBIOCONDECOR_GETCFG32:
-+	{
-+		int rval;
-+		struct vc_decor32 cfg_compat;
-+		struct vc_decor cfg;
-+
-+		if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
-+			return -EFAULT;
-+		cfg.theme = compat_ptr(cfg_compat.theme);
-+
-+		rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
-+
-+		vc_decor_to_compat(cfg_compat, cfg);
-+
-+		if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32)))
-+			return -EFAULT;
-+		return rval;
-+	}
-+
-+	case FBIOCONDECOR_SETSTATE32:
-+	{
-+		compat_uint_t state_compat = 0;
-+		unsigned int state = 0;
-+
-+		if (get_user(state_compat, (compat_uint_t __user *)data))
-+			return -EFAULT;
-+
-+		state = (unsigned int)state_compat;
-+
-+		return fbcon_decor_ioctl_dosetstate(vc, state, origin);
-+	}
-+
-+	case FBIOCONDECOR_GETSTATE32:
-+	{
-+		compat_uint_t state_compat = 0;
-+		unsigned int state = 0;
-+
-+		fbcon_decor_ioctl_dogetstate(vc, &state);
-+		state_compat = (compat_uint_t)state;
-+
-+		return put_user(state_compat, (compat_uint_t __user *)data);
-+	}
-+
-+	default:
-+		return -ENOIOCTLCMD;
-+	}
-+}
-+#else
-+  #define fbcon_decor_compat_ioctl NULL
-+#endif
-+
-+static struct file_operations fbcon_decor_ops = {
-+	.owner = THIS_MODULE,
-+	.unlocked_ioctl = fbcon_decor_ioctl,
-+	.compat_ioctl = fbcon_decor_compat_ioctl
-+};
-+
-+static struct miscdevice fbcon_decor_dev = {
-+	.minor = MISC_DYNAMIC_MINOR,
-+	.name = "fbcondecor",
-+	.fops = &fbcon_decor_ops
-+};
-+
-+void fbcon_decor_reset(void)
-+{
-+	int i;
-+
-+	for (i = 0; i < num_registered_fb; i++) {
-+		registered_fb[i]->bgdecor.data = NULL;
-+		registered_fb[i]->bgdecor.cmap.red = NULL;
-+	}
-+
-+	for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
-+		vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth =
-+						vc_cons[i].d->vc_decor.theight = 0;
-+		vc_cons[i].d->vc_decor.theme = NULL;
-+	}
-+}
-+
-+int fbcon_decor_init(void)
-+{
-+	int i;
-+
-+	fbcon_decor_reset();
-+
-+	if (initialized)
-+		return 0;
-+
-+	i = misc_register(&fbcon_decor_dev);
-+	if (i) {
-+		printk(KERN_ERR "fbcondecor: failed to register device\n");
-+		return i;
-+	}
-+
-+	fbcon_decor_call_helper("init", 0);
-+	initialized = 1;
-+	return 0;
-+}
-+
-+int fbcon_decor_exit(void)
-+{
-+	fbcon_decor_reset();
-+	return 0;
-+}
-diff -Naur vanilla-5.10/drivers/video/console/fbcondecor.h linux-5.10/drivers/video/console/fbcondecor.h
---- vanilla-5.10/drivers/video/console/fbcondecor.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.10/drivers/video/console/fbcondecor.h	2019-10-19 18:35:55.882917900 +0200
-@@ -0,0 +1,77 @@
-+/*
-+ *  linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers
-+ *
-+ *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
-+ *
-+ */
-+
-+#ifndef __FBCON_DECOR_H
-+#define __FBCON_DECOR_H
-+
-+#ifndef _LINUX_FB_H
-+#include <linux/fb.h>
-+#endif
-+
-+/* This is needed for vc_cons in fbcmap.c */
-+#include <linux/vt_kern.h>
-+
-+struct fb_cursor;
-+struct fb_info;
-+struct vc_data;
-+
-+#ifdef CONFIG_FB_CON_DECOR
-+/* fbcondecor.c */
-+int fbcon_decor_init(void);
-+int fbcon_decor_exit(void);
-+int fbcon_decor_call_helper(char *cmd, unsigned short cons);
-+int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw);
-+
-+/* cfbcondecor.c */
-+void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
-+void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor);
-+void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
-+void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
-+void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank);
-+void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
-+void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp);
-+void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc);
-+
-+/* vt.c */
-+void acquire_console_sem(void);
-+void release_console_sem(void);
-+void do_unblank_screen(int entering_gfx);
-+
-+/* struct vc_data *y */
-+#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme)
-+
-+/* struct fb_info *x, struct vc_data *y */
-+#define fbcon_decor_active_nores(x, y) (x->bgdecor.data && fbcon_decor_active_vc(y))
-+
-+/* struct fb_info *x, struct vc_data *y */
-+#define fbcon_decor_active(x, y) (fbcon_decor_active_nores(x, y) &&	\
-+				x->bgdecor.width == x->var.xres &&	\
-+				x->bgdecor.height == x->var.yres &&	\
-+				x->bgdecor.depth == x->var.bits_per_pixel)
-+
-+#else /* CONFIG_FB_CON_DECOR */
-+
-+static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
-+static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
-+static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
-+static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
-+static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
-+static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
-+static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
-+static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {}
-+static inline int fbcon_decor_call_helper(char *cmd, unsigned short cons) { return 0; }
-+static inline int fbcon_decor_init(void) { return 0; }
-+static inline int fbcon_decor_exit(void) { return 0; }
-+static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
-+
-+#define fbcon_decor_active_vc(y) (0)
-+#define fbcon_decor_active_nores(x, y) (0)
-+#define fbcon_decor_active(x, y) (0)
-+
-+#endif /* CONFIG_FB_CON_DECOR */
-+
-+#endif /* __FBCON_DECOR_H */
-diff -Naur vanilla-5.10/drivers/video/fbdev/Kconfig linux-5.10/drivers/video/fbdev/Kconfig
---- vanilla-5.10/drivers/video/fbdev/Kconfig	2019-10-19 17:30:53.953271478 +0200
-+++ linux-5.10/drivers/video/fbdev/Kconfig	2019-10-19 18:35:55.882917900 +0200
-@@ -1085,7 +1085,6 @@
- 	select FB_CFB_FILLRECT
- 	select FB_CFB_COPYAREA
- 	select FB_CFB_IMAGEBLIT
--	select FB_TILEBLITTING
- 	select FB_MACMODES if PPC_PMAC
- 	help
- 	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
-diff -Naur vanilla-5.10/drivers/video/fbdev/core/bitblit.c linux-5.10/drivers/video/fbdev/core/bitblit.c
---- vanilla-5.10/drivers/video/fbdev/core/bitblit.c	2018-10-22 08:37:37.000000000 +0200
-+++ linux-5.10/drivers/video/fbdev/core/bitblit.c	2019-10-19 18:35:55.882917900 +0200
-@@ -18,6 +18,7 @@
- #include <linux/console.h>
- #include <asm/types.h>
- #include "fbcon.h"
-+#include "../../console/fbcondecor.h"
- 
- /*
-  * Accelerated handlers.
-@@ -55,6 +56,13 @@
- 	area.height = height * vc->vc_font.height;
- 	area.width = width * vc->vc_font.width;
- 
-+	if (fbcon_decor_active(info, vc)) {
-+		area.sx += vc->vc_decor.tx;
-+		area.sy += vc->vc_decor.ty;
-+		area.dx += vc->vc_decor.tx;
-+		area.dy += vc->vc_decor.ty;
-+	}
-+
- 	info->fbops->fb_copyarea(info, &area);
- }
- 
-@@ -370,11 +378,15 @@
- 	cursor.image.depth = 1;
- 	cursor.rop = ROP_XOR;
- 
--	if (info->fbops->fb_cursor)
--		err = info->fbops->fb_cursor(info, &cursor);
-+	if (fbcon_decor_active(info, vc)) {
-+		fbcon_decor_cursor(info, &cursor);
-+	} else {
-+		if (info->fbops->fb_cursor)
-+			err = info->fbops->fb_cursor(info, &cursor);
- 
--	if (err)
--		soft_cursor(info, &cursor);
-+		if (err)
-+			soft_cursor(info, &cursor);
-+	}
- 
- 	ops->cursor_reset = 0;
- }
-diff -Naur vanilla-5.10/drivers/video/fbdev/core/fbcmap.c linux-5.10/drivers/video/fbdev/core/fbcmap.c
---- vanilla-5.10/drivers/video/fbdev/core/fbcmap.c	2019-10-19 17:30:53.961271599 +0200
-+++ linux-5.10/drivers/video/fbdev/core/fbcmap.c	2019-10-19 18:35:55.882917900 +0200
-@@ -17,6 +17,8 @@
- #include <linux/slab.h>
- #include <linux/uaccess.h>
- 
-+#include "../../console/fbcondecor.h"
-+
- static u16 red2[] __read_mostly = {
-     0x0000, 0xaaaa
- };
-@@ -258,9 +260,12 @@
- 				break;
- 		}
- 	}
--	if (rc == 0)
-+	if (rc == 0) {
- 		fb_copy_cmap(cmap, &info->cmap);
--
-+		if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
-+		    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
-+			fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
-+	}
- 	return rc;
- }
- 
-diff -Naur vanilla-5.10/drivers/video/fbdev/core/fbcon.c linux-5.10/drivers/video/fbdev/core/fbcon.c
---- vanilla-5.10/drivers/video/fbdev/core/fbcon.c	2019-10-19 17:30:53.962271613 +0200
-+++ linux-5.10/drivers/video/fbdev/core/fbcon.c	2019-10-19 18:37:28.607279343 +0200
-@@ -81,6 +81,7 @@
- #include <asm/irq.h>
- 
- #include "fbcon.h"
-+#include "../../console/fbcondecor.h"
- 
- #ifdef FBCONDEBUG
- #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
-@@ -115,7 +116,7 @@
- 
- static struct fbcon_display fb_display[MAX_NR_CONSOLES];
- 
--static signed char con2fb_map[MAX_NR_CONSOLES];
-+signed char con2fb_map[MAX_NR_CONSOLES];
- static signed char con2fb_map_boot[MAX_NR_CONSOLES];
- 
- static int logo_lines;
-@@ -296,7 +297,7 @@
- 		vc->vc_mode != KD_TEXT || ops->graphics);
- }
- 
--static int get_color(struct vc_data *vc, struct fb_info *info,
-+int get_color(struct vc_data *vc, struct fb_info *info,
- 	      u16 c, int is_fg)
- {
- 	int depth = fb_get_color_depth(&info->var, &info->fix);
-@@ -566,6 +567,9 @@
- 		info_idx = -1;
- 	} else {
- 		fbcon_has_console_bind = 1;
-+#ifdef CONFIG_FB_CON_DECOR
-+		fbcon_decor_init();
-+#endif
- 	}
- 
- 	return err;
-@@ -1013,6 +1017,12 @@
- 	rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- 	cols /= vc->vc_font.width;
- 	rows /= vc->vc_font.height;
-+
-+	if (fbcon_decor_active(info, vc)) {
-+		cols = vc->vc_decor.twidth / vc->vc_font.width;
-+		rows = vc->vc_decor.theight / vc->vc_font.height;
-+	}
-+
- 	vc_resize(vc, cols, rows);
- 
- 	DPRINTK("mode:   %s\n", info->fix.id);
-@@ -1048,7 +1058,7 @@
- 		logo_shown = FBCON_LOGO_DONTSHOW;
- 
- 	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
--	    (info->fix.type == FB_TYPE_TEXT))
-+	    (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc))
- 		logo = 0;
- 
- 	if (var_to_display(p, &info->var, info))
-@@ -1283,6 +1293,11 @@
- 		fbcon_clear_margins(vc, 0);
- 	}
- 
-+	if (fbcon_decor_active(info, vc)) {
-+		fbcon_decor_clear(vc, info, sy, sx, height, width);
-+		return;
-+	}
-+
- 	/* Split blits that cross physical y_wrap boundary */
- 
- 	y_break = p->vrows - p->yscroll;
-@@ -1302,10 +1317,15 @@
- 	struct fbcon_display *p = &fb_display[vc->vc_num];
- 	struct fbcon_ops *ops = info->fbcon_par;
- 
--	if (!fbcon_is_inactive(vc, info))
--		ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
--			   get_color(vc, info, scr_readw(s), 1),
--			   get_color(vc, info, scr_readw(s), 0));
-+	if (!fbcon_is_inactive(vc, info)) {
-+
-+		if (fbcon_decor_active(info, vc))
-+			fbcon_decor_putcs(vc, info, s, count, ypos, xpos);
-+		else
-+			ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
-+				   get_color(vc, info, scr_readw(s), 1),
-+				   get_color(vc, info, scr_readw(s), 0));
-+	}
- }
- 
- static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
-@@ -1321,8 +1341,12 @@
- 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
- 	struct fbcon_ops *ops = info->fbcon_par;
- 
--	if (!fbcon_is_inactive(vc, info))
--		ops->clear_margins(vc, info, margin_color, bottom_only);
-+	if (!fbcon_is_inactive(vc, info)) {
-+		if (fbcon_decor_active(info, vc))
-+			fbcon_decor_clear_margins(vc, info, bottom_only);
-+		else
-+			ops->clear_margins(vc, info, margin_color, bottom_only);
-+	}
- }
- 
- static void fbcon_cursor(struct vc_data *vc, int mode)
-@@ -1712,7 +1736,7 @@
- 	case SM_UP:
- 		if (count > vc->vc_rows)	/* Maximum realistic size */
- 			count = vc->vc_rows;
--		if (logo_shown >= 0)
-+		if (logo_shown >= 0 || fbcon_decor_active(info, vc))
- 			goto redraw_up;
- 		switch (p->scrollmode) {
- 		case SCROLL_MOVE:
-@@ -1804,6 +1828,8 @@
- 			count = vc->vc_rows;
- 		if (logo_shown >= 0)
- 			goto redraw_down;
-+		if (fbcon_decor_active(info, vc))
-+			goto redraw_down;
- 		switch (p->scrollmode) {
- 		case SCROLL_MOVE:
- 			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
-@@ -1951,6 +1977,13 @@
- 		}
- 		return;
- 	}
-+
-+	if (fbcon_decor_active(info, vc) && sy == dy && height == 1) {
-+		/* must use slower redraw bmove to keep background pic intact */
-+		fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width);
-+		return;
-+	}
-+
- 	ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
- 		   height, width);
- }
-@@ -2042,8 +2075,8 @@
- 	var.yres = virt_h * virt_fh;
- 	x_diff = info->var.xres - var.xres;
- 	y_diff = info->var.yres - var.yres;
--	if (x_diff < 0 || x_diff > virt_fw ||
--	    y_diff < 0 || y_diff > virt_fh) {
-+	if ((x_diff < 0 || x_diff > virt_fw ||
-+		y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) {
- 		const struct fb_videomode *mode;
- 
- 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
-@@ -2079,6 +2112,22 @@
- 
- 	info = registered_fb[con2fb_map[vc->vc_num]];
- 	ops = info->fbcon_par;
-+	prev_console = ops->currcon;
-+	if (prev_console != -1)
-+		old_info = registered_fb[con2fb_map[prev_console]];
-+
-+#ifdef CONFIG_FB_CON_DECOR
-+	if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-+		struct vc_data *vc_curr = vc_cons[prev_console].d;
-+
-+		if (vc_curr && fbcon_decor_active_vc(vc_curr)) {
-+			// Clear the screen to avoid displaying funky colors
-+			// during palette updates.
-+			memset((u8 *)info->screen_base + info->fix.line_length * info->var.yoffset,
-+			       0, info->var.yres * info->fix.line_length);
-+		}
-+	}
-+#endif
- 
- 	if (logo_shown >= 0) {
- 		struct vc_data *conp2 = vc_cons[logo_shown].d;
-@@ -2089,9 +2138,6 @@
- 		logo_shown = FBCON_LOGO_CANSHOW;
- 	}
- 
--	prev_console = ops->currcon;
--	if (prev_console != -1)
--		old_info = registered_fb[con2fb_map[prev_console]];
- 	/*
- 	 * FIXME: If we have multiple fbdev's loaded, we need to
- 	 * update all info->currcon.  Perhaps, we can place this
-@@ -2135,6 +2181,18 @@
- 			fbcon_del_cursor_timer(old_info);
- 	}
- 
-+	if (fbcon_decor_active_vc(vc)) {
-+		struct vc_data *vc_curr = vc_cons[prev_console].d;
-+
-+		if (!vc_curr->vc_decor.theme ||
-+			strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) ||
-+			(fbcon_decor_active_nores(info, vc_curr) &&
-+			 !fbcon_decor_active(info, vc_curr))) {
-+			fbcon_decor_disable(vc, 0);
-+			fbcon_decor_call_helper("modechange", vc->vc_num);
-+		}
-+	}
-+
- 	if (fbcon_is_inactive(vc, info) ||
- 	    ops->blank_state != FB_BLANK_UNBLANK)
- 		fbcon_del_cursor_timer(info);
-@@ -2234,14 +2292,18 @@
- 		}
- 	}
- 
-- 	if (!fbcon_is_inactive(vc, info)) {
-+	if (!fbcon_is_inactive(vc, info)) {
- 		if (ops->blank_state != blank) {
- 			ops->blank_state = blank;
- 			fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
- 			ops->cursor_flash = (!blank);
- 
--			if (fb_blank(info, blank))
--				fbcon_generic_blank(vc, info, blank);
-+			if (fb_blank(info, blank)) {
-+				if (fbcon_decor_active(info, vc))
-+					fbcon_decor_blank(vc, info, blank);
-+				else
-+					fbcon_generic_blank(vc, info, blank);
-+			}
- 		}
- 
- 		if (!blank)
-@@ -2433,13 +2495,22 @@
- 		set_vc_hi_font(vc, true);
- 
- 	if (resize) {
-+		/* reset wrap/pan */
- 		int cols, rows;
- 
- 		cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
-+
-+		if (fbcon_decor_active(info, vc)) {
-+			info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-+			cols = vc->vc_decor.twidth;
-+			rows = vc->vc_decor.theight;
-+		}
- 		cols /= w;
- 		rows /= h;
-+
- 		vc_resize(vc, cols, rows);
-+
- 	} else if (con_is_visible(vc)
- 		   && vc->vc_mode == KD_TEXT) {
- 		fbcon_clear_margins(vc, 0);
-@@ -2567,7 +2638,11 @@
- 	int i, j, k, depth;
- 	u8 val;
- 
--	if (fbcon_is_inactive(vc, info))
-+	if (fbcon_is_inactive(vc, info)
-+#ifdef CONFIG_FB_CON_DECOR
-+			|| vc->vc_num != fg_console
-+#endif
-+		)
- 		return;
- 
- 	if (!con_is_visible(vc))
-@@ -2593,7 +2668,47 @@
- 	} else
- 		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
- 
--	fb_set_cmap(&palette_cmap, info);
-+	if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
-+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-+
-+		u16 *red, *green, *blue;
-+		int minlen = min(min(info->var.red.length, info->var.green.length),
-+				     info->var.blue.length);
-+
-+		struct fb_cmap cmap = {
-+			.start = 0,
-+			.len = (1 << minlen),
-+			.red = NULL,
-+			.green = NULL,
-+			.blue = NULL,
-+			.transp = NULL
-+		};
-+
-+		red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
-+
-+		if (!red)
-+			goto out;
-+
-+		green = red + 256;
-+		blue = green + 256;
-+		cmap.red = red;
-+		cmap.green = green;
-+		cmap.blue = blue;
-+
-+		for (i = 0; i < cmap.len; i++)
-+			red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
-+
-+		fb_set_cmap(&cmap, info);
-+		fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
-+		kfree(red);
-+
-+		return;
-+
-+	} else if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
-+		   info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL)
-+		fb_set_cmap(&info->bgdecor.cmap, info);
-+
-+out:	fb_set_cmap(&palette_cmap, info);
- }
- 
- static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset)
-@@ -2691,7 +2806,14 @@
- 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- 		cols /= vc->vc_font.width;
- 		rows /= vc->vc_font.height;
--		vc_resize(vc, cols, rows);
-+
-+		if (!fbcon_decor_active_nores(info, vc)) {
-+			vc_resize(vc, cols, rows);
-+		} else {
-+			fbcon_decor_disable(vc, 0);
-+			fbcon_decor_call_helper("modechange", vc->vc_num);
-+		}
-+
- 		updatescrollmode(p, info, vc);
- 		scrollback_max = 0;
- 		scrollback_current = 0;
-@@ -2734,7 +2856,8 @@
- 		rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- 		cols /= vc->vc_font.width;
- 		rows /= vc->vc_font.height;
--		vc_resize(vc, cols, rows);
-+		if (!fbcon_decor_active_nores(info, vc))
-+			vc_resize(vc, cols, rows);
- 	}
- 
- 	if (fg != -1)
-@@ -3383,6 +3506,7 @@
- 				info->queue.func = NULL;
- 		}
- 	}
-+	fbcon_decor_exit();
- }
- 
- void __init fb_console_init(void)
-diff -Naur vanilla-5.10/drivers/video/fbdev/core/fbmem.c linux-5.10/drivers/video/fbdev/core/fbmem.c
---- vanilla-5.10/drivers/video/fbdev/core/fbmem.c	2019-10-19 17:30:53.963271629 +0200
-+++ linux-5.10/drivers/video/fbdev/core/fbmem.c	2019-10-19 18:35:55.883917927 +0200
-@@ -1203,15 +1203,6 @@
- 	u16			reserved[3];
- };
- 
--struct fb_cmap32 {
--	u32			start;
--	u32			len;
--	compat_caddr_t	red;
--	compat_caddr_t	green;
--	compat_caddr_t	blue;
--	compat_caddr_t	transp;
--};
--
- static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
- 			  unsigned long arg)
- {
-diff -Naur vanilla-5.10/include/linux/console_decor.h linux-5.10/include/linux/console_decor.h
---- vanilla-5.10/include/linux/console_decor.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.10/include/linux/console_decor.h	2019-10-19 18:35:55.883917927 +0200
-@@ -0,0 +1,46 @@
-+#ifndef _LINUX_CONSOLE_DECOR_H_
-+#define _LINUX_CONSOLE_DECOR_H_ 1
-+
-+/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */
-+struct vc_decor {
-+	__u8 bg_color;				/* The color that is to be treated as transparent */
-+	__u8 state;				/* Current decor state: 0 = off, 1 = on */
-+	__u16 tx, ty;				/* Top left corner coordinates of the text field */
-+	__u16 twidth, theight;			/* Width and height of the text field */
-+	char *theme;
-+};
-+
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+#include <linux/compat.h>
-+
-+struct vc_decor32 {
-+	__u8 bg_color;				/* The color that is to be treated as transparent */
-+	__u8 state;				/* Current decor state: 0 = off, 1 = on */
-+	__u16 tx, ty;				/* Top left corner coordinates of the text field */
-+	__u16 twidth, theight;			/* Width and height of the text field */
-+	compat_uptr_t theme;
-+};
-+
-+#define vc_decor_from_compat(to, from) \
-+	(to).bg_color = (from).bg_color; \
-+	(to).state    = (from).state; \
-+	(to).tx       = (from).tx; \
-+	(to).ty       = (from).ty; \
-+	(to).twidth   = (from).twidth; \
-+	(to).theight  = (from).theight; \
-+	(to).theme    = compat_ptr((from).theme)
-+
-+#define vc_decor_to_compat(to, from) \
-+	(to).bg_color = (from).bg_color; \
-+	(to).state    = (from).state; \
-+	(to).tx       = (from).tx; \
-+	(to).ty       = (from).ty; \
-+	(to).twidth   = (from).twidth; \
-+	(to).theight  = (from).theight; \
-+	(to).theme    = ptr_to_compat((from).theme)
-+
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
-+#endif
-diff -Naur vanilla-5.10/include/linux/console_struct.h linux-5.10/include/linux/console_struct.h
---- vanilla-5.10/include/linux/console_struct.h	2019-10-19 17:30:54.225275535 +0200
-+++ linux-5.10/include/linux/console_struct.h	2019-10-19 18:35:55.883917927 +0200
-@@ -22,6 +22,7 @@
- 
- #define NPAR 16
- #define VC_TABSTOPS_COUNT	256U
-+#include <linux/console_decor.h>
- 
- enum vc_intensity {
- 	VCI_HALF_BRIGHT,
-@@ -159,6 +160,8 @@
- 	struct uni_pagedir *vc_uni_pagedir;
- 	struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
- 	struct uni_screen *vc_uni_screen;	/* unicode screen content */
-+
-+	struct vc_decor vc_decor;
- 	/* additional information is in vt_kern.h */
- };
- 
-diff -Naur vanilla-5.10/include/linux/fb.h linux-5.10/include/linux/fb.h
---- vanilla-5.10/include/linux/fb.h	2019-10-19 17:30:54.230275610 +0200
-+++ linux-5.10/include/linux/fb.h	2019-10-19 18:35:55.884917953 +0200
-@@ -211,6 +211,34 @@
- };
- #endif
- 
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+struct fb_image32 {
-+	__u32 dx;			/* Where to place image */
-+	__u32 dy;
-+	__u32 width;			/* Size of image */
-+	__u32 height;
-+	__u32 fg_color;			/* Only used when a mono bitmap */
-+	__u32 bg_color;
-+	__u8  depth;			/* Depth of the image */
-+	const compat_uptr_t data;	/* Pointer to image data */
-+	struct fb_cmap32 cmap;		/* color map info */
-+};
-+
-+#define fb_image_from_compat(to, from) \
-+	(to).dx       = (from).dx; \
-+	(to).dy       = (from).dy; \
-+	(to).width    = (from).width; \
-+	(to).height   = (from).height; \
-+	(to).fg_color = (from).fg_color; \
-+	(to).bg_color = (from).bg_color; \
-+	(to).depth    = (from).depth; \
-+	(to).data     = compat_ptr((from).data); \
-+	fb_cmap_from_compat((to).cmap, (from).cmap)
-+
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
- /*
-  * Frame buffer operations
-  *
-@@ -487,6 +515,9 @@
- #define FBINFO_STATE_SUSPENDED	1
- 	u32 state;			/* Hardware state i.e suspend */
- 	void *fbcon_par;                /* fbcon use-only private area */
-+
-+	struct fb_image bgdecor;
-+
- 	/* From here on everything is device dependent */
- 	void *par;
- 	/* we need the PCI or similar aperture base/size not
-diff -Naur vanilla-5.10/include/uapi/linux/fb.h linux-5.10/include/uapi/linux/fb.h
---- vanilla-5.10/include/uapi/linux/fb.h	2019-07-30 18:50:35.103716407 +0200
-+++ linux-5.10/include/uapi/linux/fb.h	2019-10-19 18:35:55.884917953 +0200
-@@ -9,6 +9,23 @@
- 
- #define FB_MAX			32	/* sufficient for now */
- 
-+struct fbcon_decor_iowrapper {
-+	unsigned short vc;		/* Virtual console */
-+	unsigned char origin;		/* Point of origin of the request */
-+	void *data;
-+};
-+
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+#include <linux/compat.h>
-+struct fbcon_decor_iowrapper32 {
-+	unsigned short vc;		/* Virtual console */
-+	unsigned char origin;		/* Point of origin of the request */
-+	compat_uptr_t data;
-+};
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
- /* ioctls
-    0x46 is 'F'								*/
- #define FBIOGET_VSCREENINFO	0x4600
-@@ -36,6 +53,25 @@
- #define FBIOGET_DISPINFO        0x4618
- #define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
- 
-+#define FBIOCONDECOR_SETCFG	_IOWR('F', 0x19, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_GETCFG	_IOR('F', 0x1A, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_SETSTATE	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_GETSTATE	_IOR('F', 0x1C, struct fbcon_decor_iowrapper)
-+#define FBIOCONDECOR_SETPIC	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+#define FBIOCONDECOR_SETCFG32	_IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_GETCFG32	_IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_SETSTATE32	_IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_GETSTATE32	_IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
-+#define FBIOCONDECOR_SETPIC32	_IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
-+#define FBCON_DECOR_THEME_LEN		128	/* Maximum length of a theme name */
-+#define FBCON_DECOR_IO_ORIG_KERNEL	0	/* Kernel ioctl origin */
-+#define FBCON_DECOR_IO_ORIG_USER	1	/* User ioctl origin */
-+
- #define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/
- #define FB_TYPE_PLANES			1	/* Non interleaved planes */
- #define FB_TYPE_INTERLEAVED_PLANES	2	/* Interleaved planes	*/
-@@ -279,6 +315,29 @@
- 	__u32 reserved[4];		/* Reserved for future compatibility */
- };
- 
-+#ifdef __KERNEL__
-+#ifdef CONFIG_COMPAT
-+struct fb_cmap32 {
-+	__u32 start;
-+	__u32 len;			/* Number of entries */
-+	compat_uptr_t red;		/* Red values	*/
-+	compat_uptr_t green;
-+	compat_uptr_t blue;
-+	compat_uptr_t transp;		/* transparency, can be NULL */
-+};
-+
-+#define fb_cmap_from_compat(to, from) \
-+	(to).start  = (from).start; \
-+	(to).len    = (from).len; \
-+	(to).red    = compat_ptr((from).red); \
-+	(to).green  = compat_ptr((from).green); \
-+	(to).blue   = compat_ptr((from).blue); \
-+	(to).transp = compat_ptr((from).transp)
-+
-+#endif /* CONFIG_COMPAT */
-+#endif /* __KERNEL__ */
-+
-+
- struct fb_cmap {
- 	__u32 start;			/* First entry	*/
- 	__u32 len;			/* Number of entries */
-diff -Naur vanilla-5.10/kernel/sysctl.c linux-5.10/kernel/sysctl.c
---- vanilla-5.10/kernel/sysctl.c	2019-10-19 17:30:54.448278856 +0200
-+++ linux-5.10/kernel/sysctl.c	2019-10-19 18:35:55.884917953 +0200
-@@ -145,6 +145,10 @@
- static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
- #endif
- 
-+#ifdef CONFIG_FB_CON_DECOR
-+extern char fbcon_decor_path[];
-+#endif
-+
- #ifdef CONFIG_INOTIFY_USER
- #include <linux/inotify.h>
- #endif
-@@ -3394,6 +3398,15 @@
- 		.mode		= 0555,
- 		.child		= dev_table,
- 	},
-+#ifdef CONFIG_FB_CON_DECOR
-+	{
-+		.procname	= "fbcondecor",
-+		.data		= &fbcon_decor_path,
-+		.maxlen		= KMOD_PATH_LEN,
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dostring,
-+	},
-+#endif
- 	{ }
- };
- 
Index: npl/kernel/linux_src/linux-4.14-imq.diff
===================================================================
--- npl/kernel/linux_src/linux-4.14-imq.diff	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ 	(revision )
@@ -1,1759 +1,0 @@
-diff -Naupr linux-4.14_orig/drivers/net/imq.c linux-4.14/drivers/net/imq.c
---- linux-4.14_orig/drivers/net/imq.c	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.14/drivers/net/imq.c	2017-11-13 11:46:45.844089945 +0700
-@@ -0,0 +1,962 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ *			   See Credits.txt
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+#include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+#include <net/sock.h>
-+#include <linux/ip.h>
-+#include <linux/ipv6.h>
-+#include <linux/if_vlan.h>
-+#include <linux/if_pppox.h>
-+#include <net/ip.h>
-+#include <net/ipv6.h>
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num);
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ops[] = {
-+	{
-+	/* imq_ingress_ipv4 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET,
-+		.hooknum	= NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+		.priority	= NF_IP_PRI_MANGLE + 1,
-+#else
-+		.priority	= NF_IP_PRI_NAT_DST + 1,
-+#endif
-+	},
-+	{
-+	/* imq_egress_ipv4 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET,
-+		.hooknum	= NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+		.priority	= NF_IP_PRI_LAST,
-+#else
-+		.priority	= NF_IP_PRI_NAT_SRC - 1,
-+#endif
-+	},
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+	{
-+	/* imq_ingress_ipv6 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET6,
-+		.hooknum	= NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+		.priority	= NF_IP6_PRI_MANGLE + 1,
-+#else
-+		.priority	= NF_IP6_PRI_NAT_DST + 1,
-+#endif
-+	},
-+	{
-+	/* imq_egress_ipv6 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET6,
-+		.hooknum	= NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+		.priority	= NF_IP6_PRI_LAST,
-+#else
-+		.priority	= NF_IP6_PRI_NAT_SRC - 1,
-+#endif
-+	},
-+#endif
-+};
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+#define IMQ_MAX_QUEUES 32
-+static int numqueues = 1;
-+static u32 imq_hashrnd;
-+static int imq_dev_accurate_stats = 1;
-+
-+static inline __be16 pppoe_proto(const struct sk_buff *skb)
-+{
-+	return *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
-+			sizeof(struct pppoe_hdr)));
-+}
-+
-+static u16 imq_hash(struct net_device *dev, struct sk_buff *skb)
-+{
-+	unsigned int pull_len;
-+	u16 protocol = skb->protocol;
-+	u32 addr1, addr2;
-+	u32 hash, ihl = 0;
-+	union {
-+		u16 in16[2];
-+		u32 in32;
-+	} ports;
-+	u8 ip_proto;
-+
-+	pull_len = 0;
-+
-+recheck:
-+	switch (protocol) {
-+	case htons(ETH_P_8021Q): {
-+		if (unlikely(skb_pull(skb, VLAN_HLEN) == NULL))
-+			goto other;
-+
-+		pull_len += VLAN_HLEN;
-+		skb->network_header += VLAN_HLEN;
-+
-+		protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-+		goto recheck;
-+	}
-+
-+	case htons(ETH_P_PPP_SES): {
-+		if (unlikely(skb_pull(skb, PPPOE_SES_HLEN) == NULL))
-+			goto other;
-+
-+		pull_len += PPPOE_SES_HLEN;
-+		skb->network_header += PPPOE_SES_HLEN;
-+
-+		protocol = pppoe_proto(skb);
-+		goto recheck;
-+	}
-+
-+	case htons(ETH_P_IP): {
-+		const struct iphdr *iph = ip_hdr(skb);
-+
-+		if (unlikely(!pskb_may_pull(skb, sizeof(struct iphdr))))
-+			goto other;
-+
-+		addr1 = iph->daddr;
-+		addr2 = iph->saddr;
-+
-+		ip_proto = !(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) ?
-+				 iph->protocol : 0;
-+		ihl = ip_hdrlen(skb);
-+
-+		break;
-+	}
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+	case htons(ETH_P_IPV6): {
-+		const struct ipv6hdr *iph = ipv6_hdr(skb);
-+		__be16 fo = 0;
-+
-+		if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr))))
-+			goto other;
-+
-+		addr1 = iph->daddr.s6_addr32[3];
-+		addr2 = iph->saddr.s6_addr32[3];
-+		ihl = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &ip_proto,
-+				       &fo);
-+		if (unlikely(ihl < 0))
-+			goto other;
-+
-+		break;
-+	}
-+#endif
-+	default:
-+other:
-+		if (pull_len != 0) {
-+			skb_push(skb, pull_len);
-+			skb->network_header -= pull_len;
-+		}
-+
-+		return (u16)(ntohs(protocol) % dev->real_num_tx_queues);
-+	}
-+
-+	if (addr1 > addr2)
-+		swap(addr1, addr2);
-+
-+	switch (ip_proto) {
-+	case IPPROTO_TCP:
-+	case IPPROTO_UDP:
-+	case IPPROTO_DCCP:
-+	case IPPROTO_ESP:
-+	case IPPROTO_AH:
-+	case IPPROTO_SCTP:
-+	case IPPROTO_UDPLITE: {
-+		if (likely(skb_copy_bits(skb, ihl, &ports.in32, 4) >= 0)) {
-+			if (ports.in16[0] > ports.in16[1])
-+				swap(ports.in16[0], ports.in16[1]);
-+			break;
-+		}
-+		/* fall-through */
-+	}
-+	default:
-+		ports.in32 = 0;
-+		break;
-+	}
-+
-+	if (pull_len != 0) {
-+		skb_push(skb, pull_len);
-+		skb->network_header -= pull_len;
-+	}
-+
-+	hash = jhash_3words(addr1, addr2, ports.in32, imq_hashrnd ^ ip_proto);
-+
-+	return (u16)(((u64)hash * dev->real_num_tx_queues) >> 32);
-+}
-+
-+static inline bool sk_tx_queue_recorded(struct sock *sk)
-+{
-+	return (sk_tx_queue_get(sk) >= 0);
-+}
-+
-+static struct netdev_queue *imq_select_queue(struct net_device *dev,
-+						struct sk_buff *skb)
-+{
-+	u16 queue_index = 0;
-+	u32 hash;
-+
-+	if (likely(dev->real_num_tx_queues == 1))
-+		goto out;
-+
-+	/* IMQ can be receiving ingress or engress packets. */
-+
-+	/* Check first for if rx_queue is set */
-+	if (skb_rx_queue_recorded(skb)) {
-+		queue_index = skb_get_rx_queue(skb);
-+		goto out;
-+	}
-+
-+	/* Check if socket has tx_queue set */
-+	if (sk_tx_queue_recorded(skb->sk)) {
-+		queue_index = sk_tx_queue_get(skb->sk);
-+		goto out;
-+	}
-+
-+	/* Try use socket hash */
-+	if (skb->sk && skb->sk->sk_hash) {
-+		hash = skb->sk->sk_hash;
-+		queue_index =
-+			(u16)(((u64)hash * dev->real_num_tx_queues) >> 32);
-+		goto out;
-+	}
-+
-+	/* Generate hash from packet data */
-+	queue_index = imq_hash(dev, skb);
-+
-+out:
-+	if (unlikely(queue_index >= dev->real_num_tx_queues))
-+		queue_index = (u16)((u32)queue_index % dev->real_num_tx_queues);
-+
-+	skb_set_queue_mapping(skb, queue_index);
-+	return netdev_get_tx_queue(dev, queue_index);
-+}
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+	return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+	struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+	skb->nf_queue_entry = NULL;
-+
-+	if (entry) {
-+		nf_queue_entry_release_refs(entry);
-+		kfree(entry);
-+	}
-+
-+	skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+static void imq_done_check_queue_mapping(struct sk_buff *skb,
-+					 struct net_device *dev)
-+{
-+	unsigned int queue_index;
-+
-+	/* Don't let queue_mapping be left too large after exiting IMQ */
-+	if (likely(skb->dev != dev && skb->dev != NULL)) {
-+		queue_index = skb_get_queue_mapping(skb);
-+		if (unlikely(queue_index >= skb->dev->real_num_tx_queues)) {
-+			queue_index = (u16)((u32)queue_index %
-+						skb->dev->real_num_tx_queues);
-+			skb_set_queue_mapping(skb, queue_index);
-+		}
-+	} else {
-+		/* skb->dev was IMQ device itself or NULL, be on safe side and
-+		 * just clear queue mapping.
-+		 */
-+		skb_set_queue_mapping(skb, 0);
-+	}
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+	struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+	rcu_read_lock();
-+
-+	skb->nf_queue_entry = NULL;
-+	netif_trans_update(dev);
-+
-+	dev->stats.tx_bytes += skb->len;
-+	dev->stats.tx_packets++;
-+
-+	if (unlikely(entry == NULL)) {
-+		/* We don't know what is going on here.. packet is queued for
-+		 * imq device, but (probably) not by us.
-+		 *
-+		 * If this packet was not send here by imq_nf_queue(), then
-+		 * skb_save_cb() was not used and skb_free() should not show:
-+		 *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+		 * and/or
-+		 *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+		 *
-+		 * However if this message is shown, then IMQ is somehow broken
-+		 * and you should report this to linuximq.net.
-+		 */
-+
-+		/* imq_dev_xmit is black hole that eats all packets, report that
-+		 * we eat this packet happily and increase dropped counters.
-+		 */
-+
-+		dev->stats.tx_dropped++;
-+		dev_kfree_skb(skb);
-+
-+		rcu_read_unlock();
-+		return NETDEV_TX_OK;
-+	}
-+
-+	skb_restore_cb(skb); /* restore skb->cb */
-+
-+	skb->imq_flags = 0;
-+	skb->destructor = NULL;
-+
-+	imq_done_check_queue_mapping(skb, dev);
-+
-+	nf_reinject(entry, NF_ACCEPT);
-+
-+	rcu_read_unlock();
-+	return NETDEV_TX_OK;
-+}
-+
-+static struct net_device *get_imq_device_by_index(int index)
-+{
-+	struct net_device *dev = NULL;
-+	struct net *net;
-+	char buf[8];
-+
-+	/* get device by name and cache result */
-+	snprintf(buf, sizeof(buf), "imq%d", index);
-+
-+	/* Search device from all namespaces. */
-+	for_each_net(net) {
-+		dev = dev_get_by_name(net, buf);
-+		if (dev)
-+			break;
-+	}
-+
-+	if (WARN_ON_ONCE(dev == NULL)) {
-+		/* IMQ device not found. Exotic config? */
-+		return ERR_PTR(-ENODEV);
-+	}
-+
-+	imq_devs_cache[index] = dev;
-+	dev_put(dev);
-+
-+	return dev;
-+}
-+
-+static struct nf_queue_entry *nf_queue_entry_dup(struct nf_queue_entry *e)
-+{
-+	struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC);
-+	if (entry) {
-+		nf_queue_entry_get_refs(entry);
-+		return entry;
-+	}
-+	return NULL;
-+}
-+
-+#ifdef CONFIG_BRIDGE_NETFILTER
-+/* When called from bridge netfilter, skb->data must point to MAC header
-+ * before calling skb_gso_segment(). Else, original MAC header is lost
-+ * and segmented skbs will be sent to wrong destination.
-+ */
-+static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
-+{
-+	if (skb->nf_bridge)
-+		__skb_push(skb, skb->network_header - skb->mac_header);
-+}
-+
-+static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
-+{
-+	if (skb->nf_bridge)
-+		__skb_pull(skb, skb->network_header - skb->mac_header);
-+}
-+#else
-+#define nf_bridge_adjust_skb_data(s) do {} while (0)
-+#define nf_bridge_adjust_segmented_data(s) do {} while (0)
-+#endif
-+
-+static void free_entry(struct nf_queue_entry *entry)
-+{
-+	nf_queue_entry_release_refs(entry);
-+	kfree(entry);
-+}
-+
-+static int __imq_nf_queue(struct nf_queue_entry *entry, struct net_device *dev);
-+
-+static int __imq_nf_queue_gso(struct nf_queue_entry *entry,
-+			      struct net_device *dev, struct sk_buff *skb)
-+{
-+	int ret = -ENOMEM;
-+	struct nf_queue_entry *entry_seg;
-+
-+	nf_bridge_adjust_segmented_data(skb);
-+
-+	if (skb->next == NULL) { /* last packet, no need to copy entry */
-+		struct sk_buff *gso_skb = entry->skb;
-+		entry->skb = skb;
-+		ret = __imq_nf_queue(entry, dev);
-+		if (ret)
-+			entry->skb = gso_skb;
-+		return ret;
-+	}
-+
-+	skb->next = NULL;
-+
-+	entry_seg = nf_queue_entry_dup(entry);
-+	if (entry_seg) {
-+		entry_seg->skb = skb;
-+		ret = __imq_nf_queue(entry_seg, dev);
-+		if (ret)
-+			free_entry(entry_seg);
-+	}
-+	return ret;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+	struct sk_buff *skb, *segs;
-+	struct net_device *dev;
-+	unsigned int queued;
-+	int index, retval, err;
-+
-+	index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+	if (unlikely(index > numdevs - 1)) {
-+		if (net_ratelimit())
-+			pr_warn("IMQ: invalid device specified, highest is %u\n",
-+				numdevs - 1);
-+		retval = -EINVAL;
-+		goto out_no_dev;
-+	}
-+
-+	/* check for imq device by index from cache */
-+	dev = imq_devs_cache[index];
-+	if (unlikely(!dev)) {
-+		dev = get_imq_device_by_index(index);
-+		if (IS_ERR(dev)) {
-+			retval = PTR_ERR(dev);
-+			goto out_no_dev;
-+		}
-+	}
-+
-+	if (unlikely(!(dev->flags & IFF_UP))) {
-+		entry->skb->imq_flags = 0;
-+		retval = -ECANCELED;
-+		goto out_no_dev;
-+	}
-+
-+	/* Since 3.10.x, GSO handling moved here as result of upstream commit
-+	 * a5fedd43d5f6c94c71053a66e4c3d2e35f1731a2 (netfilter: move
-+	 * skb_gso_segment into nfnetlink_queue module).
-+	 *
-+	 * Following code replicates the gso handling from
-+	 * 'net/netfilter/nfnetlink_queue_core.c':nfqnl_enqueue_packet().
-+	 */
-+
-+	skb = entry->skb;
-+
-+	switch (entry->state.pf) {
-+	case NFPROTO_IPV4:
-+		skb->protocol = htons(ETH_P_IP);
-+		break;
-+	case NFPROTO_IPV6:
-+		skb->protocol = htons(ETH_P_IPV6);
-+		break;
-+	}
-+
-+	if (!skb_is_gso(entry->skb))
-+		return __imq_nf_queue(entry, dev);
-+
-+	nf_bridge_adjust_skb_data(skb);
-+	segs = skb_gso_segment(skb, 0);
-+	/* Does not use PTR_ERR to limit the number of error codes that can be
-+	 * returned by nf_queue.  For instance, callers rely on -ECANCELED to
-+	 * mean 'ignore this hook'.
-+	 */
-+	err = -ENOBUFS;
-+	if (IS_ERR(segs))
-+		goto out_err;
-+	queued = 0;
-+	err = 0;
-+	do {
-+		struct sk_buff *nskb = segs->next;
-+		if (nskb && nskb->next)
-+			nskb->cb_next = NULL;
-+		if (err == 0)
-+			err = __imq_nf_queue_gso(entry, dev, segs);
-+		if (err == 0)
-+			queued++;
-+		else
-+			kfree_skb(segs);
-+		segs = nskb;
-+	} while (segs);
-+
-+	if (queued) {
-+		if (err) /* some segments are already queued */
-+			free_entry(entry);
-+		kfree_skb(skb);
-+		return 0;
-+	}
-+
-+out_err:
-+	nf_bridge_adjust_segmented_data(skb);
-+	retval = err;
-+out_no_dev:
-+	return retval;
-+}
-+
-+static int __imq_nf_queue(struct nf_queue_entry *entry, struct net_device *dev)
-+{
-+	struct sk_buff *skb_orig, *skb, *skb_shared, *skb_popd;
-+	struct Qdisc *q;
-+	struct sk_buff *to_free = NULL;
-+	struct netdev_queue *txq;
-+	spinlock_t *root_lock;
-+	int users;
-+	int retval = -EINVAL;
-+	unsigned int orig_queue_index;
-+
-+	dev->last_rx = jiffies;
-+
-+	skb = entry->skb;
-+	skb_orig = NULL;
-+
-+	/* skb has owner? => make clone */
-+	if (unlikely(skb->destructor)) {
-+		skb_orig = skb;
-+		skb = skb_clone(skb, GFP_ATOMIC);
-+		if (unlikely(!skb)) {
-+			retval = -ENOMEM;
-+			goto out;
-+		}
-+		skb->cb_next = NULL;
-+		entry->skb = skb;
-+	}
-+
-+	dev->stats.rx_bytes += skb->len;
-+	dev->stats.rx_packets++;
-+
-+	if (!skb->dev) {
-+		/* skb->dev == NULL causes problems, try the find cause. */
-+		if (net_ratelimit()) {
-+			dev_warn(&dev->dev,
-+				 "received packet with skb->dev == NULL\n");
-+			dump_stack();
-+		}
-+
-+		skb->dev = dev;
-+	}
-+
-+	/* Disables softirqs for lock below */
-+	rcu_read_lock_bh();
-+
-+	/* Multi-queue selection */
-+	orig_queue_index = skb_get_queue_mapping(skb);
-+	txq = imq_select_queue(dev, skb);
-+
-+	q = rcu_dereference(txq->qdisc);
-+	if (unlikely(!q->enqueue))
-+		goto packet_not_eaten_by_imq_dev;
-+
-+	skb->nf_queue_entry = entry;
-+	root_lock = qdisc_lock(q);
-+	spin_lock(root_lock);
-+
-+	users = refcount_read(&skb->users);
-+
-+	skb_shared = skb_get(skb); /* increase reference count by one */
-+
-+	/* backup skb->cb, as qdisc layer will overwrite it */
-+	skb_save_cb(skb_shared);
-+	qdisc_enqueue_root(skb_shared, q, &to_free); /* might kfree_skb */
-+	if (likely(refcount_read(&skb_shared->users) == users + 1)) {
-+		bool validate;
-+
-+		kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+		skb->destructor = &imq_skb_destructor;
-+
-+		skb_popd = qdisc_dequeue_skb(q, &validate);
-+
-+		/* cloned? */
-+		if (unlikely(skb_orig))
-+			kfree_skb(skb_orig); /* free original */
-+
-+		spin_unlock(root_lock);
-+
-+#if 0
-+		/* schedule qdisc dequeue */
-+		__netif_schedule(q);
-+#else
-+		if (likely(skb_popd)) {
-+			/* Note that we validate skb (GSO, checksum, ...) outside of locks */
-+			if (validate)
-+        		skb_popd = validate_xmit_skb_list(skb_popd, dev);
-+
-+			if (skb_popd) {
-+				int dummy_ret;
-+				int cpu = smp_processor_id(); /* ok because BHs are off */
-+
-+				txq = skb_get_tx_queue(dev, skb_popd);
-+				/*
-+				IMQ device will not be frozen or stoped, and it always be successful.
-+				So we need not check its status and return value to accelerate.
-+				*/
-+				if (imq_dev_accurate_stats && txq->xmit_lock_owner != cpu) {
-+					HARD_TX_LOCK(dev, txq, cpu);
-+					if (!netif_xmit_frozen_or_stopped(txq)) {
-+						dev_hard_start_xmit(skb_popd, dev, txq, &dummy_ret);
-+					}
-+					HARD_TX_UNLOCK(dev, txq);
-+				} else {
-+					if (!netif_xmit_frozen_or_stopped(txq)) {
-+						dev_hard_start_xmit(skb_popd, dev, txq, &dummy_ret);
-+					}
-+				}
-+			}
-+		} else {
-+			/* No ready skb, then schedule it */
-+			__netif_schedule(q);
-+		}
-+#endif
-+		rcu_read_unlock_bh();
-+		retval = 0;
-+		goto out;
-+	} else {
-+		skb_restore_cb(skb_shared); /* restore skb->cb */
-+		skb->nf_queue_entry = NULL;
-+		/*
-+		 * qdisc dropped packet and decreased skb reference count of
-+		 * skb, so we don't really want to and try refree as that would
-+		 * actually destroy the skb.
-+		 */
-+		spin_unlock(root_lock);
-+		goto packet_not_eaten_by_imq_dev;
-+	}
-+
-+packet_not_eaten_by_imq_dev:
-+	skb_set_queue_mapping(skb, orig_queue_index);
-+	rcu_read_unlock_bh();
-+
-+	/* cloned? restore original */
-+	if (unlikely(skb_orig)) {
-+		kfree_skb(skb);
-+		entry->skb = skb_orig;
-+	}
-+	retval = -1;
-+out:
-+	if (unlikely(to_free)) {
-+		kfree_skb_list(to_free);
-+	}
-+	return retval;
-+}
-+static unsigned int imq_nf_hook(void *priv,
-+				struct sk_buff *skb,
-+				const struct nf_hook_state *state)
-+{
-+	return (skb->imq_flags & IMQ_F_ENQUEUE) ? NF_IMQ_QUEUE : NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+	netif_stop_queue(dev);
-+	return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+	netif_start_queue(dev);
-+	return 0;
-+}
-+
-+static struct device_type imq_device_type = {
-+	.name = "imq",
-+};
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+	.ndo_open		= imq_open,
-+	.ndo_stop		= imq_close,
-+	.ndo_start_xmit		= imq_dev_xmit,
-+	.ndo_get_stats		= imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+	dev->netdev_ops		= &imq_netdev_ops;
-+	dev->type		= ARPHRD_VOID;
-+	dev->mtu		= 16000; /* too small? */
-+	dev->tx_queue_len	= 11000; /* too big? */
-+	dev->flags		= IFF_NOARP;
-+	dev->features		= NETIF_F_SG | NETIF_F_FRAGLIST |
-+				  NETIF_F_GSO | NETIF_F_HW_CSUM |
-+				  NETIF_F_HIGHDMA;
-+	dev->priv_flags		&= ~(IFF_XMIT_DST_RELEASE |
-+				     IFF_TX_SKB_SHARING);
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[],
-+			struct netlink_ext_ack *extack)
-+{
-+	int ret = 0;
-+
-+	if (tb[IFLA_ADDRESS]) {
-+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+			ret = -EINVAL;
-+			goto end;
-+		}
-+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+			ret = -EADDRNOTAVAIL;
-+			goto end;
-+		}
-+	}
-+	return 0;
-+end:
-+	pr_warn("IMQ: imq_validate failed (%d)\n", ret);
-+	return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+	.kind		= "imq",
-+	.priv_size	= 0,
-+	.setup		= imq_setup,
-+	.validate	= imq_validate,
-+};
-+
-+static const struct nf_queue_handler imq_nfqh = {
-+	.outfn = imq_nf_queue,
-+};
-+
-+static int __net_init imq_nf_register(struct net *net)
-+{
-+	return nf_register_net_hooks(net, imq_ops,
-+				    ARRAY_SIZE(imq_ops));
-+};
-+
-+static void __net_exit imq_nf_unregister(struct net *net)
-+{
-+	nf_unregister_net_hooks(net, imq_ops,
-+			    ARRAY_SIZE(imq_ops));
-+};
-+
-+static struct pernet_operations imq_net_ops = {
-+	.init		= imq_nf_register,
-+	.exit		= imq_nf_unregister,
-+};
-+
-+static int __net_init imq_init_hooks(void)
-+{
-+	int ret;
-+	nf_register_queue_imq_handler(&imq_nfqh);
-+
-+	ret = register_pernet_subsys(&imq_net_ops);
-+	if (ret < 0)
-+		nf_unregister_queue_imq_handler();
-+
-+	return ret;
-+}
-+
-+#ifdef CONFIG_LOCKDEP
-+	static struct lock_class_key imq_netdev_addr_lock_key;
-+
-+	static void __init imq_dev_set_lockdep_one(struct net_device *dev,
-+				    struct netdev_queue *txq, void *arg)
-+	{
-+	/*
-+	 * the IMQ transmit locks can be taken recursively,
-+	 * for example with one IMQ rule for input- and one for
-+	 * output network devices in iptables!
-+	 * until we find a better solution ignore them.
-+	 */
-+		lockdep_set_novalidate_class(&txq->_xmit_lock);
-+	}
-+
-+	static void imq_dev_set_lockdep_class(struct net_device *dev)
-+		{
-+			lockdep_set_class_and_name(&dev->addr_list_lock,
-+			   			   &imq_netdev_addr_lock_key, "_xmit_addr_IMQ");
-+			netdev_for_each_tx_queue(dev, imq_dev_set_lockdep_one, NULL);
-+}
-+#else
-+	static inline void imq_dev_set_lockdep_class(struct net_device *dev)
-+		{
-+		}
-+#endif
-+
-+static int __init imq_init_one(int index)
-+{
-+	struct net_device *dev;
-+	int ret;
-+
-+	dev = alloc_netdev_mq(0, "imq%d", NET_NAME_UNKNOWN, imq_setup, numqueues);
-+	if (!dev)
-+		return -ENOMEM;
-+
-+	ret = dev_alloc_name(dev, dev->name);
-+	if (ret < 0)
-+		goto fail;
-+
-+	dev->rtnl_link_ops = &imq_link_ops;
-+	SET_NETDEV_DEVTYPE(dev, &imq_device_type);
-+	ret = register_netdevice(dev);
-+	if (ret < 0)
-+		goto fail;
-+
-+	imq_dev_set_lockdep_class(dev);
-+
-+	return 0;
-+fail:
-+	free_netdev(dev);
-+	return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+	int err, i;
-+
-+	if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+		pr_err("IMQ: numdevs has to be betweed 1 and %u\n",
-+		       IMQ_MAX_DEVS);
-+		return -EINVAL;
-+	}
-+
-+	if (numqueues < 1 || numqueues > IMQ_MAX_QUEUES) {
-+		pr_err("IMQ: numqueues has to be betweed 1 and %u\n",
-+		       IMQ_MAX_QUEUES);
-+		return -EINVAL;
-+	}
-+
-+	get_random_bytes(&imq_hashrnd, sizeof(imq_hashrnd));
-+
-+	rtnl_lock();
-+	err = __rtnl_link_register(&imq_link_ops);
-+
-+	for (i = 0; i < numdevs && !err; i++)
-+		err = imq_init_one(i);
-+
-+	if (err) {
-+		__rtnl_link_unregister(&imq_link_ops);
-+		memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+	}
-+	rtnl_unlock();
-+
-+	return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+	int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+	err = imq_init_devs();
-+	if (err) {
-+		pr_err("IMQ: Error trying imq_init_devs(net)\n");
-+		return err;
-+	}
-+
-+	err = imq_init_hooks();
-+	if (err) {
-+		pr_err(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+		rtnl_link_unregister(&imq_link_ops);
-+		memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+		return err;
-+	}
-+
-+	pr_info("IMQ driver loaded successfully. (numdevs = %d, numqueues = %d, imq_dev_accurate_stats = %d)\n",
-+		numdevs, numqueues, imq_dev_accurate_stats);
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+	pr_info("\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+	pr_info("\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+	pr_info("\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+	pr_info("\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+	return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+	unregister_pernet_subsys(&imq_net_ops);
-+	nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+	rtnl_link_unregister(&imq_link_ops);
-+	memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+	imq_unhook();
-+	imq_cleanup_devs();
-+	pr_info("IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+module_param(numqueues, int, 0);
-+module_param(imq_dev_accurate_stats, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
-+MODULE_PARM_DESC(numqueues, "number of queues per IMQ device");
-+MODULE_PARM_DESC(imq_dev_accurate_stats, "Notify if need the accurate imq device stats");
-+
-+MODULE_AUTHOR("https://github.com/imq/linuximq");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-diff -Naupr linux-4.14_orig/drivers/net/Kconfig linux-4.14/drivers/net/Kconfig
---- linux-4.14_orig/drivers/net/Kconfig	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/drivers/net/Kconfig	2017-11-13 11:46:45.844089945 +0700
-@@ -277,6 +277,125 @@ config RIONET_RX_SIZE
- 	depends on RIONET
- 	default "128"
- 
-+config IMQ
-+	tristate "IMQ (intermediate queueing device) support"
-+	depends on NETDEVICES && NETFILTER
-+	---help---
-+	  The IMQ device(s) is used as placeholder for QoS queueing
-+	  disciplines. Every packet entering/leaving the IP stack can be
-+	  directed through the IMQ device where it's enqueued/dequeued to the
-+	  attached qdisc. This allows you to treat network devices as classes
-+	  and distribute bandwidth among them. Iptables is used to specify
-+	  through which IMQ device, if any, packets travel.
-+
-+	  More information at: https://github.com/imq/linuximq
-+
-+	  To compile this driver as a module, choose M here: the module
-+	  will be called imq.  If unsure, say N.
-+
-+choice
-+	prompt "IMQ behavior (PRE/POSTROUTING)"
-+	depends on IMQ
-+	default IMQ_BEHAVIOR_AB
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  IMQ can work in any of the following ways:
-+
-+	      PREROUTING   |      POSTROUTING
-+	  -----------------|-------------------
-+	  #1  After NAT    |      After NAT
-+	  #2  After NAT    |      Before NAT
-+	  #3  Before NAT   |      After NAT
-+	  #4  Before NAT   |      Before NAT
-+
-+	  The default behavior is to hook before NAT on PREROUTING
-+	  and after NAT on POSTROUTING (#3).
-+
-+	  This settings are specially usefull when trying to use IMQ
-+	  to shape NATed clients.
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+	bool "IMQ AA"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   After NAT
-+	  POSTROUTING:  After NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+	bool "IMQ AB"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   After NAT
-+	  POSTROUTING:  Before NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+	bool "IMQ BA"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   Before NAT
-+	  POSTROUTING:  After NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+	bool "IMQ BB"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   Before NAT
-+	  POSTROUTING:  Before NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+	int "Number of IMQ devices"
-+	range 2 16
-+	depends on IMQ
-+	default "16"
-+	help
-+	  This setting defines how many IMQ devices will be created.
-+
-+	  The default value is 16.
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
- config TUN
- 	tristate "Universal TUN/TAP device driver support"
- 	depends on INET
-diff -Naupr linux-4.14_orig/drivers/net/Makefile linux-4.14/drivers/net/Makefile
---- linux-4.14_orig/drivers/net/Makefile	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/drivers/net/Makefile	2017-11-13 11:46:45.844089945 +0700
-@@ -13,6 +13,7 @@ obj-$(CONFIG_DUMMY) += dummy.o
- obj-$(CONFIG_EQUALIZER) += eql.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACSEC) += macsec.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
- obj-$(CONFIG_MII) += mii.o
-diff -Naupr linux-4.14_orig/include/linux/imq.h linux-4.14/include/linux/imq.h
---- linux-4.14_orig/include/linux/imq.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.14/include/linux/imq.h	2017-11-13 11:46:45.844089945 +0700
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS	5
-+
-+#define IMQ_F_IFMASK	0x0f
-+#define IMQ_F_ENQUEUE	0x10
-+
-+#define IMQ_MAX_DEVS	(IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
-diff -Naupr linux-4.14_orig/include/linux/netdevice.h linux-4.14/include/linux/netdevice.h
---- linux-4.14_orig/include/linux/netdevice.h	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/include/linux/netdevice.h	2017-11-13 11:46:45.844089945 +0700
-@@ -1771,6 +1771,11 @@ struct net_device {
- /*
-  * Cache lines mostly used on receive path (including eth_type_trans())
-  */
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	unsigned long		last_rx;
-+#endif
-+
- 	/* Interface address info used in eth_type_trans() */
- 	unsigned char		*dev_addr;
- 
-@@ -3631,6 +3636,19 @@ static inline void netif_tx_unlock_bh(st
- 	}						\
- }
- 
-+#define HARD_TX_LOCK_BH(dev, txq) {           \
-+    if ((dev->features & NETIF_F_LLTX) == 0) {  \
-+        __netif_tx_lock_bh(txq);      \
-+    }                       \
-+}
-+
-+#define HARD_TX_UNLOCK_BH(dev, txq) {          \
-+    if ((dev->features & NETIF_F_LLTX) == 0) {  \
-+        __netif_tx_unlock_bh(txq);         \
-+    }                       \
-+}
-+
-+
- static inline void netif_tx_disable(struct net_device *dev)
- {
- 	unsigned int i;
-diff -Naupr linux-4.14_orig/include/linux/netfilter/xt_IMQ.h linux-4.14/include/linux/netfilter/xt_IMQ.h
---- linux-4.14_orig/include/linux/netfilter/xt_IMQ.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.14/include/linux/netfilter/xt_IMQ.h	2017-11-13 11:46:45.847423298 +0700
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+	unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
-diff -Naupr linux-4.14_orig/include/linux/netfilter_ipv4/ipt_IMQ.h linux-4.14/include/linux/netfilter_ipv4/ipt_IMQ.h
---- linux-4.14_orig/include/linux/netfilter_ipv4/ipt_IMQ.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.14/include/linux/netfilter_ipv4/ipt_IMQ.h	2017-11-13 11:46:45.847423298 +0700
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
-diff -Naupr linux-4.14_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-4.14/include/linux/netfilter_ipv6/ip6t_IMQ.h
---- linux-4.14_orig/include/linux/netfilter_ipv6/ip6t_IMQ.h	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.14/include/linux/netfilter_ipv6/ip6t_IMQ.h	2017-11-13 11:46:45.847423298 +0700
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
-diff -Naupr linux-4.14_orig/include/linux/skbuff.h linux-4.14/include/linux/skbuff.h
---- linux-4.14_orig/include/linux/skbuff.h	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/include/linux/skbuff.h	2017-11-13 11:46:45.847423298 +0700
-@@ -41,6 +41,10 @@
- #include <linux/in6.h>
- #include <linux/if_packet.h>
- #include <net/flow.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
-+
- 
- /* The interface for checksum offload between the stack and networking drivers
-  * is as follows...
-@@ -581,7 +585,7 @@ typedef unsigned int sk_buff_data_t;
- typedef unsigned char *sk_buff_data_t;
- #endif
- 
--/** 
-+/**
-  *	struct sk_buff - socket buffer
-  *	@next: Next buffer in list
-  *	@prev: Previous buffer in list
-@@ -684,6 +688,9 @@ struct sk_buff {
- 	 * first. This is owned by whoever has the skb queued ATM.
- 	 */
- 	char			cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	void			*cb_next;
-+#endif
- 
- 	unsigned long		_skb_refdst;
- 	void			(*destructor)(struct sk_buff *skb);
-@@ -693,6 +700,9 @@ struct sk_buff {
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
- 	unsigned long		 _nfct;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+       struct nf_queue_entry   *nf_queue_entry;
-+#endif
- #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- 	struct nf_bridge_info	*nf_bridge;
- #endif
-@@ -772,6 +782,9 @@ struct sk_buff {
- #ifdef CONFIG_NET_SWITCHDEV
- 	__u8			offload_fwd_mark:1;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	__u8			imq_flags:IMQ_F_BITS;
-+#endif
- #ifdef CONFIG_NET_CLS_ACT
- 	__u8			tc_skip_classify:1;
- 	__u8			tc_at_ingress:1;
-@@ -870,7 +883,7 @@ static inline bool skb_pfmemalloc(const
-  */
- static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
- {
--	/* If refdst was not refcounted, check we still are in a 
-+	/* If refdst was not refcounted, check we still are in a
- 	 * rcu_read_lock section
- 	 */
- 	WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) &&
-@@ -960,6 +973,12 @@ void skb_tx_error(struct sk_buff *skb);
- void consume_skb(struct sk_buff *skb);
- void __consume_stateless_skb(struct sk_buff *skb);
- void  __kfree_skb(struct sk_buff *skb);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+int skb_save_cb(struct sk_buff *skb);
-+int skb_restore_cb(struct sk_buff *skb);
-+#endif
-+
- extern struct kmem_cache *skbuff_head_cache;
- 
- void kfree_skb_partial(struct sk_buff *skb, bool head_stolen);
-@@ -3785,8 +3804,12 @@ static inline void __nf_copy(struct sk_b
- 	dst->_nfct = src->_nfct;
- 	nf_conntrack_get(skb_nfct(src));
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	dst->imq_flags = src->imq_flags;
-+  dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
--	dst->nf_bridge  = src->nf_bridge;
-+	dst->nf_bridge = src->nf_bridge;
- 	nf_bridge_get(src->nf_bridge);
- #endif
- #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
-diff -Naupr linux-4.14_orig/include/net/netfilter/nf_queue.h linux-4.14/include/net/netfilter/nf_queue.h
---- linux-4.14_orig/include/net/netfilter/nf_queue.h	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/include/net/netfilter/nf_queue.h	2017-11-13 11:46:45.847423298 +0700
-@@ -31,6 +31,12 @@ struct nf_queue_handler {
- void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
- void nf_unregister_queue_handler(struct net *net);
- void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
-+void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+void nf_unregister_queue_imq_handler(void);
-+#endif
- 
- void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
- void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
-diff -Naupr linux-4.14_orig/include/net/pkt_sched.h linux-4.14/include/net/pkt_sched.h
---- linux-4.14_orig/include/net/pkt_sched.h	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/include/net/pkt_sched.h	2017-11-13 11:46:45.850756651 +0700
-@@ -109,6 +109,8 @@ int sch_direct_xmit(struct sk_buff *skb,
- 
- void __qdisc_run(struct Qdisc *q);
- 
-+struct sk_buff *qdisc_dequeue_skb(struct Qdisc *q, bool *validate);
-+
- static inline void qdisc_run(struct Qdisc *q)
- {
- 	if (qdisc_run_begin(q))
-diff -Naupr linux-4.14_orig/include/net/sch_generic.h linux-4.14/include/net/sch_generic.h
---- linux-4.14_orig/include/net/sch_generic.h	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/include/net/sch_generic.h	2017-11-13 11:46:45.850756651 +0700
-@@ -567,6 +567,13 @@ static inline int qdisc_enqueue(struct s
- 	return sch->enqueue(skb, sch, to_free);
- }
- 
-+static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch,
-+				      struct sk_buff **to_free)
-+{
-+    qdisc_skb_cb(skb)->pkt_len = skb->len;
-+    return qdisc_enqueue(skb, sch, to_free) & NET_XMIT_MASK;
-+}
-+
- static inline bool qdisc_is_percpu_stats(const struct Qdisc *q)
- {
- 	return q->flags & TCQ_F_CPUSTATS;
-diff -Naupr linux-4.14_orig/include/uapi/linux/netfilter.h linux-4.14/include/uapi/linux/netfilter.h
---- linux-4.14_orig/include/uapi/linux/netfilter.h	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/include/uapi/linux/netfilter.h	2017-11-13 11:46:45.850756651 +0700
-@@ -14,7 +14,8 @@
- #define NF_QUEUE 3
- #define NF_REPEAT 4
- #define NF_STOP 5	/* Deprecated, for userspace nf_queue compatibility. */
--#define NF_MAX_VERDICT NF_STOP
-+#define NF_IMQ_QUEUE 6
-+#define NF_MAX_VERDICT NF_IMQ_QUEUE
- 
- /* we overload the higher bits for encoding auxiliary data such as the queue
-  * number or errno values. Not nice, but better than additional function
-diff -Naupr linux-4.14_orig/net/core/dev.c linux-4.14/net/core/dev.c
---- linux-4.14_orig/net/core/dev.c	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/core/dev.c	2017-11-13 11:46:45.854090004 +0700
-@@ -143,6 +143,9 @@
- #include <linux/hrtimer.h>
- #include <linux/netfilter_ingress.h>
- #include <linux/crash_dump.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/sctp.h>
- #include <net/udp_tunnel.h>
- 
-@@ -2971,7 +2974,12 @@ static int xmit_one(struct sk_buff *skb,
- 	unsigned int len;
- 	int rc;
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	if ((!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) &&
-+		!(skb->imq_flags & IMQ_F_ENQUEUE))
-+#else
- 	if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
-+#endif
- 		dev_queue_xmit_nit(skb, dev);
- 
- 	len = skb->len;
-@@ -3010,6 +3018,8 @@ out:
- 	return skb;
- }
- 
-+EXPORT_SYMBOL_GPL(dev_hard_start_xmit);
-+
- static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
- 					  netdev_features_t features)
- {
-diff -Naupr linux-4.14_orig/net/core/skbuff.c linux-4.14/net/core/skbuff.c
---- linux-4.14_orig/net/core/skbuff.c	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/core/skbuff.c	2017-11-13 11:46:45.854090004 +0700
-@@ -82,6 +82,87 @@ struct kmem_cache *skbuff_head_cache __r
- static struct kmem_cache *skbuff_fclone_cache __read_mostly;
- int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
- EXPORT_SYMBOL(sysctl_max_skb_frags);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+#endif
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+	char			cb[48] __aligned(8);
-+	void			*cb_next;
-+	atomic_t		refcnt;
-+};
-+
-+static DEFINE_SPINLOCK(skb_cb_store_lock);
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+	struct skb_cb_table *next;
-+
-+	next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+	if (!next)
-+		return -ENOMEM;
-+
-+	BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+	memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+	next->cb_next = skb->cb_next;
-+
-+	atomic_set(&next->refcnt, 1);
-+
-+	skb->cb_next = next;
-+	return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+	struct skb_cb_table *next;
-+
-+	if (!skb->cb_next)
-+		return 0;
-+
-+	next = skb->cb_next;
-+
-+	BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+	memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+	skb->cb_next = next->cb_next;
-+
-+	spin_lock(&skb_cb_store_lock);
-+
-+	if (atomic_dec_and_test(&next->refcnt))
-+		kmem_cache_free(skbuff_cb_store_cache, next);
-+
-+	spin_unlock(&skb_cb_store_lock);
-+
-+	return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+
-+static void skb_copy_stored_cb(struct sk_buff *   , const struct sk_buff *     ) __attribute__ ((unused));
-+static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
-+{
-+	struct skb_cb_table *next;
-+	struct sk_buff *old;
-+
-+	if (!__old->cb_next) {
-+		new->cb_next = NULL;
-+		return;
-+	}
-+
-+	spin_lock(&skb_cb_store_lock);
-+
-+	old = (struct sk_buff *)__old;
-+
-+	next = old->cb_next;
-+	atomic_inc(&next->refcnt);
-+	new->cb_next = next;
-+
-+	spin_unlock(&skb_cb_store_lock);
-+}
-+#endif
- 
- /**
-  *	skb_panic - private function for out-of-line support
-@@ -615,6 +696,28 @@ void skb_release_head_state(struct sk_bu
- 		WARN_ON(in_irq());
- 		skb->destructor(skb);
- 	}
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	/*
-+	 * This should not happen. When it does, avoid memleak by restoring
-+	 * the chain of cb-backups.
-+	 */
-+	while (skb->cb_next != NULL) {
-+		if (net_ratelimit())
-+			pr_warn("IMQ: kfree_skb: skb->cb_next: %08x\n",
-+				(unsigned int)(uintptr_t)skb->cb_next);
-+
-+		skb_restore_cb(skb);
-+	}
-+	/*
-+	 * This should not happen either, nf_queue_entry is nullified in
-+	 * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+	 * leaking entry pointers, maybe memory. We don't know if this is
-+	 * pointer to already freed memory, or should this be freed.
-+	 * If this happens we need to add refcounting, etc for nf_queue_entry.
-+	 */
-+	if (skb->nf_queue_entry && net_ratelimit())
-+		pr_warn("%s\n", "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if IS_ENABLED(CONFIG_NF_CONNTRACK)
- 	nf_conntrack_put(skb_nfct(skb));
- #endif
-@@ -804,6 +907,10 @@ static void __copy_skb_header(struct sk_
- 	new->sp			= secpath_get(old->sp);
- #endif
- 	__nf_copy(new, old, false);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	new->cb_next = NULL;
-+	/*skb_copy_stored_cb(new, old);*/
-+#endif
- 
- 	/* Note : this field could be in headers_start/headers_end section
- 	 * It is not yet because we do not want to have a 16 bit hole
-@@ -3902,6 +4009,13 @@ void __init skb_init(void)
- 						0,
- 						SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- 						NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+						  sizeof(struct skb_cb_table),
-+						  0,
-+						  SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+						  NULL);
-+#endif
- }
- 
- static int
-diff -Naupr linux-4.14_orig/net/netfilter/core.c linux-4.14/net/netfilter/core.c
---- linux-4.14_orig/net/netfilter/core.c	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/netfilter/core.c	2017-11-13 14:16:05.896850774 +0700
-@@ -474,6 +474,11 @@ int nf_hook_slow(struct sk_buff *skb, st
- 			if (ret == 0)
- 				ret = -EPERM;
- 			return ret;
-+		case NF_IMQ_QUEUE:
-+			ret = nf_queue(skb, state, e, s, verdict);
-+			if (ret == -ECANCELED)
-+				continue;
-+			return ret;
- 		case NF_QUEUE:
- 			ret = nf_queue(skb, state, e, s, verdict);
- 			if (ret == 1)
-diff -Naupr linux-4.14_orig/net/netfilter/Kconfig linux-4.14/net/netfilter/Kconfig
---- linux-4.14_orig/net/netfilter/Kconfig	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/netfilter/Kconfig	2017-11-13 11:46:45.857423358 +0700
-@@ -867,6 +867,18 @@ config NETFILTER_XT_TARGET_LOG
- 
- 	  To compile it as a module, choose M here.  If unsure, say N.
- 
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+	depends on NETFILTER_XTABLES
-+	depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+	select IMQ
-+	default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
- 	tristate '"MARK" target support'
- 	depends on NETFILTER_ADVANCED
-diff -Naupr linux-4.14_orig/net/netfilter/Makefile linux-4.14/net/netfilter/Makefile
---- linux-4.14_orig/net/netfilter/Makefile	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/netfilter/Makefile	2017-11-13 11:46:45.857423358 +0700
-@@ -125,6 +125,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) +=
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
-diff -Naupr linux-4.14_orig/net/netfilter/nf_queue.c linux-4.14/net/netfilter/nf_queue.c
---- linux-4.14_orig/net/netfilter/nf_queue.c	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/netfilter/nf_queue.c	2017-11-13 14:25:21.436864671 +0700
-@@ -1,4 +1,4 @@
--/*
-+	/*
-  * Rusty Russell (C)2000 -- This code is GPL.
-  * Patrick McHardy (c) 2006-2012
-  */
-@@ -27,6 +27,23 @@
-  * receives, no matter what.
-  */
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler __rcu *queue_imq_handler __read_mostly;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+	rcu_assign_pointer(queue_imq_handler, qh);
-+}
-+EXPORT_SYMBOL_GPL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+	RCU_INIT_POINTER(queue_imq_handler, NULL);
-+	synchronize_rcu();
-+}
-+EXPORT_SYMBOL_GPL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh)
-@@ -113,16 +130,29 @@ EXPORT_SYMBOL_GPL(nf_queue_nf_hook_drop)
- 
- static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
- 		      const struct nf_hook_entries *entries,
--		      unsigned int index, unsigned int queuenum)
-+		      unsigned int index, unsigned int verdict)
- {
- 	int status = -ENOENT;
- 	struct nf_queue_entry *entry = NULL;
- 	const struct nf_afinfo *afinfo;
- 	const struct nf_queue_handler *qh;
- 	struct net *net = state->net;
-+	unsigned int queuetype = verdict & NF_VERDICT_MASK;
-+	unsigned int queuenum  = verdict >> NF_VERDICT_QBITS;
- 
- 	/* QUEUE == DROP if no one is waiting, to be safe. */
--	qh = rcu_dereference(net->nf.queue_handler);
-+
-+	if (queuetype == NF_IMQ_QUEUE) {
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	qh = rcu_dereference(queue_imq_handler);
-+#else
-+	BUG();
-+	goto err_unlock;
-+#endif
-+	} else {
-+		qh = rcu_dereference(net->nf.queue_handler);
-+	}
-+
- 	if (!qh) {
- 		status = -ESRCH;
- 		goto err;
-@@ -169,8 +199,16 @@ int nf_queue(struct sk_buff *skb, struct
- {
- 	int ret;
- 
--	ret = __nf_queue(skb, state, entries, index, verdict >> NF_VERDICT_QBITS);
-+	ret = __nf_queue(skb, state, entries, index, verdict);
- 	if (ret < 0) {
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	/* IMQ Bypass */
-+	if (ret == -ECANCELED && skb->imq_flags == 0) {
-+		return 1;
-+	}
-+#endif
-+
- 		if (ret == -ESRCH &&
- 		    (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
- 			return 1;
-@@ -256,6 +294,7 @@ next_hook:
- 		local_bh_enable();
- 		break;
- 	case NF_QUEUE:
-+	case NF_IMQ_QUEUE:
- 		err = nf_queue(skb, &entry->state, hooks, i, verdict);
- 		if (err == 1)
- 			goto next_hook;
-diff -Naupr linux-4.14_orig/net/netfilter/xt_IMQ.c linux-4.14/net/netfilter/xt_IMQ.c
---- linux-4.14_orig/net/netfilter/xt_IMQ.c	1970-01-01 07:00:00.000000000 +0700
-+++ linux-4.14/net/netfilter/xt_IMQ.c	2017-11-13 11:46:45.857423358 +0700
-@@ -0,0 +1,72 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+				const struct xt_action_param *par)
-+{
-+	const struct xt_imq_info *mr = par->targinfo;
-+
-+	pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+	return XT_CONTINUE;
-+}
-+
-+static int imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+	struct xt_imq_info *mr = par->targinfo;
-+
-+	if (mr->todev > IMQ_MAX_DEVS - 1) {
-+		pr_warn("IMQ: invalid device specified, highest is %u\n",
-+			IMQ_MAX_DEVS - 1);
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+	{
-+		.name           = "IMQ",
-+		.family		= AF_INET,
-+		.checkentry     = imq_checkentry,
-+		.target         = imq_target,
-+		.targetsize	= sizeof(struct xt_imq_info),
-+		.table		= "mangle",
-+		.me             = THIS_MODULE
-+	},
-+	{
-+		.name           = "IMQ",
-+		.family		= AF_INET6,
-+		.checkentry     = imq_checkentry,
-+		.target         = imq_target,
-+		.targetsize	= sizeof(struct xt_imq_info),
-+		.table		= "mangle",
-+		.me             = THIS_MODULE
-+	},
-+};
-+
-+static int __init imq_init(void)
-+{
-+	return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+	xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("https://github.com/imq/linuximq");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
-diff -Naupr linux-4.14_orig/net/sched/sch_generic.c linux-4.14/net/sched/sch_generic.c
---- linux-4.14_orig/net/sched/sch_generic.c	2017-11-13 01:46:13.000000000 +0700
-+++ linux-4.14/net/sched/sch_generic.c	2017-11-13 11:46:45.857423358 +0700
-@@ -158,6 +158,14 @@ trace:
- 	return skb;
- }
- 
-+struct sk_buff *qdisc_dequeue_skb(struct Qdisc *q, bool *validate)
-+{
-+	int packets;
-+
-+	return dequeue_skb(q, validate, &packets);
-+}
-+EXPORT_SYMBOL(qdisc_dequeue_skb);
-+
- /*
-  * Transmit possibly several skbs, and handle the return status as
-  * required. Owning running seqcount bit guarantees that
Index: npl/kernel/linux_src/linux-4.4.5-imq.diff
===================================================================
--- npl/kernel/linux_src/linux-4.4.5-imq.diff	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
+++ npl/kernel/linux_src/linux-4.4.5-imq.diff	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -0,0 +1,1720 @@
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index f184fb5..0e08522 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -234,6 +234,125 @@ config RIONET_RX_SIZE
+ 	depends on RIONET
+ 	default "128"
+ 
++config IMQ
++	tristate "IMQ (intermediate queueing device) support"
++	depends on NETDEVICES && NETFILTER
++	---help---
++	  The IMQ device(s) is used as placeholder for QoS queueing
++	  disciplines. Every packet entering/leaving the IP stack can be
++	  directed through the IMQ device where it's enqueued/dequeued to the
++	  attached qdisc. This allows you to treat network devices as classes
++	  and distribute bandwidth among them. Iptables is used to specify
++	  through which IMQ device, if any, packets travel.
++
++	  More information at: https://github.com/imq/linuximq
++
++	  To compile this driver as a module, choose M here: the module
++	  will be called imq.  If unsure, say N.
++
++choice
++	prompt "IMQ behavior (PRE/POSTROUTING)"
++	depends on IMQ
++	default IMQ_BEHAVIOR_AB
++	help
++	  This setting defines how IMQ behaves in respect to its
++	  hooking in PREROUTING and POSTROUTING.
++
++	  IMQ can work in any of the following ways:
++
++	      PREROUTING   |      POSTROUTING
++	  -----------------|-------------------
++	  #1  After NAT    |      After NAT
++	  #2  After NAT    |      Before NAT
++	  #3  Before NAT   |      After NAT
++	  #4  Before NAT   |      Before NAT
++
++	  The default behavior is to hook before NAT on PREROUTING
++	  and after NAT on POSTROUTING (#3).
++
++	  This settings are specially usefull when trying to use IMQ
++	  to shape NATed clients.
++
++	  More information can be found at: https://github.com/imq/linuximq
++
++	  If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_AA
++	bool "IMQ AA"
++	help
++	  This setting defines how IMQ behaves in respect to its
++	  hooking in PREROUTING and POSTROUTING.
++
++	  Choosing this option will make IMQ hook like this:
++
++	  PREROUTING:   After NAT
++	  POSTROUTING:  After NAT
++
++	  More information can be found at: https://github.com/imq/linuximq
++
++	  If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_AB
++	bool "IMQ AB"
++	help
++	  This setting defines how IMQ behaves in respect to its
++	  hooking in PREROUTING and POSTROUTING.
++
++	  Choosing this option will make IMQ hook like this:
++
++	  PREROUTING:   After NAT
++	  POSTROUTING:  Before NAT
++
++	  More information can be found at: https://github.com/imq/linuximq
++
++	  If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_BA
++	bool "IMQ BA"
++	help
++	  This setting defines how IMQ behaves in respect to its
++	  hooking in PREROUTING and POSTROUTING.
++
++	  Choosing this option will make IMQ hook like this:
++
++	  PREROUTING:   Before NAT
++	  POSTROUTING:  After NAT
++
++	  More information can be found at: https://github.com/imq/linuximq
++
++	  If not sure leave the default settings alone.
++
++config IMQ_BEHAVIOR_BB
++	bool "IMQ BB"
++	help
++	  This setting defines how IMQ behaves in respect to its
++	  hooking in PREROUTING and POSTROUTING.
++
++	  Choosing this option will make IMQ hook like this:
++
++	  PREROUTING:   Before NAT
++	  POSTROUTING:  Before NAT
++
++	  More information can be found at: https://github.com/imq/linuximq
++
++	  If not sure leave the default settings alone.
++
++endchoice
++
++config IMQ_NUM_DEVS
++	int "Number of IMQ devices"
++	range 2 16
++	depends on IMQ
++	default "16"
++	help
++	  This setting defines how many IMQ devices will be created.
++
++	  The default value is 16.
++
++	  More information can be found at: https://github.com/imq/linuximq
++
++	  If not sure leave the default settings alone.
++
+ config TUN
+ 	tristate "Universal TUN/TAP device driver support"
+ 	depends on INET
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index 900b0c5..e093402 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_IPVLAN) += ipvlan/
+ obj-$(CONFIG_DUMMY) += dummy.o
+ obj-$(CONFIG_EQUALIZER) += eql.o
+ obj-$(CONFIG_IFB) += ifb.o
++obj-$(CONFIG_IMQ) += imq.o
+ obj-$(CONFIG_MACVLAN) += macvlan.o
+ obj-$(CONFIG_MACVTAP) += macvtap.o
+ obj-$(CONFIG_MII) += mii.o
+diff --git a/drivers/net/imq.c b/drivers/net/imq.c
+new file mode 100644
+index 0000000..f80258f
+--- /dev/null
++++ b/drivers/net/imq.c
+@@ -0,0 +1,903 @@
++/*
++ *             Pseudo-driver for the intermediate queue device.
++ *
++ *             This program is free software; you can redistribute it and/or
++ *             modify it under the terms of the GNU General Public License
++ *             as published by the Free Software Foundation; either version
++ *             2 of the License, or (at your option) any later version.
++ *
++ * Authors:    Patrick McHardy, <kaber@trash.net>
++ *
++ *            The first version was written by Martin Devera, <devik@cdi.cz>
++ *
++ *			   See Creditis.txt
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/moduleparam.h>
++#include <linux/list.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <linux/if_arp.h>
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4.h>
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++	#include <linux/netfilter_ipv6.h>
++#endif
++#include <linux/imq.h>
++#include <net/pkt_sched.h>
++#include <net/netfilter/nf_queue.h>
++#include <net/sock.h>
++#include <linux/ip.h>
++#include <linux/ipv6.h>
++#include <linux/if_vlan.h>
++#include <linux/if_pppox.h>
++#include <net/ip.h>
++#include <net/ipv6.h>
++
++static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num);
++
++static nf_hookfn imq_nf_hook;
++
++static struct nf_hook_ops imq_ops[] = {
++	{
++	/* imq_ingress_ipv4 */
++		.hook		= imq_nf_hook,
++		.pf		= PF_INET,
++		.hooknum	= NF_INET_PRE_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++		.priority	= NF_IP_PRI_MANGLE + 1,
++#else
++		.priority	= NF_IP_PRI_NAT_DST + 1,
++#endif
++	},
++	{
++	/* imq_egress_ipv4 */
++		.hook		= imq_nf_hook,
++		.pf		= PF_INET,
++		.hooknum	= NF_INET_POST_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
++		.priority	= NF_IP_PRI_LAST,
++#else
++		.priority	= NF_IP_PRI_NAT_SRC - 1,
++#endif
++	},
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++	{
++	/* imq_ingress_ipv6 */
++		.hook		= imq_nf_hook,
++		.pf		= PF_INET6,
++		.hooknum	= NF_INET_PRE_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++		.priority	= NF_IP6_PRI_MANGLE + 1,
++#else
++		.priority	= NF_IP6_PRI_NAT_DST + 1,
++#endif
++	},
++	{
++	/* imq_egress_ipv6 */
++		.hook		= imq_nf_hook,
++		.pf		= PF_INET6,
++		.hooknum	= NF_INET_POST_ROUTING,
++#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
++		.priority	= NF_IP6_PRI_LAST,
++#else
++		.priority	= NF_IP6_PRI_NAT_SRC - 1,
++#endif
++	},
++#endif
++};
++
++#if defined(CONFIG_IMQ_NUM_DEVS)
++static int numdevs = CONFIG_IMQ_NUM_DEVS;
++#else
++static int numdevs = IMQ_MAX_DEVS;
++#endif
++
++static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
++
++#define IMQ_MAX_QUEUES 32
++static int numqueues = 1;
++static u32 imq_hashrnd;
++static int imq_dev_accurate_stats = 1;
++
++static inline __be16 pppoe_proto(const struct sk_buff *skb)
++{
++	return *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
++			sizeof(struct pppoe_hdr)));
++}
++
++static u16 imq_hash(struct net_device *dev, struct sk_buff *skb)
++{
++	unsigned int pull_len;
++	u16 protocol = skb->protocol;
++	u32 addr1, addr2;
++	u32 hash, ihl = 0;
++	union {
++		u16 in16[2];
++		u32 in32;
++	} ports;
++	u8 ip_proto;
++
++	pull_len = 0;
++
++recheck:
++	switch (protocol) {
++	case htons(ETH_P_8021Q): {
++		if (unlikely(skb_pull(skb, VLAN_HLEN) == NULL))
++			goto other;
++
++		pull_len += VLAN_HLEN;
++		skb->network_header += VLAN_HLEN;
++
++		protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
++		goto recheck;
++	}
++
++	case htons(ETH_P_PPP_SES): {
++		if (unlikely(skb_pull(skb, PPPOE_SES_HLEN) == NULL))
++			goto other;
++
++		pull_len += PPPOE_SES_HLEN;
++		skb->network_header += PPPOE_SES_HLEN;
++
++		protocol = pppoe_proto(skb);
++		goto recheck;
++	}
++
++	case htons(ETH_P_IP): {
++		const struct iphdr *iph = ip_hdr(skb);
++
++		if (unlikely(!pskb_may_pull(skb, sizeof(struct iphdr))))
++			goto other;
++
++		addr1 = iph->daddr;
++		addr2 = iph->saddr;
++
++		ip_proto = !(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) ?
++				 iph->protocol : 0;
++		ihl = ip_hdrlen(skb);
++
++		break;
++	}
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++	case htons(ETH_P_IPV6): {
++		const struct ipv6hdr *iph = ipv6_hdr(skb);
++		__be16 fo = 0;
++
++		if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr))))
++			goto other;
++
++		addr1 = iph->daddr.s6_addr32[3];
++		addr2 = iph->saddr.s6_addr32[3];
++		ihl = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &ip_proto,
++				       &fo);
++		if (unlikely(ihl < 0))
++			goto other;
++
++		break;
++	}
++#endif
++	default:
++other:
++		if (pull_len != 0) {
++			skb_push(skb, pull_len);
++			skb->network_header -= pull_len;
++		}
++
++		return (u16)(ntohs(protocol) % dev->real_num_tx_queues);
++	}
++
++	if (addr1 > addr2)
++		swap(addr1, addr2);
++
++	switch (ip_proto) {
++	case IPPROTO_TCP:
++	case IPPROTO_UDP:
++	case IPPROTO_DCCP:
++	case IPPROTO_ESP:
++	case IPPROTO_AH:
++	case IPPROTO_SCTP:
++	case IPPROTO_UDPLITE: {
++		if (likely(skb_copy_bits(skb, ihl, &ports.in32, 4) >= 0)) {
++			if (ports.in16[0] > ports.in16[1])
++				swap(ports.in16[0], ports.in16[1]);
++			break;
++		}
++		/* fall-through */
++	}
++	default:
++		ports.in32 = 0;
++		break;
++	}
++
++	if (pull_len != 0) {
++		skb_push(skb, pull_len);
++		skb->network_header -= pull_len;
++	}
++
++	hash = jhash_3words(addr1, addr2, ports.in32, imq_hashrnd ^ ip_proto);
++
++	return (u16)(((u64)hash * dev->real_num_tx_queues) >> 32);
++}
++
++static inline bool sk_tx_queue_recorded(struct sock *sk)
++{
++	return (sk_tx_queue_get(sk) >= 0);
++}
++
++static struct netdev_queue *imq_select_queue(struct net_device *dev,
++						struct sk_buff *skb)
++{
++	u16 queue_index = 0;
++	u32 hash;
++
++	if (likely(dev->real_num_tx_queues == 1))
++		goto out;
++
++	/* IMQ can be receiving ingress or engress packets. */
++
++	/* Check first for if rx_queue is set */
++	if (skb_rx_queue_recorded(skb)) {
++		queue_index = skb_get_rx_queue(skb);
++		goto out;
++	}
++
++	/* Check if socket has tx_queue set */
++	if (sk_tx_queue_recorded(skb->sk)) {
++		queue_index = sk_tx_queue_get(skb->sk);
++		goto out;
++	}
++
++	/* Try use socket hash */
++	if (skb->sk && skb->sk->sk_hash) {
++		hash = skb->sk->sk_hash;
++		queue_index =
++			(u16)(((u64)hash * dev->real_num_tx_queues) >> 32);
++		goto out;
++	}
++
++	/* Generate hash from packet data */
++	queue_index = imq_hash(dev, skb);
++
++out:
++	if (unlikely(queue_index >= dev->real_num_tx_queues))
++		queue_index = (u16)((u32)queue_index % dev->real_num_tx_queues);
++
++	skb_set_queue_mapping(skb, queue_index);
++	return netdev_get_tx_queue(dev, queue_index);
++}
++
++static struct net_device_stats *imq_get_stats(struct net_device *dev)
++{
++	return &dev->stats;
++}
++
++/* called for packets kfree'd in qdiscs at places other than enqueue */
++static void imq_skb_destructor(struct sk_buff *skb)
++{
++	struct nf_queue_entry *entry = skb->nf_queue_entry;
++
++	skb->nf_queue_entry = NULL;
++
++	if (entry) {
++		nf_queue_entry_release_refs(entry);
++		kfree(entry);
++	}
++
++	skb_restore_cb(skb); /* kfree backup */
++}
++
++static void imq_done_check_queue_mapping(struct sk_buff *skb,
++					 struct net_device *dev)
++{
++	unsigned int queue_index;
++
++	/* Don't let queue_mapping be left too large after exiting IMQ */
++	if (likely(skb->dev != dev && skb->dev != NULL)) {
++		queue_index = skb_get_queue_mapping(skb);
++		if (unlikely(queue_index >= skb->dev->real_num_tx_queues)) {
++			queue_index = (u16)((u32)queue_index %
++						skb->dev->real_num_tx_queues);
++			skb_set_queue_mapping(skb, queue_index);
++		}
++	} else {
++		/* skb->dev was IMQ device itself or NULL, be on safe side and
++		 * just clear queue mapping.
++		 */
++		skb_set_queue_mapping(skb, 0);
++	}
++}
++
++static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	struct nf_queue_entry *entry = skb->nf_queue_entry;
++
++	skb->nf_queue_entry = NULL;
++	dev->trans_start = jiffies;
++
++	dev->stats.tx_bytes += skb->len;
++	dev->stats.tx_packets++;
++
++	if (unlikely(entry == NULL)) {
++		/* We don't know what is going on here.. packet is queued for
++		 * imq device, but (probably) not by us.
++		 *
++		 * If this packet was not send here by imq_nf_queue(), then
++		 * skb_save_cb() was not used and skb_free() should not show:
++		 *   WARNING: IMQ: kfree_skb: skb->cb_next:..
++		 * and/or
++		 *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
++		 *
++		 * However if this message is shown, then IMQ is somehow broken
++		 * and you should report this to linuximq.net.
++		 */
++
++		/* imq_dev_xmit is black hole that eats all packets, report that
++		 * we eat this packet happily and increase dropped counters.
++		 */
++
++		dev->stats.tx_dropped++;
++		dev_kfree_skb(skb);
++
++		return NETDEV_TX_OK;
++	}
++
++	skb_restore_cb(skb); /* restore skb->cb */
++
++	skb->imq_flags = 0;
++	skb->destructor = NULL;
++
++	imq_done_check_queue_mapping(skb, dev);
++
++	nf_reinject(entry, NF_ACCEPT);
++
++	return NETDEV_TX_OK;
++}
++
++static struct net_device *get_imq_device_by_index(int index)
++{
++	struct net_device *dev = NULL;
++	struct net *net;
++	char buf[8];
++
++	/* get device by name and cache result */
++	snprintf(buf, sizeof(buf), "imq%d", index);
++
++	/* Search device from all namespaces. */
++	for_each_net(net) {
++		dev = dev_get_by_name(net, buf);
++		if (dev)
++			break;
++	}
++
++	if (WARN_ON_ONCE(dev == NULL)) {
++		/* IMQ device not found. Exotic config? */
++		return ERR_PTR(-ENODEV);
++	}
++
++	imq_devs_cache[index] = dev;
++	dev_put(dev);
++
++	return dev;
++}
++
++static struct nf_queue_entry *nf_queue_entry_dup(struct nf_queue_entry *e)
++{
++	struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC);
++	if (entry) {
++		nf_queue_entry_get_refs(entry);
++			return entry;
++	}
++	return NULL;
++}
++
++#ifdef CONFIG_BRIDGE_NETFILTER
++/* When called from bridge netfilter, skb->data must point to MAC header
++ * before calling skb_gso_segment(). Else, original MAC header is lost
++ * and segmented skbs will be sent to wrong destination.
++ */
++static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
++{
++	if (skb->nf_bridge)
++		__skb_push(skb, skb->network_header - skb->mac_header);
++}
++
++static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
++{
++	if (skb->nf_bridge)
++		__skb_pull(skb, skb->network_header - skb->mac_header);
++}
++#else
++#define nf_bridge_adjust_skb_data(s) do {} while (0)
++#define nf_bridge_adjust_segmented_data(s) do {} while (0)
++#endif
++
++static void free_entry(struct nf_queue_entry *entry)
++{
++	nf_queue_entry_release_refs(entry);
++	kfree(entry);
++}
++
++static int __imq_nf_queue(struct nf_queue_entry *entry, struct net_device *dev);
++
++static int __imq_nf_queue_gso(struct nf_queue_entry *entry,
++			      struct net_device *dev, struct sk_buff *skb)
++{
++	int ret = -ENOMEM;
++	struct nf_queue_entry *entry_seg;
++
++	nf_bridge_adjust_segmented_data(skb);
++
++	if (skb->next == NULL) { /* last packet, no need to copy entry */
++		struct sk_buff *gso_skb = entry->skb;
++		entry->skb = skb;
++		ret = __imq_nf_queue(entry, dev);
++		if (ret)
++			entry->skb = gso_skb;
++		return ret;
++	}
++
++	skb->next = NULL;
++
++	entry_seg = nf_queue_entry_dup(entry);
++	if (entry_seg) {
++		entry_seg->skb = skb;
++		ret = __imq_nf_queue(entry_seg, dev);
++		if (ret)
++			free_entry(entry_seg);
++	}
++	return ret;
++}
++
++static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
++{
++	struct sk_buff *skb, *segs;
++	struct net_device *dev;
++	unsigned int queued;
++	int index, retval, err;
++
++	index = entry->skb->imq_flags & IMQ_F_IFMASK;
++	if (unlikely(index > numdevs - 1)) {
++		if (net_ratelimit())
++			pr_warn("IMQ: invalid device specified, highest is %u\n",
++				numdevs - 1);
++		retval = -EINVAL;
++		goto out_no_dev;
++	}
++
++	/* check for imq device by index from cache */
++	dev = imq_devs_cache[index];
++	if (unlikely(!dev)) {
++		dev = get_imq_device_by_index(index);
++		if (IS_ERR(dev)) {
++			retval = PTR_ERR(dev);
++			goto out_no_dev;
++		}
++	}
++
++	if (unlikely(!(dev->flags & IFF_UP))) {
++		entry->skb->imq_flags = 0;
++		retval = -ECANCELED;
++		goto out_no_dev;
++	}
++
++	/* Since 3.10.x, GSO handling moved here as result of upstream commit
++	 * a5fedd43d5f6c94c71053a66e4c3d2e35f1731a2 (netfilter: move
++	 * skb_gso_segment into nfnetlink_queue module).
++	 *
++	 * Following code replicates the gso handling from
++	 * 'net/netfilter/nfnetlink_queue_core.c':nfqnl_enqueue_packet().
++	 */
++
++	skb = entry->skb;
++
++	switch (entry->state.pf) {
++	case NFPROTO_IPV4:
++		skb->protocol = htons(ETH_P_IP);
++		break;
++	case NFPROTO_IPV6:
++		skb->protocol = htons(ETH_P_IPV6);
++		break;
++	}
++
++	if (!skb_is_gso(entry->skb))
++		return __imq_nf_queue(entry, dev);
++
++	nf_bridge_adjust_skb_data(skb);
++	segs = skb_gso_segment(skb, 0);
++	/* Does not use PTR_ERR to limit the number of error codes that can be
++	 * returned by nf_queue.  For instance, callers rely on -ECANCELED to
++	 * mean 'ignore this hook'.
++	 */
++	err = -ENOBUFS;
++	if (IS_ERR(segs))
++		goto out_err;
++	queued = 0;
++	err = 0;
++	do {
++		struct sk_buff *nskb = segs->next;
++		if (nskb && nskb->next)
++			nskb->cb_next = NULL;
++		if (err == 0)
++			err = __imq_nf_queue_gso(entry, dev, segs);
++		if (err == 0)
++			queued++;
++		else
++			kfree_skb(segs);
++		segs = nskb;
++	} while (segs);
++
++	if (queued) {
++		if (err) /* some segments are already queued */
++			free_entry(entry);
++		kfree_skb(skb);
++		return 0;
++	}
++
++out_err:
++	nf_bridge_adjust_segmented_data(skb);
++	retval = err;
++out_no_dev:
++	return retval;
++}
++
++static int __imq_nf_queue(struct nf_queue_entry *entry, struct net_device *dev)
++{
++	struct sk_buff *skb_orig, *skb, *skb_shared, *skb_popd;
++	struct Qdisc *q;
++	struct netdev_queue *txq;
++	spinlock_t *root_lock;
++	int users;
++	int retval = -EINVAL;
++	unsigned int orig_queue_index;
++
++	dev->last_rx = jiffies;
++
++	skb = entry->skb;
++	skb_orig = NULL;
++
++	/* skb has owner? => make clone */
++	if (unlikely(skb->destructor)) {
++		skb_orig = skb;
++		skb = skb_clone(skb, GFP_ATOMIC);
++		if (unlikely(!skb)) {
++			retval = -ENOMEM;
++			goto out;
++		}
++		skb->cb_next = NULL;
++		entry->skb = skb;
++	}
++
++	dev->stats.rx_bytes += skb->len;
++	dev->stats.rx_packets++;
++
++	if (!skb->dev) {
++		/* skb->dev == NULL causes problems, try the find cause. */
++		if (net_ratelimit()) {
++			dev_warn(&dev->dev,
++				 "received packet with skb->dev == NULL\n");
++			dump_stack();
++		}
++
++		skb->dev = dev;
++	}
++
++	/* Disables softirqs for lock below */
++	rcu_read_lock_bh();
++
++	/* Multi-queue selection */
++	orig_queue_index = skb_get_queue_mapping(skb);
++	txq = imq_select_queue(dev, skb);
++
++	q = rcu_dereference(txq->qdisc);
++	if (unlikely(!q->enqueue))
++		goto packet_not_eaten_by_imq_dev;
++
++	skb->nf_queue_entry = entry;
++	root_lock = qdisc_lock(q);
++	spin_lock(root_lock);
++
++	users = atomic_read(&skb->users);
++
++	skb_shared = skb_get(skb); /* increase reference count by one */
++
++	/* backup skb->cb, as qdisc layer will overwrite it */
++	skb_save_cb(skb_shared);
++	qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
++	if (likely(atomic_read(&skb_shared->users) == users + 1)) {
++		bool validate;
++
++		kfree_skb(skb_shared); /* decrease reference count by one */
++
++		skb->destructor = &imq_skb_destructor;
++
++		skb_popd = qdisc_dequeue_skb(q, &validate);
++
++		/* cloned? */
++		if (unlikely(skb_orig))
++			kfree_skb(skb_orig); /* free original */
++
++		spin_unlock(root_lock);
++
++#if 0
++		/* schedule qdisc dequeue */
++		__netif_schedule(q);
++#else
++		if (likely(skb_popd)) {
++			/* Note that we validate skb (GSO, checksum, ...) outside of locks */
++			if (validate)
++        		skb_popd = validate_xmit_skb_list(skb_popd, dev);
++			
++			if (skb_popd) {
++				int dummy_ret;
++				int cpu = smp_processor_id(); /* ok because BHs are off */
++
++				txq = skb_get_tx_queue(dev, skb_popd);
++				/* 
++				IMQ device will not be frozen or stoped, and it always be successful.
++				So we need not check its status and return value to accelerate.
++				*/
++				if (imq_dev_accurate_stats && txq->xmit_lock_owner != cpu) {
++					HARD_TX_LOCK(dev, txq, cpu);
++					if (!netif_xmit_frozen_or_stopped(txq)) {
++						dev_hard_start_xmit(skb_popd, dev, txq, &dummy_ret);
++					}
++					HARD_TX_UNLOCK(dev, txq);
++				} else {
++					if (!netif_xmit_frozen_or_stopped(txq)) {
++						dev_hard_start_xmit(skb_popd, dev, txq, &dummy_ret);
++					}
++				}
++			}
++		} else {
++			/* No ready skb, then schedule it */
++			__netif_schedule(q);
++		}
++#endif
++		rcu_read_unlock_bh();
++		retval = 0;
++		goto out;
++	} else {
++		skb_restore_cb(skb_shared); /* restore skb->cb */
++		skb->nf_queue_entry = NULL;
++		/*
++		 * qdisc dropped packet and decreased skb reference count of
++		 * skb, so we don't really want to and try refree as that would
++		 * actually destroy the skb.
++		 */
++		spin_unlock(root_lock);
++		goto packet_not_eaten_by_imq_dev;
++	}
++
++packet_not_eaten_by_imq_dev:
++	skb_set_queue_mapping(skb, orig_queue_index);
++	rcu_read_unlock_bh();
++
++	/* cloned? restore original */
++	if (unlikely(skb_orig)) {
++		kfree_skb(skb);
++		entry->skb = skb_orig;
++	}
++	retval = -1;
++out:
++	return retval;
++}
++static unsigned int imq_nf_hook(void *priv,
++				struct sk_buff *skb,
++				const struct nf_hook_state *state)
++{
++	return (skb->imq_flags & IMQ_F_ENQUEUE) ? NF_IMQ_QUEUE : NF_ACCEPT;
++}
++
++static int imq_close(struct net_device *dev)
++{
++	netif_stop_queue(dev);
++	return 0;
++}
++
++static int imq_open(struct net_device *dev)
++{
++	netif_start_queue(dev);
++	return 0;
++}
++
++static const struct net_device_ops imq_netdev_ops = {
++	.ndo_open		= imq_open,
++	.ndo_stop		= imq_close,
++	.ndo_start_xmit		= imq_dev_xmit,
++	.ndo_get_stats		= imq_get_stats,
++};
++
++static void imq_setup(struct net_device *dev)
++{
++	dev->netdev_ops		= &imq_netdev_ops;
++	dev->type		= ARPHRD_VOID;
++	dev->mtu		= 16000; /* too small? */
++	dev->tx_queue_len	= 11000; /* too big? */
++	dev->flags		= IFF_NOARP;
++	dev->features		= NETIF_F_SG | NETIF_F_FRAGLIST |
++				  NETIF_F_GSO | NETIF_F_HW_CSUM |
++				  NETIF_F_HIGHDMA;
++	dev->priv_flags		&= ~(IFF_XMIT_DST_RELEASE |
++				     IFF_TX_SKB_SHARING);
++}
++
++static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
++{
++	int ret = 0;
++
++	if (tb[IFLA_ADDRESS]) {
++		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
++			ret = -EINVAL;
++			goto end;
++		}
++		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
++			ret = -EADDRNOTAVAIL;
++			goto end;
++		}
++	}
++	return 0;
++end:
++	pr_warn("IMQ: imq_validate failed (%d)\n", ret);
++	return ret;
++}
++
++static struct rtnl_link_ops imq_link_ops __read_mostly = {
++	.kind		= "imq",
++	.priv_size	= 0,
++	.setup		= imq_setup,
++	.validate	= imq_validate,
++};
++
++static const struct nf_queue_handler imq_nfqh = {
++	.outfn = imq_nf_queue,
++};
++
++static int __init imq_init_hooks(void)
++{
++	int ret;
++
++	nf_register_queue_imq_handler(&imq_nfqh);
++
++	ret = nf_register_hooks(imq_ops, ARRAY_SIZE(imq_ops));
++	if (ret < 0)
++		nf_unregister_queue_imq_handler();
++
++	return ret;
++}
++
++static int __init imq_init_one(int index)
++{
++	struct net_device *dev;
++	int ret;
++
++	dev = alloc_netdev_mq(0, "imq%d", NET_NAME_UNKNOWN, imq_setup, numqueues);
++	if (!dev)
++		return -ENOMEM;
++
++	ret = dev_alloc_name(dev, dev->name);
++	if (ret < 0)
++		goto fail;
++
++	dev->rtnl_link_ops = &imq_link_ops;
++	ret = register_netdevice(dev);
++	if (ret < 0)
++		goto fail;
++
++	return 0;
++fail:
++	free_netdev(dev);
++	return ret;
++}
++
++static int __init imq_init_devs(void)
++{
++	int err, i;
++
++	if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
++		pr_err("IMQ: numdevs has to be betweed 1 and %u\n",
++		       IMQ_MAX_DEVS);
++		return -EINVAL;
++	}
++
++	if (numqueues < 1 || numqueues > IMQ_MAX_QUEUES) {
++		pr_err("IMQ: numqueues has to be betweed 1 and %u\n",
++		       IMQ_MAX_QUEUES);
++		return -EINVAL;
++	}
++
++	get_random_bytes(&imq_hashrnd, sizeof(imq_hashrnd));
++
++	rtnl_lock();
++	err = __rtnl_link_register(&imq_link_ops);
++
++	for (i = 0; i < numdevs && !err; i++)
++		err = imq_init_one(i);
++
++	if (err) {
++		__rtnl_link_unregister(&imq_link_ops);
++		memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
++	}
++	rtnl_unlock();
++
++	return err;
++}
++
++static int __init imq_init_module(void)
++{
++	int err;
++
++#if defined(CONFIG_IMQ_NUM_DEVS)
++	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
++	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
++	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
++#endif
++
++	err = imq_init_devs();
++	if (err) {
++		pr_err("IMQ: Error trying imq_init_devs(net)\n");
++		return err;
++	}
++
++	err = imq_init_hooks();
++	if (err) {
++		pr_err(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
++		rtnl_link_unregister(&imq_link_ops);
++		memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
++		return err;
++	}
++
++	pr_info("IMQ driver loaded successfully. (numdevs = %d, numqueues = %d, imq_dev_accurate_stats = %d)\n",
++		numdevs, numqueues, imq_dev_accurate_stats);
++
++#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++	pr_info("\tHooking IMQ before NAT on PREROUTING.\n");
++#else
++	pr_info("\tHooking IMQ after NAT on PREROUTING.\n");
++#endif
++#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
++	pr_info("\tHooking IMQ before NAT on POSTROUTING.\n");
++#else
++	pr_info("\tHooking IMQ after NAT on POSTROUTING.\n");
++#endif
++
++	return 0;
++}
++
++static void __exit imq_unhook(void)
++{
++	nf_unregister_hooks(imq_ops, ARRAY_SIZE(imq_ops));
++	nf_unregister_queue_imq_handler();
++}
++
++static void __exit imq_cleanup_devs(void)
++{
++	rtnl_link_unregister(&imq_link_ops);
++	memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
++}
++
++static void __exit imq_exit_module(void)
++{
++	imq_unhook();
++	imq_cleanup_devs();
++	pr_info("IMQ driver unloaded successfully.\n");
++}
++
++module_init(imq_init_module);
++module_exit(imq_exit_module);
++
++module_param(numdevs, int, 0);
++module_param(numqueues, int, 0);
++module_param(imq_dev_accurate_stats, int, 0);
++MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
++MODULE_PARM_DESC(numqueues, "number of queues per IMQ device");
++MODULE_PARM_DESC(imq_dev_accurate_stats, "Notify if need the accurate imq device stats");
++
++MODULE_AUTHOR("http://https://github.com/imq/linuximq");
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_RTNL_LINK("imq");
+diff --git a/include/linux/imq.h b/include/linux/imq.h
+new file mode 100644
+index 0000000..1babb09
+--- /dev/null
++++ b/include/linux/imq.h
+@@ -0,0 +1,13 @@
++#ifndef _IMQ_H
++#define _IMQ_H
++
++/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
++#define IMQ_F_BITS	5
++
++#define IMQ_F_IFMASK	0x0f
++#define IMQ_F_ENQUEUE	0x10
++
++#define IMQ_MAX_DEVS	(IMQ_F_IFMASK + 1)
++
++#endif /* _IMQ_H */
++
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 3143c84..e213b31 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -3341,6 +3341,19 @@ static inline void netif_tx_unlock_bh(struct net_device *dev)
+ 	}						\
+ }
+ 
++#define HARD_TX_LOCK_BH(dev, txq) {           \
++    if ((dev->features & NETIF_F_LLTX) == 0) {  \
++        __netif_tx_lock_bh(txq);      \
++    }                       \
++}
++
++#define HARD_TX_UNLOCK_BH(dev, txq) {          \
++    if ((dev->features & NETIF_F_LLTX) == 0) {  \
++        __netif_tx_unlock_bh(txq);         \
++    }                       \
++}
++
++
+ static inline void netif_tx_disable(struct net_device *dev)
+ {
+ 	unsigned int i;
+diff --git a/include/linux/netfilter/xt_IMQ.h b/include/linux/netfilter/xt_IMQ.h
+new file mode 100644
+index 0000000..9b07230
+--- /dev/null
++++ b/include/linux/netfilter/xt_IMQ.h
+@@ -0,0 +1,9 @@
++#ifndef _XT_IMQ_H
++#define _XT_IMQ_H
++
++struct xt_imq_info {
++	unsigned int todev;     /* target imq device */
++};
++
++#endif /* _XT_IMQ_H */
++
+diff --git a/include/linux/netfilter_ipv4/ipt_IMQ.h b/include/linux/netfilter_ipv4/ipt_IMQ.h
+new file mode 100644
+index 0000000..7af320f
+--- /dev/null
++++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
+@@ -0,0 +1,10 @@
++#ifndef _IPT_IMQ_H
++#define _IPT_IMQ_H
++
++/* Backwards compatibility for old userspace */
++#include <linux/netfilter/xt_IMQ.h>
++
++#define ipt_imq_info xt_imq_info
++
++#endif /* _IPT_IMQ_H */
++
+diff --git a/include/linux/netfilter_ipv6/ip6t_IMQ.h b/include/linux/netfilter_ipv6/ip6t_IMQ.h
+new file mode 100644
+index 0000000..198ac01
+--- /dev/null
++++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
+@@ -0,0 +1,10 @@
++#ifndef _IP6T_IMQ_H
++#define _IP6T_IMQ_H
++
++/* Backwards compatibility for old userspace */
++#include <linux/netfilter/xt_IMQ.h>
++
++#define ip6t_imq_info xt_imq_info
++
++#endif /* _IP6T_IMQ_H */
++
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 4355129..47914c0 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -38,6 +38,10 @@
+ #include <linux/splice.h>
+ #include <linux/in6.h>
+ #include <net/flow.h>
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++#include <linux/imq.h>
++#endif
++
+ 
+ /* A. Checksumming of received packets by device.
+  *
+@@ -566,6 +570,9 @@ struct sk_buff {
+ 	 * first. This is owned by whoever has the skb queued ATM.
+ 	 */
+ 	char			cb[48] __aligned(8);
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++	void			*cb_next;
++#endif
+ 
+ 	unsigned long		_skb_refdst;
+ 	void			(*destructor)(struct sk_buff *skb);
+@@ -575,6 +582,9 @@ struct sk_buff {
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ 	struct nf_conntrack	*nfct;
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++       struct nf_queue_entry   *nf_queue_entry;
++#endif
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ 	struct nf_bridge_info	*nf_bridge;
+ #endif
+@@ -642,6 +652,9 @@ struct sk_buff {
+ 	__u8			inner_protocol_type:1;
+ 	__u8			remcsum_offload:1;
+ 	/* 3 or 5 bit hole */
++	#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++	__u8                    imq_flags:IMQ_F_BITS;
++	#endif
+ 
+ #ifdef CONFIG_NET_SCHED
+ 	__u16			tc_index;	/* traffic control index */
+@@ -798,6 +811,12 @@ void kfree_skb_list(struct sk_buff *segs);
+ void skb_tx_error(struct sk_buff *skb);
+ void consume_skb(struct sk_buff *skb);
+ void  __kfree_skb(struct sk_buff *skb);
++
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++int skb_save_cb(struct sk_buff *skb);
++int skb_restore_cb(struct sk_buff *skb);
++#endif
++
+ extern struct kmem_cache *skbuff_head_cache;
+ 
+ void kfree_skb_partial(struct sk_buff *skb, bool head_stolen);
+@@ -3344,6 +3363,10 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
+ 	if (copy)
+ 		dst->nfctinfo = src->nfctinfo;
+ #endif
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++       dst->imq_flags = src->imq_flags;
++       dst->nf_queue_entry = src->nf_queue_entry;
++#endif
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ 	dst->nf_bridge  = src->nf_bridge;
+ 	nf_bridge_get(src->nf_bridge);
+diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
+index 9c5638a..b173aa7 100644
+--- a/include/net/netfilter/nf_queue.h
++++ b/include/net/netfilter/nf_queue.h
+@@ -31,6 +31,12 @@ struct nf_queue_handler {
+ void nf_register_queue_handler(const struct nf_queue_handler *qh);
+ void nf_unregister_queue_handler(void);
+ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
++void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
++
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
++void nf_unregister_queue_imq_handler(void);
++#endif
+ 
+ void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
+ void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
+diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
+index 401038d..4668849 100644
+--- a/include/net/pkt_sched.h
++++ b/include/net/pkt_sched.h
+@@ -104,6 +104,8 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
+ 
+ void __qdisc_run(struct Qdisc *q);
+ 
++struct sk_buff *qdisc_dequeue_skb(struct Qdisc *q, bool *validate);
++
+ static inline void qdisc_run(struct Qdisc *q)
+ {
+ 	if (qdisc_run_begin(q))
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index b2a8e63..d9feaa3 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -506,6 +506,12 @@ static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ 	return sch->enqueue(skb, sch);
+ }
+ 
++static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
++{
++    qdisc_skb_cb(skb)->pkt_len = skb->len;
++    return qdisc_enqueue(skb, sch) & NET_XMIT_MASK;
++}
++
+ static inline bool qdisc_is_percpu_stats(const struct Qdisc *q)
+ {
+ 	return q->flags & TCQ_F_CPUSTATS;
+diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
+index d93f949..23fb6d1 100644
+--- a/include/uapi/linux/netfilter.h
++++ b/include/uapi/linux/netfilter.h
+@@ -14,7 +14,8 @@
+ #define NF_QUEUE 3
+ #define NF_REPEAT 4
+ #define NF_STOP 5
+-#define NF_MAX_VERDICT NF_STOP
++#define NF_IMQ_QUEUE 6
++#define NF_MAX_VERDICT NF_IMQ_QUEUE
+ 
+ /* we overload the higher bits for encoding auxiliary data such as the queue
+  * number or errno values. Not nice, but better than additional function
+diff --git a/net/core/dev.c b/net/core/dev.c
+index ae00b89..1cdcd02 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -137,6 +137,9 @@
+ #include <linux/errqueue.h>
+ #include <linux/hrtimer.h>
+ #include <linux/netfilter_ingress.h>
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++#include <linux/imq.h>
++#endif
+ 
+ #include "net-sysfs.h"
+ 
+@@ -2705,7 +2708,12 @@ static int xmit_one(struct sk_buff *skb, struct net_device *dev,
+ 	unsigned int len;
+ 	int rc;
+ 
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++	if ((!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) &&
++		!(skb->imq_flags & IMQ_F_ENQUEUE))
++#else
+ 	if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
++#endif
+ 		dev_queue_xmit_nit(skb, dev);
+ 
+ 	len = skb->len;
+@@ -2743,6 +2751,7 @@ out:
+ 	*ret = rc;
+ 	return skb;
+ }
++EXPORT_SYMBOL(dev_hard_start_xmit);
+ 
+ static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
+ 					  netdev_features_t features)
+@@ -2831,6 +2840,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
+ 	}
+ 	return head;
+ }
++//EXPORT_SYMBOL(validate_xmit_skb_list);
+ 
+ static void qdisc_pkt_len_init(struct sk_buff *skb)
+ {
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index b2df375..bc3c51e 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -79,6 +79,87 @@
+ static struct kmem_cache *skbuff_fclone_cache __read_mostly;
+ int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
+ EXPORT_SYMBOL(sysctl_max_skb_frags);
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
++#endif
++
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++/* Control buffer save/restore for IMQ devices */
++struct skb_cb_table {
++	char			cb[48] __aligned(8);
++	void			*cb_next;
++	atomic_t		refcnt;
++};
++
++static DEFINE_SPINLOCK(skb_cb_store_lock);
++
++int skb_save_cb(struct sk_buff *skb)
++{
++	struct skb_cb_table *next;
++
++	next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
++	if (!next)
++		return -ENOMEM;
++
++	BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
++
++	memcpy(next->cb, skb->cb, sizeof(skb->cb));
++	next->cb_next = skb->cb_next;
++
++	atomic_set(&next->refcnt, 1);
++
++	skb->cb_next = next;
++	return 0;
++}
++EXPORT_SYMBOL(skb_save_cb);
++
++int skb_restore_cb(struct sk_buff *skb)
++{
++	struct skb_cb_table *next;
++
++	if (!skb->cb_next)
++		return 0;
++
++	next = skb->cb_next;
++
++	BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
++
++	memcpy(skb->cb, next->cb, sizeof(skb->cb));
++	skb->cb_next = next->cb_next;
++
++	spin_lock(&skb_cb_store_lock);
++
++	if (atomic_dec_and_test(&next->refcnt))
++		kmem_cache_free(skbuff_cb_store_cache, next);
++
++	spin_unlock(&skb_cb_store_lock);
++
++	return 0;
++}
++EXPORT_SYMBOL(skb_restore_cb);
++
++static void skb_copy_stored_cb(struct sk_buff *   , const struct sk_buff *     ) __attribute__ ((unused));
++static void skb_copy_stored_cb(struct sk_buff *new, const struct sk_buff *__old)
++{
++	struct skb_cb_table *next;
++	struct sk_buff *old;
++
++	if (!__old->cb_next) {
++		new->cb_next = NULL;
++		return;
++	}
++
++	spin_lock(&skb_cb_store_lock);
++
++	old = (struct sk_buff *)__old;
++
++	next = old->cb_next;
++	atomic_inc(&next->refcnt);
++	new->cb_next = next;
++
++	spin_unlock(&skb_cb_store_lock);
++}
++#endif
+ 
+ /**
+  *	skb_panic - private function for out-of-line support
+@@ -643,6 +724,28 @@ static void skb_release_head_state(struct sk_buff *skb)
+ 		WARN_ON(in_irq());
+ 		skb->destructor(skb);
+ 	}
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++	/*
++	 * This should not happen. When it does, avoid memleak by restoring
++	 * the chain of cb-backups.
++	 */
++	while (skb->cb_next != NULL) {
++		if (net_ratelimit())
++			pr_warn("IMQ: kfree_skb: skb->cb_next: %08x\n",
++				(unsigned int)(uintptr_t)skb->cb_next);
++
++		skb_restore_cb(skb);
++	}
++	/*
++	 * This should not happen either, nf_queue_entry is nullified in
++	 * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
++	 * leaking entry pointers, maybe memory. We don't know if this is
++	 * pointer to already freed memory, or should this be freed.
++	 * If this happens we need to add refcounting, etc for nf_queue_entry.
++	 */
++	if (skb->nf_queue_entry && net_ratelimit())
++		pr_warn("%s\n", "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
++#endif
+ #if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ 	nf_conntrack_put(skb->nfct);
+ #endif
+@@ -765,6 +868,10 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+ 	new->sp			= secpath_get(old->sp);
+ #endif
+ 	__nf_copy(new, old, false);
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++	new->cb_next = NULL;
++	/*skb_copy_stored_cb(new, old);*/
++#endif
+ 
+ 	/* Note : this field could be in headers_start/headers_end section
+ 	 * It is not yet because we do not want to have a 16 bit hole
+@@ -3325,6 +3432,13 @@ void __init skb_init(void)
+ 						0,
+ 						SLAB_HWCACHE_ALIGN|SLAB_PANIC,
+ 						NULL);
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++	skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
++						  sizeof(struct skb_cb_table),
++						  0,
++						  SLAB_HWCACHE_ALIGN|SLAB_PANIC,
++						  NULL);
++#endif
+ }
+ 
+ /**
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index e6a7bd15..c81496e 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -65,9 +65,6 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
+ 	struct in6_addr *nexthop;
+ 	int ret;
+ 
+-	skb->protocol = htons(ETH_P_IPV6);
+-	skb->dev = dev;
+-
+ 	if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
+ 		struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+ 
+@@ -142,6 +139,13 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+ 		return 0;
+ 	}
+ 
++	/*
++	* IMQ-patch: moved setting skb->dev and skb->protocol from
++	* ip6_finish_output2 to fix crashing at netif_skb_features().
++	*/
++	skb->protocol = htons(ETH_P_IPV6);
++	skb->dev = dev;
++
+ 	return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
+ 			    net, sk, skb, NULL, dev,
+ 			    ip6_finish_output,
+diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
+index 4692782..dce47db 100644
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -785,6 +785,18 @@ config NETFILTER_XT_TARGET_LOG
+ 
+ 	  To compile it as a module, choose M here.  If unsure, say N.
+ 
++config NETFILTER_XT_TARGET_IMQ
++        tristate '"IMQ" target support'
++	depends on NETFILTER_XTABLES
++	depends on IP_NF_MANGLE || IP6_NF_MANGLE
++	select IMQ
++	default m if NETFILTER_ADVANCED=n
++        help
++          This option adds a `IMQ' target which is used to specify if and
++          to which imq device packets should get enqueued/dequeued.
++
++          To compile it as a module, choose M here.  If unsure, say N.
++
+ config NETFILTER_XT_TARGET_MARK
+ 	tristate '"MARK" target support'
+ 	depends on NETFILTER_ADVANCED
+diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
+index 7638c36..614ad8a 100644
+--- a/net/netfilter/Makefile
++++ b/net/netfilter/Makefile
+@@ -108,6 +108,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
++obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
+diff --git a/net/netfilter/core.c b/net/netfilter/core.c
+index f39276d..9877a27 100644
+--- a/net/netfilter/core.c
++++ b/net/netfilter/core.c
+@@ -311,9 +311,11 @@ next_hook:
+ 		ret = NF_DROP_GETERR(verdict);
+ 		if (ret == 0)
+ 			ret = -EPERM;
+-	} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
++	} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE ||
++		(verdict & NF_VERDICT_MASK) == NF_IMQ_QUEUE) {
+ 		int err = nf_queue(skb, elem, state,
+-				   verdict >> NF_VERDICT_QBITS);
++				   verdict >> NF_VERDICT_QBITS,
++				  verdict & NF_VERDICT_MASK);
+ 		if (err < 0) {
+ 			if (err == -ESRCH &&
+ 			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
+diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
+index 0655225..25d4141 100644
+--- a/net/netfilter/nf_internals.h
++++ b/net/netfilter/nf_internals.h
+@@ -18,7 +18,7 @@ unsigned int nf_iterate(struct list_head *head, struct sk_buff *skb,
+ 
+ /* nf_queue.c */
+ int nf_queue(struct sk_buff *skb, struct nf_hook_ops *elem,
+-	     struct nf_hook_state *state, unsigned int queuenum);
++	     struct nf_hook_state *state, unsigned int queuenum, unsigned int queuetype);
+ void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops);
+ int __init netfilter_queue_init(void);
+ 
+diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
+index 5baa8e2..9740e8c 100644
+--- a/net/netfilter/nf_queue.c
++++ b/net/netfilter/nf_queue.c
+@@ -28,6 +28,23 @@
+  */
+ static const struct nf_queue_handler __rcu *queue_handler __read_mostly;
+ 
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++static const struct nf_queue_handler __rcu *queue_imq_handler __read_mostly;
++
++void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
++{
++	rcu_assign_pointer(queue_imq_handler, qh);
++}
++EXPORT_SYMBOL_GPL(nf_register_queue_imq_handler);
++
++void nf_unregister_queue_imq_handler(void)
++{
++	RCU_INIT_POINTER(queue_imq_handler, NULL);
++	synchronize_rcu();
++}
++EXPORT_SYMBOL_GPL(nf_unregister_queue_imq_handler);
++#endif
++
+ /* return EBUSY when somebody else is registered, return EEXIST if the
+  * same handler is registered, return 0 in case of success. */
+ void nf_register_queue_handler(const struct nf_queue_handler *qh)
+@@ -116,7 +133,8 @@ void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops)
+ int nf_queue(struct sk_buff *skb,
+ 	     struct nf_hook_ops *elem,
+ 	     struct nf_hook_state *state,
+-	     unsigned int queuenum)
++	     unsigned int queuenum,
++		 unsigned int queuetype)
+ {
+ 	int status = -ENOENT;
+ 	struct nf_queue_entry *entry = NULL;
+@@ -124,7 +142,17 @@ int nf_queue(struct sk_buff *skb,
+ 	const struct nf_queue_handler *qh;
+ 
+ 	/* QUEUE == DROP if no one is waiting, to be safe. */
+-	qh = rcu_dereference(queue_handler);
++	if (queuetype == NF_IMQ_QUEUE) {
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++		qh = rcu_dereference(queue_imq_handler);
++#else
++		BUG();
++		goto err_unlock;
++#endif
++	} else {
++		qh = rcu_dereference(queue_handler);
++	}
++
+ 	if (!qh) {
+ 		status = -ESRCH;
+ 		goto err;
+@@ -199,8 +227,10 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
+ 		local_bh_enable();
+ 		break;
+ 	case NF_QUEUE:
++	case NF_IMQ_QUEUE:
+ 		err = nf_queue(skb, elem, &entry->state,
+-			       verdict >> NF_VERDICT_QBITS);
++			       verdict >> NF_VERDICT_QBITS,
++				   verdict & NF_VERDICT_MASK);
+ 		if (err < 0) {
+ 			if (err == -ESRCH &&
+ 			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
+diff --git a/net/netfilter/xt_IMQ.c b/net/netfilter/xt_IMQ.c
+new file mode 100644
+index 0000000..86d7b84
+--- /dev/null
++++ b/net/netfilter/xt_IMQ.c
+@@ -0,0 +1,72 @@
++/*
++ * This target marks packets to be enqueued to an imq device
++ */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter/x_tables.h>
++#include <linux/netfilter/xt_IMQ.h>
++#include <linux/imq.h>
++
++static unsigned int imq_target(struct sk_buff *pskb,
++				const struct xt_action_param *par)
++{
++	const struct xt_imq_info *mr = par->targinfo;
++
++	pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
++
++	return XT_CONTINUE;
++}
++
++static int imq_checkentry(const struct xt_tgchk_param *par)
++{
++	struct xt_imq_info *mr = par->targinfo;
++
++	if (mr->todev > IMQ_MAX_DEVS - 1) {
++		pr_warn("IMQ: invalid device specified, highest is %u\n",
++			IMQ_MAX_DEVS - 1);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static struct xt_target xt_imq_reg[] __read_mostly = {
++	{
++		.name           = "IMQ",
++		.family		= AF_INET,
++		.checkentry     = imq_checkentry,
++		.target         = imq_target,
++		.targetsize	= sizeof(struct xt_imq_info),
++		.table		= "mangle",
++		.me             = THIS_MODULE
++	},
++	{
++		.name           = "IMQ",
++		.family		= AF_INET6,
++		.checkentry     = imq_checkentry,
++		.target         = imq_target,
++		.targetsize	= sizeof(struct xt_imq_info),
++		.table		= "mangle",
++		.me             = THIS_MODULE
++	},
++};
++
++static int __init imq_init(void)
++{
++	return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
++}
++
++static void __exit imq_fini(void)
++{
++	xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
++}
++
++module_init(imq_init);
++module_exit(imq_fini);
++
++MODULE_AUTHOR("http://https://github.com/imq/linuximq");
++MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("ipt_IMQ");
++MODULE_ALIAS("ip6t_IMQ");
++
+diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
+index e82a1ad..b55331d 100644
+--- a/net/sched/sch_generic.c
++++ b/net/sched/sch_generic.c
+@@ -108,6 +108,14 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
+ 	return skb;
+ }
+ 
++struct sk_buff *qdisc_dequeue_skb(struct Qdisc *q, bool *validate)
++{
++	int packets;
++
++	return dequeue_skb(q, validate, &packets);
++}
++EXPORT_SYMBOL(qdisc_dequeue_skb);
++
+ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
+ 					   struct netdev_queue *dev_queue,
+ 					   struct Qdisc *q)
Index: npl/kernel/linux_src/linux-5.9-imq.patch
===================================================================
--- npl/kernel/linux_src/linux-5.9-imq.patch	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ 	(revision )
@@ -1,1691 +1,0 @@
-diff -purN linux-5.8_org/drivers/net/imq.c linux-5.8/drivers/net/imq.c
---- linux-5.8_org/drivers/net/imq.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.8/drivers/net/imq.c	2020-08-18 21:52:02.073931596 +0200
-@@ -0,0 +1,957 @@
-+/*
-+ *             Pseudo-driver for the intermediate queue device.
-+ *
-+ *             This program is free software; you can redistribute it and/or
-+ *             modify it under the terms of the GNU General Public License
-+ *             as published by the Free Software Foundation; either version
-+ *             2 of the License, or (at your option) any later version.
-+ *
-+ * Authors:    Patrick McHardy, <kaber@trash.net>
-+ *
-+ *            The first version was written by Martin Devera, <devik@cdi.cz>
-+ *
-+ *			   See Credits.txt
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/moduleparam.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/if_arp.h>
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+#include <linux/netfilter_ipv6.h>
-+#endif
-+#include <linux/imq.h>
-+#include <net/pkt_sched.h>
-+#include <net/netfilter/nf_queue.h>
-+#include <net/sock.h>
-+#include <linux/ip.h>
-+#include <linux/ipv6.h>
-+#include <linux/if_vlan.h>
-+#include <linux/if_pppox.h>
-+#include <net/ip.h>
-+#include <net/ipv6.h>
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num);
-+
-+static nf_hookfn imq_nf_hook;
-+
-+static struct nf_hook_ops imq_ops[] = {
-+	{
-+	/* imq_ingress_ipv4 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET,
-+		.hooknum	= NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+		.priority	= NF_IP_PRI_MANGLE + 1,
-+#else
-+		.priority	= NF_IP_PRI_NAT_DST + 1,
-+#endif
-+	},
-+	{
-+	/* imq_egress_ipv4 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET,
-+		.hooknum	= NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+		.priority	= NF_IP_PRI_LAST,
-+#else
-+		.priority	= NF_IP_PRI_NAT_SRC - 1,
-+#endif
-+	},
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+	{
-+	/* imq_ingress_ipv6 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET6,
-+		.hooknum	= NF_INET_PRE_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+		.priority	= NF_IP6_PRI_MANGLE + 1,
-+#else
-+		.priority	= NF_IP6_PRI_NAT_DST + 1,
-+#endif
-+	},
-+	{
-+	/* imq_egress_ipv6 */
-+		.hook		= imq_nf_hook,
-+		.pf		= PF_INET6,
-+		.hooknum	= NF_INET_POST_ROUTING,
-+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
-+		.priority	= NF_IP6_PRI_LAST,
-+#else
-+		.priority	= NF_IP6_PRI_NAT_SRC - 1,
-+#endif
-+	},
-+#endif
-+};
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+static int numdevs = CONFIG_IMQ_NUM_DEVS;
-+#else
-+static int numdevs = IMQ_MAX_DEVS;
-+#endif
-+
-+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
-+
-+#define IMQ_MAX_QUEUES 32
-+static int numqueues = 1;
-+static u32 imq_hashrnd;
-+static int imq_dev_accurate_stats = 1;
-+
-+static inline __be16 pppoe_proto(const struct sk_buff *skb)
-+{
-+	return *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
-+			sizeof(struct pppoe_hdr)));
-+}
-+
-+static u16 imq_hash(struct net_device *dev, struct sk_buff *skb)
-+{
-+	unsigned int pull_len;
-+	u16 protocol = skb->protocol;
-+	u32 addr1, addr2;
-+	u32 hash, ihl = 0;
-+	union {
-+		u16 in16[2];
-+		u32 in32;
-+	} ports;
-+	u8 ip_proto;
-+
-+	pull_len = 0;
-+
-+recheck:
-+	switch (protocol) {
-+	case htons(ETH_P_8021Q): {
-+		if (unlikely(skb_pull(skb, VLAN_HLEN) == NULL))
-+			goto other;
-+
-+		pull_len += VLAN_HLEN;
-+		skb->network_header += VLAN_HLEN;
-+
-+		protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-+		goto recheck;
-+	}
-+
-+	case htons(ETH_P_PPP_SES): {
-+		if (unlikely(skb_pull(skb, PPPOE_SES_HLEN) == NULL))
-+			goto other;
-+
-+		pull_len += PPPOE_SES_HLEN;
-+		skb->network_header += PPPOE_SES_HLEN;
-+
-+		protocol = pppoe_proto(skb);
-+		goto recheck;
-+	}
-+
-+	case htons(ETH_P_IP): {
-+		const struct iphdr *iph = ip_hdr(skb);
-+
-+		if (unlikely(!pskb_may_pull(skb, sizeof(struct iphdr))))
-+			goto other;
-+
-+		addr1 = iph->daddr;
-+		addr2 = iph->saddr;
-+
-+		ip_proto = !(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) ?
-+				 iph->protocol : 0;
-+		ihl = ip_hdrlen(skb);
-+
-+		break;
-+	}
-+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-+	case htons(ETH_P_IPV6): {
-+		const struct ipv6hdr *iph = ipv6_hdr(skb);
-+		__be16 fo = 0;
-+
-+		if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr))))
-+			goto other;
-+
-+		addr1 = iph->daddr.s6_addr32[3];
-+		addr2 = iph->saddr.s6_addr32[3];
-+		ihl = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &ip_proto,
-+				       &fo);
-+		if (unlikely(ihl < 0))
-+			goto other;
-+
-+		break;
-+	}
-+#endif
-+	default:
-+other:
-+		if (pull_len != 0) {
-+			skb_push(skb, pull_len);
-+			skb->network_header -= pull_len;
-+		}
-+
-+		return (u16)(ntohs(protocol) % dev->real_num_tx_queues);
-+	}
-+
-+	if (addr1 > addr2)
-+		swap(addr1, addr2);
-+
-+	switch (ip_proto) {
-+	case IPPROTO_TCP:
-+	case IPPROTO_UDP:
-+	case IPPROTO_DCCP:
-+	case IPPROTO_ESP:
-+	case IPPROTO_AH:
-+	case IPPROTO_SCTP:
-+	case IPPROTO_UDPLITE: {
-+		if (likely(skb_copy_bits(skb, ihl, &ports.in32, 4) >= 0)) {
-+			if (ports.in16[0] > ports.in16[1])
-+				swap(ports.in16[0], ports.in16[1]);
-+			break;
-+		}
-+		/* fall-through */
-+	}
-+	default:
-+		ports.in32 = 0;
-+		break;
-+	}
-+
-+	if (pull_len != 0) {
-+		skb_push(skb, pull_len);
-+		skb->network_header -= pull_len;
-+	}
-+
-+	hash = jhash_3words(addr1, addr2, ports.in32, imq_hashrnd ^ ip_proto);
-+
-+	return (u16)(((u64)hash * dev->real_num_tx_queues) >> 32);
-+}
-+
-+static inline bool sk_tx_queue_recorded(struct sock *sk)
-+{
-+	return (sk_tx_queue_get(sk) >= 0);
-+}
-+
-+static struct netdev_queue *imq_select_queue(struct net_device *dev,
-+						struct sk_buff *skb)
-+{
-+	u16 queue_index = 0;
-+	u32 hash;
-+
-+	if (likely(dev->real_num_tx_queues == 1))
-+		goto out;
-+
-+	/* IMQ can be receiving ingress or engress packets. */
-+
-+	/* Check first for if rx_queue is set */
-+	if (skb_rx_queue_recorded(skb)) {
-+		queue_index = skb_get_rx_queue(skb);
-+		goto out;
-+	}
-+
-+	/* Check if socket has tx_queue set */
-+	if (sk_tx_queue_recorded(skb->sk)) {
-+		queue_index = sk_tx_queue_get(skb->sk);
-+		goto out;
-+	}
-+
-+	/* Try use socket hash */
-+	if (skb->sk && skb->sk->sk_hash) {
-+		hash = skb->sk->sk_hash;
-+		queue_index =
-+			(u16)(((u64)hash * dev->real_num_tx_queues) >> 32);
-+		goto out;
-+	}
-+
-+	/* Generate hash from packet data */
-+	queue_index = imq_hash(dev, skb);
-+
-+out:
-+	if (unlikely(queue_index >= dev->real_num_tx_queues))
-+		queue_index = (u16)((u32)queue_index % dev->real_num_tx_queues);
-+
-+	skb_set_queue_mapping(skb, queue_index);
-+	return netdev_get_tx_queue(dev, queue_index);
-+}
-+
-+static struct net_device_stats *imq_get_stats(struct net_device *dev)
-+{
-+	return &dev->stats;
-+}
-+
-+/* called for packets kfree'd in qdiscs at places other than enqueue */
-+static void imq_skb_destructor(struct sk_buff *skb)
-+{
-+	struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+	skb->nf_queue_entry = NULL;
-+
-+	if (entry) {
-+		nf_queue_entry_free(entry);
-+		kfree(entry);
-+	}
-+
-+	skb_restore_cb(skb); /* kfree backup */
-+}
-+
-+static void imq_done_check_queue_mapping(struct sk_buff *skb,
-+					 struct net_device *dev)
-+{
-+	unsigned int queue_index;
-+
-+	/* Don't let queue_mapping be left too large after exiting IMQ */
-+	if (likely(skb->dev != dev && skb->dev != NULL)) {
-+		queue_index = skb_get_queue_mapping(skb);
-+		if (unlikely(queue_index >= skb->dev->real_num_tx_queues)) {
-+			queue_index = (u16)((u32)queue_index %
-+						skb->dev->real_num_tx_queues);
-+			skb_set_queue_mapping(skb, queue_index);
-+		}
-+	} else {
-+		/* skb->dev was IMQ device itself or NULL, be on safe side and
-+		 * just clear queue mapping.
-+		 */
-+		skb_set_queue_mapping(skb, 0);
-+	}
-+}
-+
-+static netdev_tx_t imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+	struct nf_queue_entry *entry = skb->nf_queue_entry;
-+
-+	rcu_read_lock();
-+
-+	skb->nf_queue_entry = NULL;
-+	netif_trans_update(dev);
-+
-+	dev->stats.tx_bytes += skb->len;
-+	dev->stats.tx_packets++;
-+
-+	if (unlikely(entry == NULL)) {
-+		/* We don't know what is going on here.. packet is queued for
-+		 * imq device, but (probably) not by us.
-+		 *
-+		 * If this packet was not send here by imq_nf_queue(), then
-+		 * skb_save_cb() was not used and skb_free() should not show:
-+		 *   WARNING: IMQ: kfree_skb: skb->cb_next:..
-+		 * and/or
-+		 *   WARNING: IMQ: kfree_skb: skb->nf_queue_entry...
-+		 *
-+		 * However if this message is shown, then IMQ is somehow broken
-+		 * and you should report this to linuximq.net.
-+		 */
-+
-+		/* imq_dev_xmit is black hole that eats all packets, report that
-+		 * we eat this packet happily and increase dropped counters.
-+		 */
-+
-+		dev->stats.tx_dropped++;
-+		dev_kfree_skb(skb);
-+
-+		rcu_read_unlock();
-+		return NETDEV_TX_OK;
-+	}
-+
-+	skb_restore_cb(skb); /* restore skb->cb */
-+
-+	skb->imq_flags = 0;
-+	skb->destructor = NULL;
-+
-+	imq_done_check_queue_mapping(skb, dev);
-+
-+	nf_reinject(entry, NF_ACCEPT);
-+
-+	rcu_read_unlock();
-+	return NETDEV_TX_OK;
-+}
-+
-+static struct net_device *get_imq_device_by_index(int index)
-+{
-+	struct net_device *dev = NULL;
-+	struct net *net;
-+	char buf[8];
-+
-+	/* get device by name and cache result */
-+	snprintf(buf, sizeof(buf), "imq%d", index);
-+
-+	/* Search device from all namespaces. */
-+	for_each_net(net) {
-+		dev = dev_get_by_name(net, buf);
-+		if (dev)
-+			break;
-+	}
-+
-+	if (WARN_ON_ONCE(dev == NULL)) {
-+		/* IMQ device not found. Exotic config? */
-+		return ERR_PTR(-ENODEV);
-+	}
-+
-+	imq_devs_cache[index] = dev;
-+	dev_put(dev);
-+
-+	return dev;
-+}
-+
-+static struct nf_queue_entry *nf_queue_entry_dup(struct nf_queue_entry *e)
-+{
-+	struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC);
-+	if (entry) {
-+		nf_queue_entry_get_refs(entry);
-+		return entry;
-+	}
-+	return NULL;
-+}
-+
-+#ifdef CONFIG_BRIDGE_NETFILTER
-+/* When called from bridge netfilter, skb->data must point to MAC header
-+ * before calling skb_gso_segment(). Else, original MAC header is lost
-+ * and segmented skbs will be sent to wrong destination.
-+ */
-+static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
-+{
-+	if (skb->nf_bridge)
-+		__skb_push(skb, skb->network_header - skb->mac_header);
-+}
-+
-+static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
-+{
-+	if (skb->nf_bridge)
-+		__skb_pull(skb, skb->network_header - skb->mac_header);
-+}
-+#else
-+#define nf_bridge_adjust_skb_data(s) do {} while (0)
-+#define nf_bridge_adjust_segmented_data(s) do {} while (0)
-+#endif
-+
-+static int __imq_nf_queue(struct nf_queue_entry *entry, struct net_device *dev);
-+
-+static int __imq_nf_queue_gso(struct nf_queue_entry *entry,
-+			      struct net_device *dev, struct sk_buff *skb)
-+{
-+	int ret = -ENOMEM;
-+	struct nf_queue_entry *entry_seg;
-+
-+	nf_bridge_adjust_segmented_data(skb);
-+
-+	if (skb->next == NULL) { /* last packet, no need to copy entry */
-+		struct sk_buff *gso_skb = entry->skb;
-+		entry->skb = skb;
-+		ret = __imq_nf_queue(entry, dev);
-+		if (ret)
-+			entry->skb = gso_skb;
-+		return ret;
-+	}
-+
-+	skb->next = NULL;
-+
-+	entry_seg = nf_queue_entry_dup(entry);
-+	if (entry_seg) {
-+		entry_seg->skb = skb;
-+		ret = __imq_nf_queue(entry_seg, dev);
-+		if (ret)
-+			nf_queue_entry_free(entry_seg);
-+	}
-+	return ret;
-+}
-+
-+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
-+{
-+	struct sk_buff *skb, *segs;
-+	struct net_device *dev;
-+	unsigned int queued;
-+	int index, retval, err;
-+
-+	index = entry->skb->imq_flags & IMQ_F_IFMASK;
-+	if (unlikely(index > numdevs - 1)) {
-+		if (net_ratelimit())
-+			pr_warn("IMQ: invalid device specified, highest is %u\n",
-+				numdevs - 1);
-+		retval = -EINVAL;
-+		goto out_no_dev;
-+	}
-+
-+	/* check for imq device by index from cache */
-+	dev = imq_devs_cache[index];
-+	if (unlikely(!dev)) {
-+		dev = get_imq_device_by_index(index);
-+		if (IS_ERR(dev)) {
-+			retval = PTR_ERR(dev);
-+			goto out_no_dev;
-+		}
-+	}
-+
-+	if (unlikely(!(dev->flags & IFF_UP))) {
-+		entry->skb->imq_flags = 0;
-+		retval = -ECANCELED;
-+		goto out_no_dev;
-+	}
-+
-+	/* Since 3.10.x, GSO handling moved here as result of upstream commit
-+	 * a5fedd43d5f6c94c71053a66e4c3d2e35f1731a2 (netfilter: move
-+	 * skb_gso_segment into nfnetlink_queue module).
-+	 *
-+	 * Following code replicates the gso handling from
-+	 * 'net/netfilter/nfnetlink_queue_core.c':nfqnl_enqueue_packet().
-+	 */
-+
-+	skb = entry->skb;
-+
-+	switch (entry->state.pf) {
-+	case NFPROTO_IPV4:
-+		skb->protocol = htons(ETH_P_IP);
-+		break;
-+	case NFPROTO_IPV6:
-+		skb->protocol = htons(ETH_P_IPV6);
-+		break;
-+	}
-+
-+	if (!skb_is_gso(entry->skb))
-+		return __imq_nf_queue(entry, dev);
-+
-+	nf_bridge_adjust_skb_data(skb);
-+	segs = skb_gso_segment(skb, 0);
-+	/* Does not use PTR_ERR to limit the number of error codes that can be
-+	 * returned by nf_queue.  For instance, callers rely on -ECANCELED to
-+	 * mean 'ignore this hook'.
-+	 */
-+	err = -ENOBUFS;
-+	if (IS_ERR(segs))
-+		goto out_err;
-+	queued = 0;
-+	err = 0;
-+	do {
-+		struct sk_buff *nskb = segs->next;
-+		if (nskb && nskb->next)
-+			nskb->cb_next = NULL;
-+		if (err == 0)
-+			err = __imq_nf_queue_gso(entry, dev, segs);
-+		if (err == 0)
-+			queued++;
-+		else
-+			kfree_skb(segs);
-+		segs = nskb;
-+	} while (segs);
-+
-+	if (queued) {
-+		if (err) /* some segments are already queued */
-+			nf_queue_entry_free(entry);
-+		kfree_skb(skb);
-+		return 0;
-+	}
-+
-+out_err:
-+	nf_bridge_adjust_segmented_data(skb);
-+	retval = err;
-+out_no_dev:
-+	return retval;
-+}
-+
-+static int __imq_nf_queue(struct nf_queue_entry *entry, struct net_device *dev)
-+{
-+	struct sk_buff *skb_orig, *skb, *skb_shared, *skb_popd;
-+	struct Qdisc *q;
-+	struct sk_buff *to_free = NULL;
-+	struct netdev_queue *txq;
-+	spinlock_t *root_lock;
-+	int users;
-+	int retval = -EINVAL;
-+	unsigned int orig_queue_index;
-+	bool again = false;
-+
-+	dev->last_rx = jiffies;
-+
-+	skb = entry->skb;
-+	skb_orig = NULL;
-+
-+	/* skb has owner? => make clone */
-+	if (unlikely(skb->destructor)) {
-+		skb_orig = skb;
-+		skb = skb_clone(skb, GFP_ATOMIC);
-+		if (unlikely(!skb)) {
-+			retval = -ENOMEM;
-+			goto out;
-+		}
-+		skb->cb_next = NULL;
-+		entry->skb = skb;
-+	}
-+
-+	dev->stats.rx_bytes += skb->len;
-+	dev->stats.rx_packets++;
-+
-+	if (!skb->dev) {
-+		/* skb->dev == NULL causes problems, try the find cause. */
-+		if (net_ratelimit()) {
-+			dev_warn(&dev->dev,
-+				 "received packet with skb->dev == NULL\n");
-+			dump_stack();
-+		}
-+
-+		skb->dev = dev;
-+	}
-+
-+	/* Disables softirqs for lock below */
-+	rcu_read_lock_bh();
-+
-+	/* Multi-queue selection */
-+	orig_queue_index = skb_get_queue_mapping(skb);
-+	txq = imq_select_queue(dev, skb);
-+
-+	q = rcu_dereference_bh(txq->qdisc);
-+	if (unlikely(!q->enqueue))
-+		goto packet_not_eaten_by_imq_dev;
-+
-+	skb->nf_queue_entry = entry;
-+	root_lock = qdisc_lock(q);
-+	spin_lock(root_lock);
-+
-+	users = refcount_read(&skb->users);
-+
-+	skb_shared = skb_get(skb); /* increase reference count by one */
-+
-+	/* backup skb->cb, as qdisc layer will overwrite it */
-+	skb_save_cb(skb_shared);
-+	qdisc_enqueue_root(skb_shared, q, &to_free); /* might kfree_skb */
-+	if (likely(refcount_read(&skb_shared->users) == users + 1)) {
-+		bool validate;
-+
-+		kfree_skb(skb_shared); /* decrease reference count by one */
-+
-+		skb->destructor = &imq_skb_destructor;
-+
-+		skb_popd = qdisc_dequeue_skb(q, &validate);
-+
-+		/* cloned? */
-+		if (unlikely(skb_orig))
-+			kfree_skb(skb_orig); /* free original */
-+
-+		spin_unlock(root_lock);
-+
-+#if 0
-+		/* schedule qdisc dequeue */
-+		__netif_schedule(q);
-+#else
-+		if (likely(skb_popd)) {
-+			/* Note that we validate skb (GSO, checksum, ...) outside of locks */
-+			if (validate)
-+        		skb_popd = validate_xmit_skb_list(skb_popd, dev, &again);
-+
-+			if (skb_popd) {
-+				int dummy_ret;
-+				int cpu = smp_processor_id(); /* ok because BHs are off */
-+
-+				txq = skb_get_tx_queue(dev, skb_popd);
-+				/*
-+				IMQ device will not be frozen or stoped, and it always be successful.
-+				So we need not check its status and return value to accelerate.
-+				*/
-+				if (imq_dev_accurate_stats && txq->xmit_lock_owner != cpu) {
-+					HARD_TX_LOCK(dev, txq, cpu);
-+					if (!netif_xmit_frozen_or_stopped(txq)) {
-+						dev_hard_start_xmit(skb_popd, dev, txq, &dummy_ret);
-+					}
-+					HARD_TX_UNLOCK(dev, txq);
-+				} else {
-+					if (!netif_xmit_frozen_or_stopped(txq)) {
-+						dev_hard_start_xmit(skb_popd, dev, txq, &dummy_ret);
-+					}
-+				}
-+			}
-+		} else {
-+			/* No ready skb, then schedule it */
-+			__netif_schedule(q);
-+		}
-+#endif
-+		rcu_read_unlock_bh();
-+		retval = 0;
-+		goto out;
-+	} else {
-+		skb_restore_cb(skb_shared); /* restore skb->cb */
-+		skb->nf_queue_entry = NULL;
-+		/*
-+		 * qdisc dropped packet and decreased skb reference count of
-+		 * skb, so we don't really want to and try refree as that would
-+		 * actually destroy the skb.
-+		 */
-+		spin_unlock(root_lock);
-+		goto packet_not_eaten_by_imq_dev;
-+	}
-+
-+packet_not_eaten_by_imq_dev:
-+	skb_set_queue_mapping(skb, orig_queue_index);
-+	rcu_read_unlock_bh();
-+
-+	/* cloned? restore original */
-+	if (unlikely(skb_orig)) {
-+		kfree_skb(skb);
-+		entry->skb = skb_orig;
-+	}
-+	retval = -1;
-+out:
-+	if (unlikely(to_free)) {
-+		kfree_skb_list(to_free);
-+	}
-+	return retval;
-+}
-+static unsigned int imq_nf_hook(void *priv,
-+				struct sk_buff *skb,
-+				const struct nf_hook_state *state)
-+{
-+	return (skb->imq_flags & IMQ_F_ENQUEUE) ? NF_IMQ_QUEUE : NF_ACCEPT;
-+}
-+
-+static int imq_close(struct net_device *dev)
-+{
-+	netif_stop_queue(dev);
-+	return 0;
-+}
-+
-+static int imq_open(struct net_device *dev)
-+{
-+	netif_start_queue(dev);
-+	return 0;
-+}
-+
-+static struct device_type imq_device_type = {
-+	.name = "imq",
-+};
-+
-+static const struct net_device_ops imq_netdev_ops = {
-+	.ndo_open		= imq_open,
-+	.ndo_stop		= imq_close,
-+	.ndo_start_xmit		= imq_dev_xmit,
-+	.ndo_get_stats		= imq_get_stats,
-+};
-+
-+static void imq_setup(struct net_device *dev)
-+{
-+	dev->netdev_ops		= &imq_netdev_ops;
-+	dev->type		= ARPHRD_VOID;
-+	dev->mtu		= 16000; /* too small? */
-+	dev->tx_queue_len	= 11000; /* too big? */
-+	dev->flags		= IFF_NOARP;
-+	dev->features		= NETIF_F_SG | NETIF_F_FRAGLIST |
-+				  NETIF_F_GSO | NETIF_F_HW_CSUM |
-+				  NETIF_F_HIGHDMA;
-+	dev->priv_flags		&= ~(IFF_XMIT_DST_RELEASE |
-+				     IFF_TX_SKB_SHARING);
-+}
-+
-+static int imq_validate(struct nlattr *tb[], struct nlattr *data[],
-+			struct netlink_ext_ack *extack)
-+{
-+	int ret = 0;
-+
-+	if (tb[IFLA_ADDRESS]) {
-+		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
-+			ret = -EINVAL;
-+			goto end;
-+		}
-+		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
-+			ret = -EADDRNOTAVAIL;
-+			goto end;
-+		}
-+	}
-+	return 0;
-+end:
-+	pr_warn("IMQ: imq_validate failed (%d)\n", ret);
-+	return ret;
-+}
-+
-+static struct rtnl_link_ops imq_link_ops __read_mostly = {
-+	.kind		= "imq",
-+	.priv_size	= 0,
-+	.setup		= imq_setup,
-+	.validate	= imq_validate,
-+};
-+
-+static const struct nf_queue_handler imq_nfqh = {
-+	.outfn = imq_nf_queue,
-+};
-+
-+static int __net_init imq_nf_register(struct net *net)
-+{
-+	return nf_register_net_hooks(net, imq_ops,
-+				    ARRAY_SIZE(imq_ops));
-+};
-+
-+static void __net_exit imq_nf_unregister(struct net *net)
-+{
-+	nf_unregister_net_hooks(net, imq_ops,
-+			    ARRAY_SIZE(imq_ops));
-+};
-+
-+static struct pernet_operations imq_net_ops = {
-+	.init		= imq_nf_register,
-+	.exit		= imq_nf_unregister,
-+};
-+
-+static int __net_init imq_init_hooks(void)
-+{
-+	int ret;
-+	nf_register_queue_imq_handler(&imq_nfqh);
-+
-+	ret = register_pernet_subsys(&imq_net_ops);
-+	if (ret < 0)
-+		nf_unregister_queue_imq_handler();
-+
-+	return ret;
-+}
-+
-+#ifdef CONFIG_LOCKDEP
-+	static struct lock_class_key imq_netdev_addr_lock_key;
-+
-+	static void __init imq_dev_set_lockdep_one(struct net_device *dev,
-+				    struct netdev_queue *txq, void *arg)
-+	{
-+	/*
-+	 * the IMQ transmit locks can be taken recursively,
-+	 * for example with one IMQ rule for input- and one for
-+	 * output network devices in iptables!
-+	 * until we find a better solution ignore them.
-+	 */
-+		lockdep_set_novalidate_class(&txq->_xmit_lock);
-+	}
-+
-+	static void imq_dev_set_lockdep_class(struct net_device *dev)
-+		{
-+			lockdep_set_class_and_name(&dev->addr_list_lock,
-+			   			   &imq_netdev_addr_lock_key, "_xmit_addr_IMQ");
-+			netdev_for_each_tx_queue(dev, imq_dev_set_lockdep_one, NULL);
-+}
-+#else
-+	static inline void imq_dev_set_lockdep_class(struct net_device *dev)
-+		{
-+		}
-+#endif
-+
-+static int __init imq_init_one(int index)
-+{
-+	struct net_device *dev;
-+	int ret;
-+
-+	dev = alloc_netdev_mq(0, "imq%d", NET_NAME_UNKNOWN, imq_setup, numqueues);
-+	if (!dev)
-+		return -ENOMEM;
-+
-+	ret = dev_alloc_name(dev, dev->name);
-+	if (ret < 0)
-+		goto fail;
-+
-+	dev->rtnl_link_ops = &imq_link_ops;
-+	SET_NETDEV_DEVTYPE(dev, &imq_device_type);
-+	ret = register_netdevice(dev);
-+	if (ret < 0)
-+		goto fail;
-+
-+	imq_dev_set_lockdep_class(dev);
-+
-+	return 0;
-+fail:
-+	free_netdev(dev);
-+	return ret;
-+}
-+
-+static int __init imq_init_devs(void)
-+{
-+	int err, i;
-+
-+	if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
-+		pr_err("IMQ: numdevs has to be betweed 1 and %u\n",
-+		       IMQ_MAX_DEVS);
-+		return -EINVAL;
-+	}
-+
-+	if (numqueues < 1 || numqueues > IMQ_MAX_QUEUES) {
-+		pr_err("IMQ: numqueues has to be betweed 1 and %u\n",
-+		       IMQ_MAX_QUEUES);
-+		return -EINVAL;
-+	}
-+
-+	get_random_bytes(&imq_hashrnd, sizeof(imq_hashrnd));
-+
-+	rtnl_lock();
-+	err = __rtnl_link_register(&imq_link_ops);
-+
-+	for (i = 0; i < numdevs && !err; i++)
-+		err = imq_init_one(i);
-+
-+	if (err) {
-+		__rtnl_link_unregister(&imq_link_ops);
-+		memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+	}
-+	rtnl_unlock();
-+
-+	return err;
-+}
-+
-+static int __init imq_init_module(void)
-+{
-+	int err;
-+
-+#if defined(CONFIG_IMQ_NUM_DEVS)
-+	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
-+	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
-+	BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
-+#endif
-+
-+	err = imq_init_devs();
-+	if (err) {
-+		pr_err("IMQ: Error trying imq_init_devs(net)\n");
-+		return err;
-+	}
-+
-+	err = imq_init_hooks();
-+	if (err) {
-+		pr_err(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
-+		rtnl_link_unregister(&imq_link_ops);
-+		memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+		return err;
-+	}
-+
-+	pr_info("IMQ driver loaded successfully. (numdevs = %d, numqueues = %d, imq_dev_accurate_stats = %d)\n",
-+		numdevs, numqueues, imq_dev_accurate_stats);
-+
-+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+	pr_info("\tHooking IMQ before NAT on PREROUTING.\n");
-+#else
-+	pr_info("\tHooking IMQ after NAT on PREROUTING.\n");
-+#endif
-+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
-+	pr_info("\tHooking IMQ before NAT on POSTROUTING.\n");
-+#else
-+	pr_info("\tHooking IMQ after NAT on POSTROUTING.\n");
-+#endif
-+
-+	return 0;
-+}
-+
-+static void __exit imq_unhook(void)
-+{
-+	unregister_pernet_subsys(&imq_net_ops);
-+	nf_unregister_queue_imq_handler();
-+}
-+
-+static void __exit imq_cleanup_devs(void)
-+{
-+	rtnl_link_unregister(&imq_link_ops);
-+	memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
-+}
-+
-+static void __exit imq_exit_module(void)
-+{
-+	imq_unhook();
-+	imq_cleanup_devs();
-+	pr_info("IMQ driver unloaded successfully.\n");
-+}
-+
-+module_init(imq_init_module);
-+module_exit(imq_exit_module);
-+
-+module_param(numdevs, int, 0);
-+module_param(numqueues, int, 0);
-+module_param(imq_dev_accurate_stats, int, 0);
-+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
-+MODULE_PARM_DESC(numqueues, "number of queues per IMQ device");
-+MODULE_PARM_DESC(imq_dev_accurate_stats, "Notify if need the accurate imq device stats");
-+
-+MODULE_AUTHOR("https://github.com/imq/linuximq");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_RTNL_LINK("imq");
-diff -purN linux-5.8_org/drivers/net/Kconfig linux-5.8/drivers/net/Kconfig
---- linux-5.8_org/drivers/net/Kconfig	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/drivers/net/Kconfig	2020-08-12 21:08:08.643831110 +0200
-@@ -339,6 +339,125 @@ config RIONET_RX_SIZE
- 	depends on RIONET
- 	default "128"
- 
-+config IMQ
-+	tristate "IMQ (intermediate queueing device) support"
-+	depends on NETDEVICES && NETFILTER
-+	help
-+	  The IMQ device(s) is used as placeholder for QoS queueing
-+	  disciplines. Every packet entering/leaving the IP stack can be
-+	  directed through the IMQ device where it's enqueued/dequeued to the
-+	  attached qdisc. This allows you to treat network devices as classes
-+	  and distribute bandwidth among them. Iptables is used to specify
-+	  through which IMQ device, if any, packets travel.
-+
-+	  More information at: https://github.com/imq/linuximq
-+
-+	  To compile this driver as a module, choose M here: the module
-+	  will be called imq.  If unsure, say N.
-+
-+choice
-+	prompt "IMQ behavior (PRE/POSTROUTING)"
-+	depends on IMQ
-+	default IMQ_BEHAVIOR_AB
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  IMQ can work in any of the following ways:
-+
-+	      PREROUTING   |      POSTROUTING
-+	  -----------------|-------------------
-+	  #1  After NAT    |      After NAT
-+	  #2  After NAT    |      Before NAT
-+	  #3  Before NAT   |      After NAT
-+	  #4  Before NAT   |      Before NAT
-+
-+	  The default behavior is to hook before NAT on PREROUTING
-+	  and after NAT on POSTROUTING (#3).
-+
-+	  This settings are specially usefull when trying to use IMQ
-+	  to shape NATed clients.
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AA
-+	bool "IMQ AA"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   After NAT
-+	  POSTROUTING:  After NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_AB
-+	bool "IMQ AB"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   After NAT
-+	  POSTROUTING:  Before NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BA
-+	bool "IMQ BA"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   Before NAT
-+	  POSTROUTING:  After NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+config IMQ_BEHAVIOR_BB
-+	bool "IMQ BB"
-+	help
-+	  This setting defines how IMQ behaves in respect to its
-+	  hooking in PREROUTING and POSTROUTING.
-+
-+	  Choosing this option will make IMQ hook like this:
-+
-+	  PREROUTING:   Before NAT
-+	  POSTROUTING:  Before NAT
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
-+endchoice
-+
-+config IMQ_NUM_DEVS
-+	int "Number of IMQ devices"
-+	range 2 16
-+	depends on IMQ
-+	default "16"
-+	help
-+	  This setting defines how many IMQ devices will be created.
-+
-+	  The default value is 16.
-+
-+	  More information can be found at: https://github.com/imq/linuximq
-+
-+	  If not sure leave the default settings alone.
-+
- config TUN
- 	tristate "Universal TUN/TAP device driver support"
- 	depends on INET
-diff -purN linux-5.8_org/drivers/net/Makefile linux-5.8/drivers/net/Makefile
---- linux-5.8_org/drivers/net/Makefile	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/drivers/net/Makefile	2020-08-12 21:08:08.643831110 +0200
-@@ -14,6 +14,7 @@ obj-$(CONFIG_WIREGUARD) += wireguard/
- obj-$(CONFIG_EQUALIZER) += eql.o
- obj-$(CONFIG_IFB) += ifb.o
- obj-$(CONFIG_MACSEC) += macsec.o
-+obj-$(CONFIG_IMQ) += imq.o
- obj-$(CONFIG_MACVLAN) += macvlan.o
- obj-$(CONFIG_MACVTAP) += macvtap.o
- obj-$(CONFIG_MII) += mii.o
-diff -purN linux-5.8_org/include/linux/imq.h linux-5.8/include/linux/imq.h
---- linux-5.8_org/include/linux/imq.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.8/include/linux/imq.h	2020-08-12 21:08:08.643831110 +0200
-@@ -0,0 +1,13 @@
-+#ifndef _IMQ_H
-+#define _IMQ_H
-+
-+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
-+#define IMQ_F_BITS	5
-+
-+#define IMQ_F_IFMASK	0x0f
-+#define IMQ_F_ENQUEUE	0x10
-+
-+#define IMQ_MAX_DEVS	(IMQ_F_IFMASK + 1)
-+
-+#endif /* _IMQ_H */
-+
-diff -purN linux-5.8_org/include/linux/netdevice.h linux-5.8/include/linux/netdevice.h
---- linux-5.8_org/include/linux/netdevice.h	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/include/linux/netdevice.h	2020-08-12 21:08:08.647831063 +0200
-@@ -1998,6 +1998,11 @@ struct net_device {
- /*
-  * Cache lines mostly used on receive path (including eth_type_trans())
-  */
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	unsigned long		last_rx;
-+#endif
-+
- 	/* Interface address info used in eth_type_trans() */
- 	unsigned char		*dev_addr;
- 
-@@ -4216,6 +4221,19 @@ static inline void netif_tx_unlock_bh(st
- 	}						\
- }
- 
-+#define HARD_TX_LOCK_BH(dev, txq) {           \
-+    if ((dev->features & NETIF_F_LLTX) == 0) {  \
-+        __netif_tx_lock_bh(txq);      \
-+    }                       \
-+}
-+
-+#define HARD_TX_UNLOCK_BH(dev, txq) {          \
-+    if ((dev->features & NETIF_F_LLTX) == 0) {  \
-+        __netif_tx_unlock_bh(txq);         \
-+    }                       \
-+}
-+
-+
- static inline void netif_tx_disable(struct net_device *dev)
- {
- 	unsigned int i;
-diff -purN linux-5.8_org/include/linux/netfilter/xt_IMQ.h linux-5.8/include/linux/netfilter/xt_IMQ.h
---- linux-5.8_org/include/linux/netfilter/xt_IMQ.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.8/include/linux/netfilter/xt_IMQ.h	2020-08-12 21:08:08.647831063 +0200
-@@ -0,0 +1,9 @@
-+#ifndef _XT_IMQ_H
-+#define _XT_IMQ_H
-+
-+struct xt_imq_info {
-+	unsigned int todev;     /* target imq device */
-+};
-+
-+#endif /* _XT_IMQ_H */
-+
-diff -purN linux-5.8_org/include/linux/netfilter_ipv4/ipt_IMQ.h linux-5.8/include/linux/netfilter_ipv4/ipt_IMQ.h
---- linux-5.8_org/include/linux/netfilter_ipv4/ipt_IMQ.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.8/include/linux/netfilter_ipv4/ipt_IMQ.h	2020-08-12 21:08:08.647831063 +0200
-@@ -0,0 +1,10 @@
-+#ifndef _IPT_IMQ_H
-+#define _IPT_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ipt_imq_info xt_imq_info
-+
-+#endif /* _IPT_IMQ_H */
-+
-diff -purN linux-5.8_org/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-5.8/include/linux/netfilter_ipv6/ip6t_IMQ.h
---- linux-5.8_org/include/linux/netfilter_ipv6/ip6t_IMQ.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.8/include/linux/netfilter_ipv6/ip6t_IMQ.h	2020-08-12 21:08:08.647831063 +0200
-@@ -0,0 +1,10 @@
-+#ifndef _IP6T_IMQ_H
-+#define _IP6T_IMQ_H
-+
-+/* Backwards compatibility for old userspace */
-+#include <linux/netfilter/xt_IMQ.h>
-+
-+#define ip6t_imq_info xt_imq_info
-+
-+#endif /* _IP6T_IMQ_H */
-+
-diff -purN linux-5.8_org/include/linux/skbuff.h linux-5.8/include/linux/skbuff.h
---- linux-5.8_org/include/linux/skbuff.h	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/include/linux/skbuff.h	2020-08-12 21:08:08.647831063 +0200
-@@ -40,6 +40,9 @@
- #if IS_ENABLED(CONFIG_NF_CONNTRACK)
- #include <linux/netfilter/nf_conntrack_common.h>
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- 
- /* The interface for checksum offload between the stack and networking drivers
-  * is as follows...
-@@ -744,6 +747,9 @@ struct sk_buff {
- 	 * first. This is owned by whoever has the skb queued ATM.
- 	 */
- 	char			cb[48] __aligned(8);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	void			*cb_next;
-+#endif
- 
- 	union {
- 		struct {
-@@ -756,6 +762,9 @@ struct sk_buff {
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
- 	unsigned long		 _nfct;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	struct nf_queue_entry *nf_queue_entry;
-+#endif
- 	unsigned int		len,
- 				data_len;
- 	__u16			mac_len,
-@@ -845,6 +854,9 @@ struct sk_buff {
- 	__u8			offload_fwd_mark:1;
- 	__u8			offload_l3_fwd_mark:1;
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	__u8			imq_flags:IMQ_F_BITS;
-+#endif
- #ifdef CONFIG_NET_CLS_ACT
- 	__u8			tc_skip_classify:1;
- 	__u8			tc_at_ingress:1;
-@@ -1057,6 +1069,10 @@ void skb_tx_error(struct sk_buff *skb);
- void consume_skb(struct sk_buff *skb);
- void __consume_stateless_skb(struct sk_buff *skb);
- void  __kfree_skb(struct sk_buff *skb);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+int skb_save_cb(struct sk_buff *skb);
-+int skb_restore_cb(struct sk_buff *skb);
-+#endif
- extern struct kmem_cache *skbuff_head_cache;
- 
- void kfree_skb_partial(struct sk_buff *skb, bool head_stolen);
-@@ -4257,6 +4273,10 @@ static inline void __nf_copy(struct sk_b
- 	dst->_nfct = src->_nfct;
- 	nf_conntrack_get(skb_nfct(src));
- #endif
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	dst->imq_flags = src->imq_flags;
-+	dst->nf_queue_entry = src->nf_queue_entry;
-+#endif
- #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
- 	if (copy)
- 		dst->nf_trace = src->nf_trace;
-diff -purN linux-5.8_org/include/net/netfilter/nf_queue.h linux-5.8/include/net/netfilter/nf_queue.h
---- linux-5.8_org/include/net/netfilter/nf_queue.h	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/include/net/netfilter/nf_queue.h	2020-08-22 21:09:43.290601818 +0200
-@@ -40,6 +40,11 @@ void nf_reinject(struct nf_queue_entry *
- void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
- void nf_queue_entry_free(struct nf_queue_entry *entry);
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
-+void nf_unregister_queue_imq_handler(void);
-+#endif
-+
- static inline void init_hashrandom(u32 *jhash_initval)
- {
- 	while (*jhash_initval == 0)
-diff -purN linux-5.8_org/include/net/pkt_sched.h linux-5.8/include/net/pkt_sched.h
---- linux-5.8_org/include/net/pkt_sched.h	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/include/net/pkt_sched.h	2020-08-12 21:08:08.647831063 +0200
-@@ -123,6 +123,8 @@ bool sch_direct_xmit(struct sk_buff *skb
- 
- void __qdisc_run(struct Qdisc *q);
- 
-+struct sk_buff *qdisc_dequeue_skb(struct Qdisc *q, bool *validate);
-+
- static inline void qdisc_run(struct Qdisc *q)
- {
- 	if (qdisc_run_begin(q)) {
-diff -purN linux-5.8_org/include/net/sch_generic.h linux-5.8/include/net/sch_generic.h
---- linux-5.8_org/include/net/sch_generic.h	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/include/net/sch_generic.h	2020-08-12 21:08:08.651831016 +0200
-@@ -795,6 +795,13 @@ static inline int qdisc_enqueue(struct s
- 	return sch->enqueue(skb, sch, to_free);
- }
- 
-+static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch,
-+				      struct sk_buff **to_free)
-+{
-+    qdisc_skb_cb(skb)->pkt_len = skb->len;
-+    return qdisc_enqueue(skb, sch, to_free) & NET_XMIT_MASK;
-+}
-+
- static inline void _bstats_update(struct gnet_stats_basic_packed *bstats,
- 				  __u64 bytes, __u32 packets)
- {
-diff -purN linux-5.8_org/include/uapi/linux/netfilter.h linux-5.8/include/uapi/linux/netfilter.h
---- linux-5.8_org/include/uapi/linux/netfilter.h	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/include/uapi/linux/netfilter.h	2020-08-12 21:08:08.651831016 +0200
-@@ -14,7 +14,8 @@
- #define NF_QUEUE 3
- #define NF_REPEAT 4
- #define NF_STOP 5	/* Deprecated, for userspace nf_queue compatibility. */
--#define NF_MAX_VERDICT NF_STOP
-+#define NF_IMQ_QUEUE 6
-+#define NF_MAX_VERDICT NF_IMQ_QUEUE
- 
- /* we overload the higher bits for encoding auxiliary data such as the queue
-  * number or errno values. Not nice, but better than additional function
-diff -purN linux-5.8_org/net/core/dev.c linux-5.8/net/core/dev.c
---- linux-5.8_org/net/core/dev.c	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/core/dev.c	2020-08-12 21:08:08.651831016 +0200
-@@ -138,6 +138,9 @@
- #include <linux/hrtimer.h>
- #include <linux/netfilter_ingress.h>
- #include <linux/crash_dump.h>
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+#include <linux/imq.h>
-+#endif
- #include <linux/sctp.h>
- #include <net/udp_tunnel.h>
- #include <linux/net_namespace.h>
-@@ -3548,6 +3551,13 @@ static int xmit_one(struct sk_buff *skb,
- 	unsigned int len;
- 	int rc;
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	if ((!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) &&
-+		!(skb->imq_flags & IMQ_F_ENQUEUE))
-+#else
-+	if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
-+#endif
-+
- 	if (dev_nit_active(dev))
- 		dev_queue_xmit_nit(skb, dev);
- 
-@@ -3587,6 +3597,8 @@ out:
- 	return skb;
- }
- 
-+EXPORT_SYMBOL_GPL(dev_hard_start_xmit);
-+
- static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb,
- 					  netdev_features_t features)
- {
-diff -purN linux-5.8_org/net/core/skbuff.c linux-5.8/net/core/skbuff.c
---- linux-5.8_org/net/core/skbuff.c	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/core/skbuff.c	2020-08-12 21:08:08.651831016 +0200
-@@ -87,6 +87,56 @@ static struct kmem_cache *skbuff_ext_cac
- int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
- EXPORT_SYMBOL(sysctl_max_skb_frags);
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
-+
-+/* Control buffer save/restore for IMQ devices */
-+struct skb_cb_table {
-+	char			cb[48] __aligned(8);
-+	void			*cb_next;
-+};
-+
-+int skb_save_cb(struct sk_buff *skb)
-+{
-+	struct skb_cb_table *next;
-+
-+	next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
-+	if (!next)
-+		return -ENOMEM;
-+
-+	BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+	memcpy(next->cb, skb->cb, sizeof(skb->cb));
-+	next->cb_next = skb->cb_next;
-+	skb->cb_next = next;
-+	smp_wmb();
-+
-+	return 0;
-+}
-+EXPORT_SYMBOL(skb_save_cb);
-+
-+int skb_restore_cb(struct sk_buff *skb)
-+{
-+	struct skb_cb_table *next;
-+
-+	if (!skb->cb_next)
-+		return 0;
-+
-+	next = skb->cb_next;
-+
-+	BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
-+
-+	memcpy(skb->cb, next->cb, sizeof(skb->cb));
-+	skb->cb_next = next->cb_next;
-+	smp_wmb();
-+
-+	kmem_cache_free(skbuff_cb_store_cache, next);
-+
-+	return 0;
-+}
-+EXPORT_SYMBOL(skb_restore_cb);
-+#endif
-+
- /**
-  *	skb_panic - private function for out-of-line support
-  *	@skb:	buffer
-@@ -650,6 +700,28 @@ void skb_release_head_state(struct sk_bu
- 		WARN_ON(in_irq());
- 		skb->destructor(skb);
- 	}
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	/*
-+	 * This should not happen. When it does, avoid memleak by restoring
-+	 * the chain of cb-backups.
-+	 */
-+	while (skb->cb_next != NULL) {
-+		if (net_ratelimit())
-+			pr_warn("IMQ: kfree_skb: skb->cb_next: %08x\n",
-+				(unsigned int)(uintptr_t)skb->cb_next);
-+
-+		skb_restore_cb(skb);
-+	}
-+	/*
-+	 * This should not happen either, nf_queue_entry is nullified in
-+	 * imq_dev_xmit(). If we have non-NULL nf_queue_entry then we are
-+	 * leaking entry pointers, maybe memory. We don't know if this is
-+	 * pointer to already freed memory, or should this be freed.
-+	 * If this happens we need to add refcounting, etc for nf_queue_entry.
-+	 */
-+	if (skb->nf_queue_entry && net_ratelimit())
-+		pr_warn("%s\n", "IMQ: kfree_skb: skb->nf_queue_entry != NULL");
-+#endif
- #if IS_ENABLED(CONFIG_NF_CONNTRACK)
- 	nf_conntrack_put(skb_nfct(skb));
- #endif
-@@ -934,6 +1006,9 @@ static void __copy_skb_header(struct sk_
- 	skb_dst_copy(new, old);
- 	__skb_ext_copy(new, old);
- 	__nf_copy(new, old, false);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	new->cb_next = NULL;
-+#endif
- 
- 	/* Note : this field could be in headers_start/headers_end section
- 	 * It is not yet because we do not want to have a 16 bit hole
-@@ -4257,6 +4332,13 @@ void __init skb_init(void)
- 						0,
- 						SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- 						NULL);
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
-+						sizeof(struct skb_cb_table),
-+						0,
-+						SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-+						NULL);
-+#endif
- 	skb_extensions_init();
- }
- 
-diff -purN linux-5.8_org/net/netfilter/core.c linux-5.8/net/netfilter/core.c
---- linux-5.8_org/net/netfilter/core.c	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/netfilter/core.c	2020-08-12 21:08:08.651831016 +0200
-@@ -519,6 +519,11 @@ int nf_hook_slow(struct sk_buff *skb, st
- 			if (ret == 0)
- 				ret = -EPERM;
- 			return ret;
-+		case NF_IMQ_QUEUE:
-+			ret = nf_queue(skb, state, s, verdict);
-+			if (ret == -ECANCELED)
-+				continue;
-+			return ret;
- 		case NF_QUEUE:
- 			ret = nf_queue(skb, state, s, verdict);
- 			if (ret == 1)
-diff -purN linux-5.8_org/net/netfilter/Kconfig linux-5.8/net/netfilter/Kconfig
---- linux-5.8_org/net/netfilter/Kconfig	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/netfilter/Kconfig	2020-08-12 21:08:08.651831016 +0200
-@@ -921,6 +921,18 @@ config NETFILTER_XT_TARGET_LOG
- 
- 	  To compile it as a module, choose M here.  If unsure, say N.
- 
-+config NETFILTER_XT_TARGET_IMQ
-+        tristate '"IMQ" target support'
-+	depends on NETFILTER_XTABLES
-+	depends on IP_NF_MANGLE || IP6_NF_MANGLE
-+	select IMQ
-+	default m if NETFILTER_ADVANCED=n
-+        help
-+          This option adds a `IMQ' target which is used to specify if and
-+          to which imq device packets should get enqueued/dequeued.
-+
-+          To compile it as a module, choose M here.  If unsure, say N.
-+
- config NETFILTER_XT_TARGET_MARK
- 	tristate '"MARK" target support'
- 	depends on NETFILTER_ADVANCED
-diff -purN linux-5.8_org/net/netfilter/Makefile linux-5.8/net/netfilter/Makefile
---- linux-5.8_org/net/netfilter/Makefile	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/netfilter/Makefile	2020-08-12 21:08:08.655830969 +0200
-@@ -147,6 +147,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) +=
- obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
-+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
- obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o
-diff -purN linux-5.8_org/net/netfilter/nf_queue.c linux-5.8/net/netfilter/nf_queue.c
---- linux-5.8_org/net/netfilter/nf_queue.c	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/netfilter/nf_queue.c	2020-08-12 21:08:08.655830969 +0200
-@@ -29,6 +29,23 @@
-  * receives, no matter what.
-  */
- 
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+static const struct nf_queue_handler __rcu *queue_imq_handler __read_mostly;
-+
-+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
-+{
-+	rcu_assign_pointer(queue_imq_handler, qh);
-+}
-+EXPORT_SYMBOL_GPL(nf_register_queue_imq_handler);
-+
-+void nf_unregister_queue_imq_handler(void)
-+{
-+	RCU_INIT_POINTER(queue_imq_handler, NULL);
-+	synchronize_rcu();
-+}
-+EXPORT_SYMBOL_GPL(nf_unregister_queue_imq_handler);
-+#endif
-+
- /* return EBUSY when somebody else is registered, return EEXIST if the
-  * same handler is registered, return 0 in case of success. */
- void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh)
-@@ -153,16 +170,28 @@ static void nf_ip6_saveroute(const struc
- }
- 
- static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
--		      unsigned int index, unsigned int queuenum)
-+		      unsigned int index, unsigned int verdict)
- {
- 	struct nf_queue_entry *entry = NULL;
- 	const struct nf_queue_handler *qh;
- 	struct net *net = state->net;
- 	unsigned int route_key_size;
-+	unsigned int queuetype = verdict & NF_VERDICT_MASK;
-+	unsigned int queuenum  = verdict >> NF_VERDICT_QBITS;
- 	int status;
- 
- 	/* QUEUE == DROP if no one is waiting, to be safe. */
--	qh = rcu_dereference(net->nf.queue_handler);
-+	if (queuetype == NF_IMQ_QUEUE) {
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	qh = rcu_dereference(queue_imq_handler);
-+#else
-+	BUG();
-+	goto err_unlock;
-+#endif
-+	} else {
-+		qh = rcu_dereference(net->nf.queue_handler);
-+	}
-+
- 	if (!qh)
- 		return -ESRCH;
- 
-@@ -222,8 +251,16 @@ int nf_queue(struct sk_buff *skb, struct
- {
- 	int ret;
- 
--	ret = __nf_queue(skb, state, index, verdict >> NF_VERDICT_QBITS);
-+	ret = __nf_queue(skb, state, index, verdict);
- 	if (ret < 0) {
-+
-+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
-+	/* IMQ Bypass */
-+	if (ret == -ECANCELED && skb->imq_flags == 0) {
-+		return 1;
-+	}
-+#endif
-+
- 		if (ret == -ESRCH &&
- 		    (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
- 			return 1;
-@@ -326,6 +363,7 @@ next_hook:
- 		local_bh_enable();
- 		break;
- 	case NF_QUEUE:
-+	case NF_IMQ_QUEUE:
- 		err = nf_queue(skb, &entry->state, i, verdict);
- 		if (err == 1)
- 			goto next_hook;
-diff -purN linux-5.8_org/net/netfilter/xt_IMQ.c linux-5.8/net/netfilter/xt_IMQ.c
---- linux-5.8_org/net/netfilter/xt_IMQ.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-5.8/net/netfilter/xt_IMQ.c	2020-08-12 21:08:08.655830969 +0200
-@@ -0,0 +1,72 @@
-+/*
-+ * This target marks packets to be enqueued to an imq device
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <linux/netfilter/x_tables.h>
-+#include <linux/netfilter/xt_IMQ.h>
-+#include <linux/imq.h>
-+
-+static unsigned int imq_target(struct sk_buff *pskb,
-+				const struct xt_action_param *par)
-+{
-+	const struct xt_imq_info *mr = par->targinfo;
-+
-+	pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
-+
-+	return XT_CONTINUE;
-+}
-+
-+static int imq_checkentry(const struct xt_tgchk_param *par)
-+{
-+	struct xt_imq_info *mr = par->targinfo;
-+
-+	if (mr->todev > IMQ_MAX_DEVS - 1) {
-+		pr_warn("IMQ: invalid device specified, highest is %u\n",
-+			IMQ_MAX_DEVS - 1);
-+		return -EINVAL;
-+	}
-+
-+	return 0;
-+}
-+
-+static struct xt_target xt_imq_reg[] __read_mostly = {
-+	{
-+		.name           = "IMQ",
-+		.family		= AF_INET,
-+		.checkentry     = imq_checkentry,
-+		.target         = imq_target,
-+		.targetsize	= sizeof(struct xt_imq_info),
-+		.table		= "mangle",
-+		.me             = THIS_MODULE
-+	},
-+	{
-+		.name           = "IMQ",
-+		.family		= AF_INET6,
-+		.checkentry     = imq_checkentry,
-+		.target         = imq_target,
-+		.targetsize	= sizeof(struct xt_imq_info),
-+		.table		= "mangle",
-+		.me             = THIS_MODULE
-+	},
-+};
-+
-+static int __init imq_init(void)
-+{
-+	return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+static void __exit imq_fini(void)
-+{
-+	xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
-+}
-+
-+module_init(imq_init);
-+module_exit(imq_fini);
-+
-+MODULE_AUTHOR("https://github.com/imq/linuximq");
-+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information.");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("ipt_IMQ");
-+MODULE_ALIAS("ip6t_IMQ");
-+
-diff -purN linux-5.8_org/net/sched/sch_generic.c linux-5.8/net/sched/sch_generic.c
---- linux-5.8_org/net/sched/sch_generic.c	2020-08-02 23:21:45.000000000 +0200
-+++ linux-5.8/net/sched/sch_generic.c	2020-08-12 21:08:08.655830969 +0200
-@@ -273,6 +273,14 @@ trace:
- 	return skb;
- }
- 
-+struct sk_buff *qdisc_dequeue_skb(struct Qdisc *q, bool *validate)
-+{
-+	int packets;
-+
-+	return dequeue_skb(q, validate, &packets);
-+}
-+EXPORT_SYMBOL(qdisc_dequeue_skb);
-+
- /*
-  * Transmit possibly several skbs, and handle the return status as
-  * required. Owning running seqcount bit guarantees that
Index: npl/kernel/linux_src/linux_src.SlackBuild
===================================================================
--- npl/kernel/linux_src/linux_src.SlackBuild	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ npl/kernel/linux_src/linux_src.SlackBuild	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -1,5 +1,4 @@
 #!/bin/bash
 #NEED:ncurses_dev
-#DEP:openssl
 
 NAME=linux_src
@@ -15,10 +14,10 @@
 
 #unpack basic kernel and apply all incremental patches
-tar -xf $CWD/linux-5.14.tar.xz || exit 1
+tar -xf $CWD/linux-4.4.tar.xz || exit 1
 cd linux-* || exit 1
 #if you want to create a newer kernel: just download newest patches, and increase patchlevel
-#also increase .major file to trigger rebuilds!
-PATCHLEVEL=12
-VER=5.14.$PATCHLEVEL
+#Also increase the linux_src.major number, so everything that depends on linux_src is rebuilded.
+PATCHLEVEL=33
+VER=4.4.$PATCHLEVEL
 #bunzip2 $CWD/patch-$VER.bz2 || exit 1
 #gunzip $CWD/patch-$VER.gz || exit 1
@@ -44,11 +43,5 @@
 #patch -p1 < $CWD/fbcondecor-3.14b.patch || exit 1
 #patch -F3 -p1 < $CWD/fbcondecor-3.15.patch || exit 1
-#patch  -p1 < $CWD/fbcondecor-3.19.patch || exit 1
-
-#from https://dev.gentoo.org/~mpagano/genpatches/patches-4.9-143.html
-#https://dev.gentoo.org/~mpagano/genpatches/patches-4.14-182.html
-#patch  -F3 -p1 < $CWD/4200_fbcondecor.patch || exit 1
-#from https://raw.githubusercontent.com/jirka-grunt/fbcondecor/master/fbcondecor-5.10.patch
-#patch   -p1 < $CWD/fbcondecor-5.10.patch || exit 1
+patch  -p1 < $CWD/fbcondecor-3.19.patch || exit 1
 
 
@@ -58,10 +51,5 @@
 #patch -p1 -F3 < $CWD/linux-3.13-imq.diff || exit 1
 #patch -p1 -F3 < $CWD/linux-3.13.10_hardened_gentoo.diff || exit 1
-#patch -p1  < $CWD/linux-4.4.5-imq.diff || exit 1
-#patch -p1  < $CWD/linux-4.9-imq.diff || exit 1
-#from https://raw.githubusercontent.com/imq/linuximq/master/kernel/v4.x/linux-4.14-imq.diff
-#patch -p1  < $CWD/linux-4.14-imq.diff || exit 1
-#from https://raw.githubusercontent.com/imq/linuximq/master/kernel/v5.x/linux-5.9-imq.patch
-#patch -p1 < $CWD/linux-5.9-imq.patch || exit 1
+patch -p1  < $CWD/linux-4.4.5-imq.diff || exit 1
 
 
Index: npl/kernel/linux_src/linux_src.build
===================================================================
--- npl/kernel/linux_src/linux_src.build	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ 	(revision )
@@ -1,1 +1,0 @@
-6591
Index: npl/kernel/linux_src/linux_src.depver
===================================================================
--- npl/kernel/linux_src/linux_src.depver	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ 	(revision )
@@ -1,1 +1,0 @@
-openssl	5
Index: npl/kernel/linux_src/linux_src.major
===================================================================
--- npl/kernel/linux_src/linux_src.major	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ npl/kernel/linux_src/linux_src.major	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -1,2 +1,2 @@
-5140120005
+404033004
 
Index: npl/kernel/linux_src/linux_src.md5
===================================================================
--- npl/kernel/linux_src/linux_src.md5	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ npl/kernel/linux_src/linux_src.md5	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -1,15 +1,12 @@
-8e12dfcbf36f937747e1fb36b115c14b  ./4200_fbcondecor.patch
-37312241e4d0ddaaed1db8ce6a9449a1  ./config
-580fdf2704779952beee1c84784ec5d4  ./configsyn3
-f7dc68ab549b1ba378cf83ec574fa724  ./fbcondecor-5.10.patch
-914a5254c91f2564a7654c2180f4e911  ./linux-4.14-imq.diff
-bacdb9ffdcd922aa069a5e1520160e24  ./linux-4.14.tar.xz
-753adc474bf799d569dec4f165ed92c3  ./linux-5.10.tar.xz
-a082ef5748b813abca0649dab8be5f52  ./linux-5.14.tar.xz
-72e4cc0000ef96e1c1766f1f231e79d1  ./linux-5.9-imq.patch
-b2bcb6b88cfbb62b02ffd90bf7cde7b3  ./linux_src.pkg
-f49c6e36d588a59bdf266ceadf8d7928  ./linux_src.SlackBuild
-a1db499e53ccc4cb23f6bb6cb30a3be6  ./linux_src.SlackBuild.log.gz
-67928983c499e1bca70005677c119765  ./patch-4.14.206.xz
-abe6c2e8f921432bb73be0d6bdb5e791  ./patch-5.10.73.xz
-f6951f77178db6beaf48cfa9ad662739  ./patch-5.14.12.xz
+017c99ede49e47e606a889dffe7e23ab  ./config
+d55f716a0835a3f00b557466008b9293  ./fbcondecor-3.15.patch
+8b7ca23aa660578023a0a244ae235888  ./fbcondecor-3.19.patch
+467d0a59ae2bfe466a370d65768b8ace  ./linux-4.4.5-imq.diff
+099c7494932ef49edf6a3ac4c50e8d38  ./linux-4.4-imq.diff
+9a78fa2eb6c68ca5a40ed5af08142599  ./linux-4.4.tar.xz
+61c5bb69b49cd98c614165e3c1768ed4  ./linux_src.pkg
+1ae17eb0b9c74977bcb0d29d7114a2f0  ./linux_src.SlackBuild
+7aa7fbdbf97b2fc15c45f225b06e57d1  ./linux_src.SlackBuild.log.gz
+91b0fc0919b520a647e2d3ba60b77254  ./patch-4.4.31.xz
+394f1ad7f950428eaed011f2e6d36060  ./patch-4.4.32.xz
+eae23d12c918b5b8fa6baa88d53ff2b7  ./patch-4.4.33.xz
Index: npl/kernel/linux_src/linux_src.version
===================================================================
--- npl/kernel/linux_src/linux_src.version	(revision 26ffad77000ead3839f0b4ca05a51545ff3ac867)
+++ npl/kernel/linux_src/linux_src.version	(revision c5c522c7ca74a4c1725ca5e3fe0bdcadff80e49a)
@@ -1,1 +1,1 @@
-5.14.12_bigmem_syn3
+4.4.33_bigmem_syn3
