diff -ruw linux-6.4/Makefile linux-6.4-fbx/Makefile
--- linux-6.4/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/Makefile	2024-03-08 11:55:17.847155822 +0100
@@ -386,6 +386,8 @@
 # CROSS_COMPILE can be set on the command line
 # make CROSS_COMPILE=ia64-linux-
 # Alternatively CROSS_COMPILE can be set in the environment.
+# A third alternative is to store a setting in .config so that plain
+# "make" in the configured kernel build directory always uses that.
 # Default value for CROSS_COMPILE is not to prefix executables
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 ARCH		?= $(SUBARCH)
@@ -423,6 +425,9 @@
 KCONFIG_CONFIG	?= .config
 export KCONFIG_CONFIG
 
+CONFIG_CROSS_COMPILE := $(shell grep ^CONFIG_CROSS_COMPILE= $(KCONFIG_CONFIG) | cut -f 2 -d = | tr -d '"')
+CROSS_COMPILE	?= $(CONFIG_CROSS_COMPILE:"%"=%)
+
 # SHELL used by kbuild
 CONFIG_SHELL := sh
 
@@ -1366,7 +1371,7 @@
 quiet_cmd_headers_install = INSTALL $(INSTALL_HDR_PATH)/include
       cmd_headers_install = \
 	mkdir -p $(INSTALL_HDR_PATH); \
-	rsync -mrl --include='*/' --include='*\.h' --exclude='*' \
+	rsync -cmrl --include='*/' --include='*\.h' --exclude='*' \
 	usr/include $(INSTALL_HDR_PATH)
 
 PHONY += headers_install
diff -ruw linux-6.4/arch/x86/Kconfig linux-6.4-fbx/arch/x86/Kconfig
--- linux-6.4/arch/x86/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/Kconfig	2024-03-08 11:55:17.847155822 +0100
@@ -613,6 +613,11 @@
 	  This option compiles in support for the CE4100 SOC for settop
 	  boxes and media devices.
 
+config FBX6HD
+	bool "Freebox 6HD support"
+	depends on X86_INTEL_CE
+	select ARCH_HAS_FBXSERIAL
+
 config X86_INTEL_MID
 	bool "Intel MID platform support"
 	depends on X86_EXTENDED_PLATFORM
@@ -3074,4 +3079,5 @@
 
 source "arch/x86/kvm/Kconfig"
 
+
 source "arch/x86/Kconfig.assembler"
diff -ruw linux-6.4/arch/x86/boot/compressed/Makefile linux-6.4-fbx/arch/x86/boot/compressed/Makefile
--- linux-6.4/arch/x86/boot/compressed/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/boot/compressed/Makefile	2023-11-29 17:07:06.901650953 +0100
@@ -90,6 +90,7 @@
 	$(call if_changed,voffset)
 
 $(obj)/misc.o: $(obj)/../voffset.h
+$(obj)/head_$(BITS).o: $(obj)/../voffset.h
 
 vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/kernel_info.o $(obj)/head_$(BITS).o \
 	$(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/error.o \
diff -ruw linux-6.4/arch/x86/boot/compressed/head_32.S linux-6.4-fbx/arch/x86/boot/compressed/head_32.S
--- linux-6.4/arch/x86/boot/compressed/head_32.S	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/boot/compressed/head_32.S	2023-11-29 17:07:06.901650953 +0100
@@ -31,6 +31,7 @@
 #include <asm/boot.h>
 #include <asm/asm-offsets.h>
 #include <asm/bootparam.h>
+#include "../voffset.h"
 
 /*
  * These symbols needed to be marked as .hidden to prevent the BFD linker from
@@ -110,7 +111,18 @@
 
 	movl	%ebx, %ebp	// Save the output address for later
 	/* Target address to relocate to for decompression */
+#ifdef CONFIG_FBX6HD
+	/*
+	* uboot does not copy this field from boot params, so just
+	* hardcode the value that is put into the boot header.
+	*
+	* zoffset.h is not generated, ignore it and assume
+	* uncompressed kernel is larger than compressed one
+	*/
+	movl    $(VO__end - VO__text), %ebx
+#else
 	addl    BP_init_size(%esi), %ebx
+#endif
 	subl    $_end@GOTOFF, %ebx
 
 	/* Set up the stack */
diff -ruw linux-6.4/arch/x86/boot/early_serial_console.c linux-6.4-fbx/arch/x86/boot/early_serial_console.c
--- linux-6.4/arch/x86/boot/early_serial_console.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/boot/early_serial_console.c	2020-02-08 00:30:16.492453337 +0100
@@ -29,11 +29,17 @@
 	unsigned divisor;
 
 	outb(0x3, port + LCR);	/* 8n1 */
+#ifndef CONFIG_X86_INTEL_CE
 	outb(0, port + IER);	/* no interrupt */
+#endif
 	outb(0, port + FCR);	/* no fifo */
 	outb(0x3, port + MCR);	/* DTR + RTS */
 
+#ifdef CONFIG_X86_INTEL_CE
+	divisor	= 921600 / baud;
+#else
 	divisor	= 115200 / baud;
+#endif
 	c = inb(port + LCR);
 	outb(c | DLAB, port + LCR);
 	outb(divisor & 0xff, port + DLL);
diff -ruw linux-6.4/arch/x86/include/asm/elf.h linux-6.4-fbx/arch/x86/include/asm/elf.h
--- linux-6.4/arch/x86/include/asm/elf.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/include/asm/elf.h	2023-11-29 17:07:06.938317676 +0100
@@ -271,7 +271,7 @@
  * ELF:                 |            |                  |                |
  * ---------------------|------------|------------------|----------------|
  * missing PT_GNU_STACK | exec-all   | exec-all         | exec-none      |
- * PT_GNU_STACK == RWX  | exec-stack | exec-stack       | exec-stack     |
+ * PT_GNU_STACK == RWX  | exec-stack | exec-all         | exec-stack     |
  * PT_GNU_STACK == RW   | exec-none  | exec-none        | exec-none      |
  *
  *  exec-all  : all PROT_READ user mappings are executable, except when
@@ -286,7 +286,7 @@
  *
  */
 #define elf_read_implies_exec(ex, executable_stack)	\
-	(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
+	(mmap_is_ia32() && executable_stack != EXSTACK_DISABLE_X)
 
 struct task_struct;
 
diff -ruw linux-6.4/arch/x86/include/asm/string_32.h linux-6.4-fbx/arch/x86/include/asm/string_32.h
--- linux-6.4/arch/x86/include/asm/string_32.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/include/asm/string_32.h	2023-11-29 17:07:06.954984369 +0100
@@ -147,7 +147,14 @@
 
 #ifndef CONFIG_FORTIFY_SOURCE
 
+#if (__GNUC__ >= 4 && !defined(CONFIG_X86_INTEL_CE))
 #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
+#else
+#define memcpy(t, f, n)				\
+	(__builtin_constant_p((n))		\
+	 ? __constant_memcpy((t), (f), (n))	\
+	 : __memcpy((t), (f), (n)))
+#endif
 
 #endif /* !CONFIG_FORTIFY_SOURCE */
 
@@ -176,6 +183,29 @@
 /* we might want to write optimized versions of these later */
 #define __constant_count_memset(s, c, count) __memset_generic((s), (c), (count))
 
+/*
+ * memset(x, 0, y) is a reasonably common thing to do, so we want to fill
+ * things 32 bits at a time even when we don't know the size of the
+ * area at compile-time..
+ */
+static __always_inline
+void *__constant_c_memset(void *s, unsigned long c, size_t count)
+{
+	int d0, d1;
+	asm volatile("rep ; stosl\n\t"
+		     "testb $2,%b3\n\t"
+		     "je 1f\n\t"
+		     "stosw\n"
+		     "1:\ttestb $1,%b3\n\t"
+		     "je 2f\n\t"
+		     "stosb\n"
+		     "2:"
+		     : "=&c" (d0), "=&D" (d1)
+		     : "a" (c), "q" (count), "0" (count/4), "1" ((long)s)
+		     : "memory");
+	return s;
+}
+
 /* Added by Gertjan van Wingerde to make minix and sysv module work */
 #define __HAVE_ARCH_STRNLEN
 extern size_t strnlen(const char *s, size_t count);
@@ -184,6 +214,67 @@
 #define __HAVE_ARCH_STRSTR
 extern char *strstr(const char *cs, const char *ct);
 
+/*
+ * This looks horribly ugly, but the compiler can optimize it totally,
+ * as we by now know that both pattern and count is constant..
+ */
+static __always_inline
+void *__constant_c_and_count_memset(void *s, unsigned long pattern,
+				    size_t count)
+{
+	switch (count) {
+	case 0:
+		return s;
+	case 1:
+		*(unsigned char *)s = pattern & 0xff;
+		return s;
+	case 2:
+		*(unsigned short *)s = pattern & 0xffff;
+		return s;
+	case 3:
+		*(unsigned short *)s = pattern & 0xffff;
+		*((unsigned char *)s + 2) = pattern & 0xff;
+		return s;
+	case 4:
+		*(unsigned long *)s = pattern;
+		return s;
+	}
+
+#define COMMON(x)							\
+	asm volatile("rep ; stosl"					\
+		     x							\
+		     : "=&c" (d0), "=&D" (d1)				\
+		     : "a" (eax), "0" (count/4), "1" ((long)s)	\
+		     : "memory")
+
+	{
+		int d0, d1;
+		unsigned long eax = pattern;
+
+		switch (count % 4) {
+		case 0:
+			COMMON("");
+			return s;
+		case 1:
+			COMMON("\n\tstosb");
+			return s;
+		case 2:
+			COMMON("\n\tstosw");
+			return s;
+		default:
+			COMMON("\n\tstosw\n\tstosb");
+			return s;
+		}
+	}
+
+#undef COMMON
+}
+
+#define __constant_c_x_memset(s, c, count)			\
+	(__builtin_constant_p(count)				\
+	 ? __constant_c_and_count_memset((s), (c), (count))	\
+	 : __constant_c_memset((s), (c), (count)))
+
 #define __memset(s, c, count)				\
 	(__builtin_constant_p(count)			\
 	 ? __constant_count_memset((s), (c), (count))	\
@@ -192,7 +283,15 @@
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *, int, size_t);
 #ifndef CONFIG_FORTIFY_SOURCE
+#if (__GNUC__ >= 4 && !defined(CONFIG_X86_INTEL_CE))
 #define memset(s, c, count) __builtin_memset(s, c, count)
+#else
+#define memset(s, c, count)						\
+	(__builtin_constant_p(c)					\
+	 ? __constant_c_x_memset((s), (0x01010101UL * (unsigned char)(c)), \
+				 (count))				\
+	 : __memset((s), (c), (count)))
+#endif
 #endif /* !CONFIG_FORTIFY_SOURCE */
 
 #define __HAVE_ARCH_MEMSET16
diff -ruw linux-6.4/arch/x86/include/uapi/asm/bootparam.h linux-6.4-fbx/arch/x86/include/uapi/asm/bootparam.h
--- linux-6.4/arch/x86/include/uapi/asm/bootparam.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/include/uapi/asm/bootparam.h	2023-11-29 17:07:06.958317708 +0100
@@ -48,6 +48,17 @@
 #include <asm/ist.h>
 #include <video/edid.h>
 
+/* setup data types */
+#define SETUP_NONE			0
+#define SETUP_E820_EXT			1
+#define SETUP_DTB			2
+
+/*
+ * use a number that likely won't clash with newer extensions.
+ */
+#define SETUP_FBXSERIAL_EXT		0x42000001
+#define SETUP_FBXBOOTINFO		0x42000002
+
 /* extensible setup data list node */
 struct setup_data {
 	__u64 next;
diff -ruw linux-6.4/arch/x86/kernel/Makefile linux-6.4-fbx/arch/x86/kernel/Makefile
--- linux-6.4/arch/x86/kernel/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/Makefile	2023-11-29 17:07:06.961651046 +0100
@@ -145,6 +145,9 @@
 
 obj-$(CONFIG_CALL_THUNKS)		+= callthunks.o
 
+obj-$(CONFIG_FBXSERIAL)			+= fbxserial.o
+obj-y					+= fbxbootinfo.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff -ruw linux-6.4/arch/x86/kernel/apic/io_apic.c linux-6.4-fbx/arch/x86/kernel/apic/io_apic.c
--- linux-6.4/arch/x86/kernel/apic/io_apic.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/apic/io_apic.c	2023-11-29 17:07:06.964984385 +0100
@@ -2173,6 +2173,7 @@
 	int node = cpu_to_node(0);
 	int apic1, pin1, apic2, pin2;
 	int no_pin1 = 0;
+	unsigned int vector;
 
 	if (!global_clock_event)
 		return;
@@ -2201,9 +2202,14 @@
 	pin2  = ioapic_i8259.pin;
 	apic2 = ioapic_i8259.apic;
 
+	if (cfg)
+		vector = cfg->vector;
+	else
+		vector = ISA_IRQ_VECTOR(0);
+
 	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
 		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
-		    cfg->vector, apic1, pin1, apic2, pin2);
+		    vector, apic1, pin1, apic2, pin2);
 
 	/*
 	 * Some BIOS writers are clueless and report the ExtINTA
@@ -2277,7 +2283,7 @@
 		    "...trying to set up timer as Virtual Wire IRQ...\n");
 
 	lapic_register_intr(0);
-	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
 	legacy_pic->unmask(0);
 
 	if (timer_irq_works()) {
@@ -2285,7 +2291,7 @@
 		goto out;
 	}
 	legacy_pic->mask(0);
-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
 	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
 
 	apic_printk(APIC_QUIET, KERN_INFO
diff -ruw linux-6.4/arch/x86/kernel/cpu/intel.c linux-6.4-fbx/arch/x86/kernel/cpu/intel.c
--- linux-6.4/arch/x86/kernel/cpu/intel.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/cpu/intel.c	2023-11-29 17:07:06.968317723 +0100
@@ -461,13 +461,26 @@
 		clear_cpu_cap(c, X86_FEATURE_PAT);
 
 	/*
-	 * If fast string is not enabled in IA32_MISC_ENABLE for any reason,
-	 * clear the fast string and enhanced fast string CPU capabilities.
+	 * If BIOS didn't enable fast string operation, try to enable
+	 * it ourselves.  If that fails, then clear the fast string
+	 * and enhanced fast string CPU capabilities.
 	 */
 	if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
 		rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+		if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
+			misc_enable |= MSR_IA32_MISC_ENABLE_FAST_STRING;
+			wrmsrl_safe(MSR_IA32_MISC_ENABLE, misc_enable);
+
+			/* Re-read to make sure it stuck. */
+			rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+			if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)
+				printk_once(KERN_INFO FW_WARN "IA32_MISC_ENABLE.FAST_STRING_ENABLE was not set\n");
+		}
+
 		if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
-			pr_info("Disabled fast string operations\n");
+			pr_info("Failed to enable fast string operations\n");
 			setup_clear_cpu_cap(X86_FEATURE_REP_GOOD);
 			setup_clear_cpu_cap(X86_FEATURE_ERMS);
 		}
diff -ruw linux-6.4/arch/x86/kernel/early_printk.c linux-6.4-fbx/arch/x86/kernel/early_printk.c
--- linux-6.4/arch/x86/kernel/early_printk.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/early_printk.c	2023-11-29 17:07:06.981651077 +0100
@@ -132,7 +132,9 @@
 	unsigned char c;
 
 	serial_out(early_serial_base, LCR, 0x3);	/* 8n1 */
+#ifndef CONFIG_X86_INTEL_CE
 	serial_out(early_serial_base, IER, 0);	/* no interrupt */
+#endif
 	serial_out(early_serial_base, FCR, 0);	/* no fifo */
 	serial_out(early_serial_base, MCR, 0x3);	/* DTR + RTS */
 
@@ -181,7 +183,11 @@
 	}
 
 	/* Convert from baud to divisor value */
+#ifdef CONFIG_X86_INTEL_CE
+	divisor = 921600 / baud;
+#else
 	divisor = 115200 / baud;
+#endif
 
 	/* These will always be IO based ports */
 	serial_in = io_serial_in;
diff -ruw linux-6.4/arch/x86/kernel/head32.c linux-6.4-fbx/arch/x86/kernel/head32.c
--- linux-6.4/arch/x86/kernel/head32.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/head32.c	2023-11-29 17:07:06.984984416 +0100
@@ -38,6 +38,13 @@
 
 	sanitize_boot_params(&boot_params);
 
+#ifdef CONFIG_FBX6HD
+	/* bootloader does not set subarch correctly, so we can't
+	 * compile generic kernels, though we may be able to detect
+	 * ce4100 at runtime */
+	boot_params.hdr.hardware_subarch = X86_SUBARCH_CE4100;
+#endif
+
 	x86_early_init_platform_quirks();
 
 	/* Call the subarch specific early setup function */
diff -ruw linux-6.4/arch/x86/kernel/reboot_fixups_32.c linux-6.4-fbx/arch/x86/kernel/reboot_fixups_32.c
--- linux-6.4/arch/x86/kernel/reboot_fixups_32.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/reboot_fixups_32.c	2020-02-08 00:30:16.620454581 +0100
@@ -9,6 +9,7 @@
  */
 
 #include <asm/delay.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <asm/reboot_fixups.h>
@@ -17,6 +18,11 @@
 
 static void cs5530a_warm_reset(struct pci_dev *dev)
 {
+	if (in_interrupt()) {
+		printk("cs5530a_warm_reset(): can't reboot: can't access "
+		       "PCI config space from IRQ.\n");
+		return ;
+	}
 	/* writing 1 to the reset control register, 0x44 causes the
 	cs5530a to perform a system warm reset */
 	pci_write_config_byte(dev, 0x44, 0x1);
@@ -58,6 +64,7 @@
 	unsigned int vendor;
 	unsigned int device;
 	void (*reboot_fixup)(struct pci_dev *);
+	struct pci_dev *dev;
 };
 
 /*
@@ -65,7 +72,7 @@
  */
 #define PCI_DEVICE_ID_INTEL_CE4100	0x0708
 
-static const struct device_fixup fixups_table[] = {
+static struct device_fixup fixups_table[] = {
 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset },
 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset },
@@ -82,22 +89,29 @@
 void mach_reboot_fixups(void)
 {
 	const struct device_fixup *cur;
-	struct pci_dev *dev;
 	int i;
 
-	/* we can be called from sysrq-B code. In such a case it is
-	 * prohibited to dig PCI */
-	if (in_interrupt())
-		return;
+	for (i = 0; i < ARRAY_SIZE(fixups_table); ++i) {
+		cur = &fixups_table[i];
+		if (cur->dev)
+			cur->reboot_fixup(cur->dev);
+	}
+}
+
+static int mach_reboot_fixups_init(void)
+{
+	struct pci_dev *dev;
+	struct device_fixup *cur;
+	int i;
 
 	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
-		cur = &(fixups_table[i]);
+		cur = &fixups_table[i];
 		dev = pci_get_device(cur->vendor, cur->device, NULL);
 		if (!dev)
 			continue;
 
-		cur->reboot_fixup(dev);
-		pci_dev_put(dev);
+		cur->dev = dev;
 	}
+	return 0;
 }
-
+module_init(mach_reboot_fixups_init);
diff -ruw linux-6.4/arch/x86/kernel/setup.c linux-6.4-fbx/arch/x86/kernel/setup.c
--- linux-6.4/arch/x86/kernel/setup.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/kernel/setup.c	2023-11-29 17:07:06.991651093 +0100
@@ -392,6 +392,11 @@
 	struct setup_data *data;
 	u64 pa_data, pa_next;
 
+#ifdef CONFIG_FBXSERIAL
+	extern void parse_fbxserial_ext(u64 phys_addr, u32 data_len);
+#endif
+	extern void parse_fbxbootinfo(u64 phys_addr, u32 data_len);
+
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
 		u32 data_len, data_type;
@@ -424,6 +429,14 @@
 			memzero_explicit(&data->len, sizeof(data->len));
 			early_memunmap(data, data_len);
 			break;
+#ifdef CONFIG_FBXSERIAL
+		case SETUP_FBXSERIAL_EXT:
+			parse_fbxserial_ext(pa_data, data_len);
+			break;
+#endif
+		case SETUP_FBXBOOTINFO:
+			parse_fbxbootinfo(pa_data, data_len);
+			break;
 		default:
 			break;
 		}
diff -ruw linux-6.4/arch/x86/platform/ce4100/Makefile linux-6.4-fbx/arch/x86/platform/ce4100/Makefile
--- linux-6.4/arch/x86/platform/ce4100/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/platform/ce4100/Makefile	2020-02-08 00:30:16.696455319 +0100
@@ -1,2 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_X86_INTEL_CE)	+= ce4100.o
+obj-$(CONFIG_FBX6HD)		+= fbx6hd.o fbx6hd.dtb.o
+
+dtb-$(CONFIG_FBX6HD)		+= fbx6hd.dtb.S
+clean-files := *.dtb *.dtb.S
diff -ruw linux-6.4/arch/x86/platform/ce4100/ce4100.c linux-6.4-fbx/arch/x86/platform/ce4100/ce4100.c
--- linux-6.4/arch/x86/platform/ce4100/ce4100.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/arch/x86/platform/ce4100/ce4100.c	2023-11-29 17:07:07.061651201 +0100
@@ -10,6 +10,11 @@
 #include <linux/reboot.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_8250.h>
+#include <linux/reboot.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
 
 #include <asm/ce4100.h>
 #include <asm/prom.h>
@@ -119,9 +124,15 @@
 static inline void sdv_serial_fixup(void) {};
 #endif
 
+extern void fbx6hd_arch_setup(void);
+
 static void __init sdv_arch_setup(void)
 {
 	sdv_serial_fixup();
+#ifdef CONFIG_FBX6HD
+	/* no clean way to detect this, so force fbx6hd init */
+	fbx6hd_arch_setup();
+#endif
 }
 
 static void sdv_pci_init(void)
@@ -143,6 +154,10 @@
 	x86_init.pci.init = ce4100_pci_init;
 	x86_init.pci.init_irq = sdv_pci_init;
 
+	/* disable RTC as it seems to sometimes start in a broken state */
+	x86_platform.get_wallclock = get_rtc_noop;
+	x86_platform.set_wallclock = set_rtc_noop;
+
 	/*
 	 * By default, the reboot method is ACPI which is supported by the
 	 * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
@@ -152,5 +167,6 @@
 	 */
 	reboot_type = BOOT_KBD;
 
+
 	pm_power_off = ce4100_power_off;
 }
diff -ruw linux-6.4/block/blk-flush.c linux-6.4-fbx/block/blk-flush.c
--- linux-6.4/block/blk-flush.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/blk-flush.c	2023-11-29 17:07:07.094984587 +0100
@@ -172,10 +172,21 @@
 	rq->flush.seq |= seq;
 	cmd_flags = rq->cmd_flags;
 
-	if (likely(!error))
+	if (likely(!error)) {
 		seq = blk_flush_cur_seq(rq);
-	else
+	} else {
 		seq = REQ_FSEQ_DONE;
+		printk_once(KERN_ERR "%s: flush failed: data integrity problem\n",
+				   rq->q->disk ? rq->q->disk->disk_name : "?");
+		/*
+		 * returning an error to the FS is wrong: the data is all
+		 * there, it just might not be written out in the expected
+		 * order and thus have a window where the integrity is suspect
+		 * in a crash.  Given the small likelihood of actually
+		 * crashing, we should just log a warning here.
+		 */
+		error = 0;
+	}
 
 	switch (seq) {
 	case REQ_FSEQ_PREFLUSH:
diff -ruw linux-6.4/block/blk-mq.c linux-6.4-fbx/block/blk-mq.c
--- linux-6.4/block/blk-mq.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/blk-mq.c	2023-11-29 17:07:07.101651264 +0100
@@ -955,7 +955,7 @@
 }
 EXPORT_SYMBOL_GPL(blk_update_request);
 
-static inline void blk_account_io_done(struct request *req, u64 now)
+static inline void blk_account_io_done(struct request *req, u64 now, blk_status_t error)
 {
 	/*
 	 * Account IO completion.  flush_rq isn't accounted as a
@@ -970,6 +970,8 @@
 		update_io_ticks(req->part, jiffies, true);
 		part_stat_inc(req->part, ios[sgrp]);
 		part_stat_add(req->part, nsecs[sgrp], now - req->start_time_ns);
+		if (error)
+			part_stat_inc(req->part, io_errors[rq_data_dir(req)]);
 		part_stat_unlock();
 	}
 }
@@ -994,19 +996,19 @@
 	}
 }
 
-static inline void __blk_mq_end_request_acct(struct request *rq, u64 now)
+static inline void __blk_mq_end_request_acct(struct request *rq, u64 now, blk_status_t error)
 {
 	if (rq->rq_flags & RQF_STATS)
 		blk_stat_add(rq, now);
 
 	blk_mq_sched_completed_request(rq, now);
-	blk_account_io_done(rq, now);
+	blk_account_io_done(rq, now, error);
 }
 
 inline void __blk_mq_end_request(struct request *rq, blk_status_t error)
 {
 	if (blk_mq_need_time_stamp(rq))
-		__blk_mq_end_request_acct(rq, ktime_get_ns());
+		__blk_mq_end_request_acct(rq, ktime_get_ns(), error);
 
 	if (rq->end_io) {
 		rq_qos_done(rq->q, rq);
@@ -1060,7 +1062,7 @@
 
 		blk_complete_request(rq);
 		if (iob->need_ts)
-			__blk_mq_end_request_acct(rq, now);
+			__blk_mq_end_request_acct(rq, now, 0);
 
 		rq_qos_done(rq->q, rq);
 
@@ -3049,7 +3051,7 @@
 	blk_mq_run_dispatch_ops(q,
 			ret = blk_mq_request_issue_directly(rq, true));
 	if (ret)
-		blk_account_io_done(rq, ktime_get_ns());
+		blk_account_io_done(rq, ktime_get_ns(), 0);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
diff -ruw linux-6.4/block/blk.h linux-6.4-fbx/block/blk.h
--- linux-6.4/block/blk.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/blk.h	2023-11-29 17:07:07.104984602 +0100
@@ -404,6 +404,7 @@
 #define ADDPART_FLAG_NONE	0
 #define ADDPART_FLAG_RAID	1
 #define ADDPART_FLAG_WHOLEDISK	2
+#define ADDPART_FLAG_RO		4
 int bdev_add_partition(struct gendisk *disk, int partno, sector_t start,
 		sector_t length);
 int bdev_del_partition(struct gendisk *disk, int partno);
diff -ruw linux-6.4/block/genhd.c linux-6.4-fbx/block/genhd.c
--- linux-6.4/block/genhd.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/genhd.c	2023-11-29 17:07:07.104984602 +0100
@@ -984,6 +984,7 @@
 		"%8u %8u %8u "
 		"%8lu %8lu %8llu %8u "
 		"%8lu %8u"
+		"%8lu %8lu"
 		"\n",
 		stat.ios[STAT_READ],
 		stat.merges[STAT_READ],
@@ -1005,7 +1006,9 @@
 		(unsigned long long)stat.sectors[STAT_DISCARD],
 		(unsigned int)div_u64(stat.nsecs[STAT_DISCARD], NSEC_PER_MSEC),
 		stat.ios[STAT_FLUSH],
-		(unsigned int)div_u64(stat.nsecs[STAT_FLUSH], NSEC_PER_MSEC));
+		(unsigned int)div_u64(stat.nsecs[STAT_FLUSH], NSEC_PER_MSEC),
+		part_stat_read(bdev, io_errors[READ]),
+		part_stat_read(bdev, io_errors[WRITE]));
 }
 
 ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
diff -ruw linux-6.4/block/partitions/Kconfig linux-6.4-fbx/block/partitions/Kconfig
--- linux-6.4/block/partitions/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/partitions/Kconfig	2023-11-29 17:07:07.104984602 +0100
@@ -270,4 +270,12 @@
 	  Say Y here if you want to read the partition table from bootargs.
 	  The format for the command line is just like mtdparts.
 
+config OF_PARTITION
+	bool "Device tree partition support" if PARTITION_ADVANCED
+	depends on OF
+
+config OF_PARTITION_IGNORE_RO
+	bool "ignore read-only flag"
+	depends on OF_PARTITION
+
 endmenu
diff -ruw linux-6.4/block/partitions/Makefile linux-6.4-fbx/block/partitions/Makefile
--- linux-6.4/block/partitions/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/partitions/Makefile	2022-08-30 19:20:22.239534492 +0200
@@ -20,3 +20,4 @@
 obj-$(CONFIG_EFI_PARTITION) += efi.o
 obj-$(CONFIG_KARMA_PARTITION) += karma.o
 obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
+obj-$(CONFIG_OF_PARTITION) += dt.o
diff -ruw linux-6.4/block/partitions/check.h linux-6.4-fbx/block/partitions/check.h
--- linux-6.4/block/partitions/check.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/partitions/check.h	2023-11-29 17:07:07.108317941 +0100
@@ -67,3 +67,4 @@
 int sun_partition(struct parsed_partitions *state);
 int sysv68_partition(struct parsed_partitions *state);
 int ultrix_partition(struct parsed_partitions *state);
+int dt_partition(struct parsed_partitions *);
diff -ruw linux-6.4/block/partitions/core.c linux-6.4-fbx/block/partitions/core.c
--- linux-6.4/block/partitions/core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/block/partitions/core.c	2023-11-29 17:07:07.108317941 +0100
@@ -13,6 +13,10 @@
 #include "check.h"
 
 static int (*check_part[])(struct parsed_partitions *) = {
+#ifdef CONFIG_OF_PARTITION
+	dt_partition,
+#endif
+
 	/*
 	 * Probe partition formats with tables at disk address 0
 	 * that also have an ADFS boot block at 0xdc0.
@@ -341,6 +345,7 @@
 
 	bdev->bd_start_sect = start;
 	bdev_set_nr_sectors(bdev, len);
+	bdev->bd_read_only = (flags & ADDPART_FLAG_RO);
 
 	pdev = &bdev->bd_device;
 	dname = dev_name(ddev);
diff -ruw linux-6.4/drivers/Kconfig linux-6.4-fbx/drivers/Kconfig
--- linux-6.4/drivers/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/Kconfig	2023-11-29 17:07:07.154984680 +0100
@@ -21,6 +21,8 @@
 
 source "drivers/gnss/Kconfig"
 
+source "drivers/fbxprocfs/Kconfig"
+
 source "drivers/mtd/Kconfig"
 
 source "drivers/of/Kconfig"
@@ -77,6 +79,10 @@
 
 source "drivers/gpio/Kconfig"
 
+source "drivers/fbxgpio/Kconfig"
+
+source "drivers/fbxjtag/Kconfig"
+
 source "drivers/w1/Kconfig"
 
 source "drivers/power/Kconfig"
@@ -85,6 +91,8 @@
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/fbxwatchdog/Kconfig"
+
 source "drivers/watchdog/Kconfig"
 
 source "drivers/ssb/Kconfig"
diff -ruw linux-6.4/drivers/Makefile linux-6.4-fbx/drivers/Makefile
--- linux-6.4/drivers/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/Makefile	2023-11-29 17:07:07.154984680 +0100
@@ -21,7 +21,9 @@
 obj-$(CONFIG_GPIOLIB)		+= gpio/
 obj-y				+= pwm/
 
+obj-$(CONFIG_FREEBOX_GPIO)	+= fbxgpio/
 obj-y				+= pci/
+obj-$(CONFIG_FREEBOX_JTAG)	+= fbxjtag/
 
 obj-$(CONFIG_PARISC)		+= parisc/
 obj-$(CONFIG_RAPIDIO)		+= rapidio/
@@ -121,6 +123,7 @@
 obj-y				+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
 obj-$(CONFIG_THERMAL)		+= thermal/
+obj-$(CONFIG_FREEBOX_WATCHDOG)	+= fbxwatchdog/
 obj-$(CONFIG_WATCHDOG)		+= watchdog/
 obj-$(CONFIG_MD)		+= md/
 obj-$(CONFIG_BT)		+= bluetooth/
@@ -195,3 +198,5 @@
 obj-$(CONFIG_HTE)		+= hte/
 obj-$(CONFIG_DRM_ACCEL)		+= accel/
 obj-$(CONFIG_CDX_BUS)		+= cdx/
+
+obj-$(CONFIG_FREEBOX_PROCFS)	+= fbxprocfs/
diff -ruw linux-6.4/drivers/ata/ahci.h linux-6.4-fbx/drivers/ata/ahci.h
--- linux-6.4/drivers/ata/ahci.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/ata/ahci.h	2023-11-29 17:07:07.311651590 +0100
@@ -378,6 +378,9 @@
 	/* only required for per-port MSI(-X) support */
 	int			(*get_irq_vector)(struct ata_host *host,
 						  int port);
+
+	u32			comreset_u;
+	u32			comwake;
 };
 
 extern int ahci_ignore_sss;
diff -ruw linux-6.4/drivers/ata/libahci.c linux-6.4-fbx/drivers/ata/libahci.c
--- linux-6.4/drivers/ata/libahci.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/ata/libahci.c	2023-11-29 17:07:07.314984929 +0100
@@ -1257,6 +1257,47 @@
 	return sprintf(buf, "%d\n", emp->blink_policy);
 }
 
+#define PORT_OOB_INDIRECT_ADDR	0x78
+#define PORT_OOB_INDIRECT_DATA	0x7c
+
+#define COM_PARAM_REG	0x48
+#define COMWAKE_MASK	0xf
+#define COMRST_MASK	0x3f
+#define COMWAKE_VAL(x)		(((x) & 0xf) << 12)
+#define COMRST_VAL(x)		(((x) & 0x3f) << 0)
+
+static void write_phy_indirect(void __iomem *pmmio, u32 v, u32 reg)
+{
+	writel(reg, pmmio + PORT_OOB_INDIRECT_ADDR);
+	writel(v, pmmio + PORT_OOB_INDIRECT_DATA);
+}
+
+static u32 read_phy_indirect(void __iomem *pmmio, u32 reg)
+{
+	writel(reg, pmmio + PORT_OOB_INDIRECT_ADDR);
+	return readl(pmmio + PORT_OOB_INDIRECT_DATA);
+}
+
+static void comwake_comrst_config(void __iomem *pmmio, u32 comwake, u32 comrst)
+{
+	u32 v;
+
+	v = read_phy_indirect(pmmio, COM_PARAM_REG);
+
+	if (comwake) {
+		v &= ~COMWAKE_VAL(COMWAKE_MASK);
+		v |= COMWAKE_VAL(comwake);
+	}
+
+	if (comrst) {
+		v &= ~COMRST_VAL(COMRST_MASK);
+		v |= COMRST_VAL(comrst);
+	}
+
+	write_phy_indirect(pmmio, v, COM_PARAM_REG);
+}
+
+
 static void ahci_port_init(struct device *dev, struct ata_port *ap,
 			   int port_no, void __iomem *mmio,
 			   void __iomem *port_mmio)
@@ -1271,6 +1312,8 @@
 	if (rc)
 		dev_warn(dev, "%s (%d)\n", emsg, rc);
 
+	comwake_comrst_config(port_mmio, hpriv->comwake, hpriv->comreset_u);
+
 	/* clear SError */
 	tmp = readl(port_mmio + PORT_SCR_ERR);
 	dev_dbg(dev, "PORT_SCR_ERR 0x%x\n", tmp);
diff -ruw linux-6.4/drivers/ata/libata-core.c linux-6.4-fbx/drivers/ata/libata-core.c
--- linux-6.4/drivers/ata/libata-core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/ata/libata-core.c	2023-11-29 17:07:07.318318267 +0100
@@ -3981,6 +3981,8 @@
 	/* Sandisk SD7/8/9s lock up hard on large trims */
 	{ "SanDisk SD[789]*",	NULL,		ATA_HORKAGE_MAX_TRIM_128M },
 
+	{ "Boot ROM", 		NULL,		ATA_HORKAGE_NODMA  },
+
 	/* devices which puke on READ_NATIVE_MAX */
 	{ "HDS724040KLSA80",	"KFAOA20N",	ATA_HORKAGE_BROKEN_HPA },
 	{ "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA },
diff -ruw linux-6.4/drivers/ata/libata-scsi.c linux-6.4-fbx/drivers/ata/libata-scsi.c
--- linux-6.4/drivers/ata/libata-scsi.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/ata/libata-scsi.c	2023-11-29 17:07:07.321651606 +0100
@@ -4235,7 +4235,7 @@
 		 */
 		shost->max_host_blocked = 1;
 
-		rc = scsi_add_host_with_dma(shost, &ap->tdev, ap->host->dev);
+		rc = scsi_add_host_with_dma(shost, host->dev, host->dev);
 		if (rc)
 			goto err_alloc;
 	}
diff -ruw linux-6.4/drivers/base/regmap/internal.h linux-6.4-fbx/drivers/base/regmap/internal.h
--- linux-6.4/drivers/base/regmap/internal.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/base/regmap/internal.h	2023-11-29 17:07:07.358318329 +0100
@@ -326,5 +326,6 @@
 #define regmap_init_ram(config, data)					\
 	__regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data)
 
+void *regmap_mmio_ctx_get_base(const void *priv);
 
 #endif
diff -ruw linux-6.4/drivers/base/regmap/regmap.c linux-6.4-fbx/drivers/base/regmap/regmap.c
--- linux-6.4/drivers/base/regmap/regmap.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/base/regmap/regmap.c	2023-11-29 17:07:07.361651668 +0100
@@ -3542,6 +3542,15 @@
 }
 EXPORT_SYMBOL_GPL(regmap_parse_val);
 
+#ifdef CONFIG_REGMAP_MMIO
+void *regmap_get_mmio_base_address(struct regmap *map)
+{
+	return regmap_mmio_ctx_get_base(map->bus_context);
+}
+
+EXPORT_SYMBOL_GPL(regmap_get_mmio_base_address);
+#endif
+
 static int __init regmap_initcall(void)
 {
 	regmap_debugfs_initcall();
diff -ruw linux-6.4/drivers/bluetooth/btrtl.h linux-6.4-fbx/drivers/bluetooth/btrtl.h
--- linux-6.4/drivers/bluetooth/btrtl.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/bluetooth/btrtl.h	2023-11-29 17:07:07.398318391 +0100
@@ -140,6 +140,7 @@
 			    unsigned int *controller_baudrate,
 			    u32 *device_baudrate, bool *flow_control);
 
+void btrtl_show_version(struct hci_dev *hdev);
 #else
 
 static inline struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
diff -ruw linux-6.4/drivers/char/Kconfig linux-6.4-fbx/drivers/char/Kconfig
--- linux-6.4/drivers/char/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/char/Kconfig	2023-11-29 17:07:07.421651761 +0100
@@ -315,6 +315,15 @@
 	  memory.
 	  When in doubt, say "Y".
 
+config DEVPHYSMEM
+	bool "/dev/physmem virtual device support"
+	default n
+	help
+	  Say Y here if you want to support the /dev/physmem device. The
+	  /dev/physmem device allows unprivileged access to physical memory
+	  unused by the kernel.
+	  When in doubt, say "N".
+
 config NVRAM
 	tristate "/dev/nvram support"
 	depends on X86 || HAVE_ARCH_NVRAM_OPS
@@ -422,3 +431,5 @@
 	  driver include crash and makedumpfile.
 
 endmenu
+
+source "drivers/char/diag/Kconfig"
diff -ruw linux-6.4/drivers/char/Makefile linux-6.4-fbx/drivers/char/Makefile
--- linux-6.4/drivers/char/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/char/Makefile	2023-11-29 17:07:07.421651761 +0100
@@ -44,3 +44,5 @@
 obj-$(CONFIG_XILLYBUS_CLASS)	+= xillybus/
 obj-$(CONFIG_POWERNV_OP_PANEL)	+= powernv-op-panel.o
 obj-$(CONFIG_ADI)		+= adi.o
+
+obj-$(CONFIG_DIAG_CHAR)		+= diag/
diff -ruw linux-6.4/drivers/char/hw_random/Kconfig linux-6.4-fbx/drivers/char/hw_random/Kconfig
--- linux-6.4/drivers/char/hw_random/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/char/hw_random/Kconfig	2023-11-29 17:07:07.428318438 +0100
@@ -98,6 +98,11 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_BCM63XX
+	tristate "Broadcom BCM63xx Random Number Generator support"
+	depends on ARCH_BCMBCA || BCM63XX
+	default HW_RANDOM
+
 config HW_RANDOM_IPROC_RNG200
 	tristate "Broadcom iProc/STB RNG200 support"
 	depends on ARCH_BCM_IPROC || ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST
@@ -559,6 +564,13 @@
 	  To compile this driver as a module, choose M here.
 	  The module will be called jh7110-trng.
 
+config HW_RANDOM_QCOM
+	tristate "Qualcomm Random Number Generator Driver"
+	depends on ARCH_QCOM || COMPILE_TEST
+	help
+	  This driver provides support for the Random Number
+	  Generator hardware found on Qualcomm SoCs.
+
 endif # HW_RANDOM
 
 config UML_RANDOM
diff -ruw linux-6.4/drivers/char/hw_random/Makefile linux-6.4-fbx/drivers/char/hw_random/Makefile
--- linux-6.4/drivers/char/hw_random/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/char/hw_random/Makefile	2023-11-29 17:07:07.428318438 +0100
@@ -30,6 +30,7 @@
 obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
 obj-$(CONFIG_HW_RANDOM_HISI)	+= hisi-rng.o
 obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
+obj-$(CONFIG_HW_RANDOM_BCM63XX) += bcm63xx-rng.o
 obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
 obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
 obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
@@ -48,3 +49,4 @@
 obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o
 obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o
 obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o
+obj-$(CONFIG_HW_RANDOM_QCOM) += qcom-rng.o
diff -ruw linux-6.4/drivers/char/mem.c linux-6.4-fbx/drivers/char/mem.c
--- linux-6.4/drivers/char/mem.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/char/mem.c	2023-11-29 17:07:07.438318454 +0100
@@ -28,6 +28,8 @@
 #include <linux/export.h>
 #include <linux/io.h>
 #include <linux/uio.h>
+#include <linux/memblock.h>
+
 #include <linux/uaccess.h>
 #include <linux/security.h>
 
@@ -402,6 +404,14 @@
 	return 0;
 }
 
+static int mmap_physmem(struct file * file, struct vm_area_struct * vma)
+{
+	if (vma->vm_pgoff < max_pfn && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	return mmap_mem(file, vma);
+}
+
 static ssize_t read_port(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
@@ -643,6 +653,11 @@
 	return 0;
 }
 
+static int open_physmem(struct inode * inode, struct file * filp)
+{
+	return 0;
+}
+
 #define zero_lseek	null_lseek
 #define full_lseek      null_lseek
 #define write_zero	write_null
@@ -697,6 +712,14 @@
 	.write		= write_full,
 };
 
+static const struct file_operations __maybe_unused physmem_fops = {
+	.mmap		= mmap_physmem,
+	.open		= open_physmem,
+#ifndef CONFIG_MMU
+	.get_unmapped_area = get_unmapped_area_mem,
+#endif
+};
+
 static const struct memdev {
 	const char *name;
 	umode_t mode;
@@ -717,6 +740,9 @@
 #ifdef CONFIG_PRINTK
 	[11] = { "kmsg", 0644, &kmsg_fops, 0 },
 #endif
+#ifdef CONFIG_DEVPHYSMEM
+	[16] = { "physmem", 0, &physmem_fops, FMODE_UNSIGNED_OFFSET },
+#endif
 };
 
 static int memory_open(struct inode *inode, struct file *filp)
diff -ruw linux-6.4/drivers/clk/qcom/Kconfig linux-6.4-fbx/drivers/clk/qcom/Kconfig
--- linux-6.4/drivers/clk/qcom/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/clk/qcom/Kconfig	2023-11-29 17:07:07.508318562 +0100
@@ -189,6 +189,12 @@
 	  i2c, USB, SD/eMMC, etc. Select this for the root clock
 	  of ipq9574.
 
+config IPQ_NSSCC_9574
+	tristate "IPQ9574 NSS Clock Controller"
+	depends on IPQ_GCC_9574
+	help
+	  Support for NSS clock controller on ipq9574 devices.
+
 config MSM_GCC_8660
 	tristate "MSM8660 Global Clock Controller"
 	help
diff -ruw linux-6.4/drivers/clk/qcom/Makefile linux-6.4-fbx/drivers/clk/qcom/Makefile
--- linux-6.4/drivers/clk/qcom/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/clk/qcom/Makefile	2023-11-29 17:07:07.508318562 +0100
@@ -29,6 +29,7 @@
 obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
 obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o
 obj-$(CONFIG_IPQ_GCC_9574) += gcc-ipq9574.o
+obj-$(CONFIG_IPQ_NSSCC_9574) += nsscc-ipq9574.o
 obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
 obj-$(CONFIG_MDM_GCC_9607) += gcc-mdm9607.o
 obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
diff -ruw linux-6.4/drivers/cpufreq/Kconfig linux-6.4-fbx/drivers/cpufreq/Kconfig
--- linux-6.4/drivers/cpufreq/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/cpufreq/Kconfig	2023-11-29 17:07:07.624985410 +0100
@@ -311,5 +311,10 @@
 	  This adds the CPUFreq driver support for Freescale QorIQ SoCs
 	  which are capable of changing the CPU's frequency dynamically.
 
+config BCM63158_CPUFREQ
+	tristate "CPU frequency scaling driver for BCM63158 SoC"
+	depends on ARCH_BCMBCA
+
 endif
+
 endmenu
diff -ruw linux-6.4/drivers/cpufreq/Makefile linux-6.4-fbx/drivers/cpufreq/Makefile
--- linux-6.4/drivers/cpufreq/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/cpufreq/Makefile	2023-11-29 17:07:07.624985410 +0100
@@ -107,3 +107,5 @@
 obj-$(CONFIG_SH_CPU_FREQ)		+= sh-cpufreq.o
 obj-$(CONFIG_SPARC_US2E_CPUFREQ)	+= sparc-us2e-cpufreq.o
 obj-$(CONFIG_SPARC_US3_CPUFREQ)		+= sparc-us3-cpufreq.o
+
+obj-$(CONFIG_BCM63158_CPUFREQ)		+= bcm63158-cpufreq.o
diff -ruw linux-6.4/drivers/gpio/Kconfig linux-6.4-fbx/drivers/gpio/Kconfig
--- linux-6.4/drivers/gpio/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/gpio/Kconfig	2023-11-29 17:07:07.798319013 +0100
@@ -1018,6 +1018,11 @@
 	  enough to represent all pins, but the driver will assume a
 	  register layout for 64 pins (8 registers).
 
+config GPIO_FBXGWR_PMU
+	tristate "Freebox PMU I2C GPIO expander"
+	depends on MFD_FBXGWR_PMU
+	select GPIOLIB_IRQCHIP
+
 config GPIO_FXL6408
 	tristate "FXL6408 I2C GPIO expander"
 	select GPIO_REGMAP
diff -ruw linux-6.4/drivers/gpio/Makefile linux-6.4-fbx/drivers/gpio/Makefile
--- linux-6.4/drivers/gpio/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/gpio/Makefile	2023-11-29 17:07:07.798319013 +0100
@@ -60,6 +60,7 @@
 obj-$(CONFIG_GPIO_EP93XX)		+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_EXAR)			+= gpio-exar.o
 obj-$(CONFIG_GPIO_F7188X)		+= gpio-f7188x.o
+obj-$(CONFIG_GPIO_FBXGWR_PMU)		+= gpio-fbxgwr-pmu.o
 obj-$(CONFIG_GPIO_FTGPIO010)		+= gpio-ftgpio010.o
 obj-$(CONFIG_GPIO_FXL6408)		+= gpio-fxl6408.o
 obj-$(CONFIG_GPIO_GE_FPGA)		+= gpio-ge.o
diff -ruw linux-6.4/drivers/hid/Kconfig linux-6.4-fbx/drivers/hid/Kconfig
--- linux-6.4/drivers/hid/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hid/Kconfig	2023-11-29 17:07:09.561655087 +0100
@@ -484,6 +484,11 @@
 	  Adds support for side buttons of Xiaomi Mi Dual Mode Wireless
 	  Mouse Silent Edition.
 
+config HID_FBX_REMOTE_AUDIO
+	tristate "Freebox BLE remote audio driver"
+	depends on HID && SND
+	select SND_PCM
+
 config HID_GYRATION
 	tristate "Gyration remote control"
 	help
diff -ruw linux-6.4/drivers/hid/Makefile linux-6.4-fbx/drivers/hid/Makefile
--- linux-6.4/drivers/hid/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hid/Makefile	2023-11-29 17:07:09.564988425 +0100
@@ -57,6 +57,7 @@
 obj-$(CONFIG_HID_GOOGLE_HAMMER)	+= hid-google-hammer.o
 obj-$(CONFIG_HID_VIVALDI)	+= hid-vivaldi.o
 obj-$(CONFIG_HID_GT683R)	+= hid-gt683r.o
+obj-$(CONFIG_HID_FBX_REMOTE_AUDIO)	+= hid-fbx-remote-audio.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-kbd.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-mouse.o
diff -ruw linux-6.4/drivers/hid/hid-dr.c linux-6.4-fbx/drivers/hid/hid-dr.c
--- linux-6.4/drivers/hid/hid-dr.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hid/hid-dr.c	2020-02-08 00:30:19.136479029 +0100
@@ -228,6 +228,75 @@
 	0xC0                /*  End Collection                  */
 };
 
+/* Size of the original descriptor of the PID 0x0006 joystick */
+#define PID0006_RDESC_ORIG_SIZE	101
+
+/* Fixed report descriptor for PID 0x006 joystick */
+static __u8 pid0006_rdesc_fixed[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),                   */
+	0x09, 0x04,         /*  Usage (Joystik),                        */
+	0xA1, 0x01,         /*  Collection (Application),               */
+	0xA1, 0x02,         /*      Collection (Logical),               */
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x02,         /*          Report Count (2),               */
+	0x15, 0x00,         /*          Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+	0x35, 0x00,         /*          Physical Minimum (0),           */
+	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+	0x09, 0x30,         /*          Usage (X),                      */
+	0x09, 0x31,         /*          Usage (Y),                      */
+	0x81, 0x02,         /*          Input (Variable),               */
+
+	/* Ignore noisy input */
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x01,         /*          Report Count (1),               */
+	0x81, 0x01,         /*          Input (Constant),       */
+
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x02,         /*          Report Count (2),               */
+	0x15, 0x00,         /*          Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+	0x35, 0x00,         /*          Physical Minimum (0),           */
+	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+	0x09, 0x30,         /*          Usage (X),                      */
+	0x09, 0x31,         /*          Usage (Y),                      */
+	0x81, 0x02,         /*          Input (Variable),               */
+
+	0x75, 0x04,         /*          Report Size (4),                */
+	0x95, 0x01,         /*          Report Count (1),               */
+	0x25, 0x07,         /*          Logical Maximum (7),            */
+	0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
+	0x65, 0x14,         /*          Unit (Degrees),                 */
+	0x09, 0x39,         /*          Usage (Hat Switch),             */
+	0x81, 0x42,         /*          Input (Variable, Null State),   */
+	0x65, 0x00,         /*          Unit,                           */
+	0x75, 0x01,         /*          Report Size (1),                */
+	0x95, 0x0C,         /*          Report Count (12),              */
+	0x25, 0x01,         /*          Logical Maximum (1),            */
+	0x45, 0x01,         /*          Physical Maximum (1),           */
+	0x05, 0x09,         /*          Usage Page (Button),            */
+	0x19, 0x01,         /*          Usage Minimum (01h),            */
+	0x29, 0x0C,         /*          Usage Maximum (0Ch),            */
+	0x81, 0x02,         /*          Input (Variable),               */
+	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),             */
+	0x75, 0x01,         /*          Report Size (1),                */
+	0x95, 0x08,         /*          Report Count (8),               */
+	0x25, 0x01,         /*          Logical Maximum (1),            */
+	0x45, 0x01,         /*          Physical Maximum (1),           */
+	0x09, 0x01,         /*          Usage (01h),                    */
+	0x81, 0x02,         /*          Input (Variable),               */
+	0xC0,               /*      End Collection,                     */
+	0xA1, 0x02,         /*      Collection (Logical),               */
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x07,         /*          Report Count (7),               */
+	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+	0x09, 0x02,         /*          Usage (02h),                    */
+	0x91, 0x02,         /*          Output (Variable),              */
+	0xC0,               /*      End Collection,                     */
+	0xC0                /*  End Collection                          */
+};
+
 static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 				unsigned int *rsize)
 {
@@ -238,6 +307,12 @@
 			*rsize = sizeof(pid0011_rdesc_fixed);
 		}
 		break;
+	case 0x0006:
+		if (*rsize == PID0006_RDESC_ORIG_SIZE) {
+			rdesc = pid0006_rdesc_fixed;
+			*rsize = sizeof(pid0006_rdesc_fixed);
+		}
+		break;
 	}
 	return rdesc;
 }
@@ -286,6 +361,7 @@
 
 	switch (hdev->product) {
 	case 0x0006:
+		strcpy(hdev->name, "Freebox Gamepad");
 		ret = drff_init(hdev);
 		if (ret) {
 			dev_err(&hdev->dev, "force feedback init failed\n");
diff -ruw linux-6.4/drivers/hid/hid-quirks.c linux-6.4-fbx/drivers/hid/hid-quirks.c
--- linux-6.4/drivers/hid/hid-quirks.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hid/hid-quirks.c	2023-11-29 17:07:09.578321779 +0100
@@ -719,6 +719,7 @@
 #if IS_ENABLED(CONFIG_HID_ZYDACRON)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
 #endif
+	{ HID_BLUETOOTH_DEVICE(0x10eb, 0x0023) },
 	{ }
 };
 
diff -ruw linux-6.4/drivers/hwmon/Kconfig linux-6.4-fbx/drivers/hwmon/Kconfig
--- linux-6.4/drivers/hwmon/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hwmon/Kconfig	2023-11-29 17:07:09.604988488 +0100
@@ -344,6 +344,10 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called fam15h_power.
 
+config SENSORS_FBXGWR_PMU
+	tristate "Freebox GWR PMU hardware monitoring driver"
+	depends on MFD_FBXGWR_PMU
+
 config SENSORS_APPLESMC
 	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
 	depends on INPUT && X86
@@ -2359,6 +2363,17 @@
 	  sensors monitor various telemetry data of different components on the
 	  card, e.g. board temperature, FPGA core temperature/voltage/current.
 
+config SENSORS_KIRKWOOD_CORETEMP
+	tristate "Kirkwood core temperature censor"
+	depends on MACH_KIRKWOOD
+
+config SENSORS_LD6710_FBX
+	tristate "LD6710 hardware monitoring driver (as seen on Freebox hardware)"
+	depends on I2C
+
+config SENSORS_AP806
+	tristate "Marvell AP806/CP110 hardware monitoring driver"
+
 if ACPI
 
 comment "ACPI drivers"
diff -ruw linux-6.4/drivers/hwmon/Makefile linux-6.4-fbx/drivers/hwmon/Makefile
--- linux-6.4/drivers/hwmon/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hwmon/Makefile	2023-11-29 17:07:09.604988488 +0100
@@ -74,6 +74,7 @@
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
+obj-$(CONFIG_SENSORS_FBXGWR_PMU)	+= fbxgwr_pmu_hwmon.o
 obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o
 obj-$(CONFIG_SENSORS_FSCHMD)	+= fschmd.o
 obj-$(CONFIG_SENSORS_FTSTEUTATES) += ftsteutates.o
@@ -102,6 +103,7 @@
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
 obj-$(CONFIG_SENSORS_LAN966X)	+= lan966x-hwmon.o
+obj-$(CONFIG_SENSORS_LD6710_FBX) += ld6710-fbx.o
 obj-$(CONFIG_SENSORS_LINEAGE)	+= lineage-pem.o
 obj-$(CONFIG_SENSORS_LOCHNAGAR)	+= lochnagar-hwmon.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
@@ -218,6 +220,8 @@
 obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
 obj-$(CONFIG_SENSORS_XGENE)	+= xgene-hwmon.o
+obj-$(CONFIG_SENSORS_KIRKWOOD_CORETEMP)+= kirkwood-coretemp.o
+obj-$(CONFIG_SENSORS_AP806)	+= ap806-hwmon.o
 
 obj-$(CONFIG_SENSORS_OCC)	+= occ/
 obj-$(CONFIG_SENSORS_PECI)	+= peci/
diff -ruw linux-6.4/drivers/hwmon/adt7475.c linux-6.4-fbx/drivers/hwmon/adt7475.c
--- linux-6.4/drivers/hwmon/adt7475.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hwmon/adt7475.c	2023-11-29 17:07:09.608321826 +0100
@@ -131,7 +131,19 @@
 
 /* Macro to read the registers */
 
-#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg))
+static inline s32 __adt7475_read(const struct i2c_client *client, u8 cmd)
+{
+	s32 ret;
+
+	ret = i2c_smbus_read_byte_data(client, cmd);
+	if (ret < 0) {
+		printk("__adt7475_read error: %d\n", ret);
+		return 0;
+	}
+	return ret;
+}
+
+#define adt7475_read(reg) __adt7475_read(client, (reg))
 
 /* Macros to easily index the registers */
 
diff -ruw linux-6.4/drivers/hwmon/lm85.c linux-6.4-fbx/drivers/hwmon/lm85.c
--- linux-6.4/drivers/hwmon/lm85.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/hwmon/lm85.c	2023-11-29 17:07:09.624988519 +0100
@@ -194,7 +194,7 @@
 };
 
 static const int adm1027_freq_map[] = { /* 1 Hz */
-	11, 15, 22, 29, 35, 44, 59, 88
+	11, 15, 22, 29, 35, 44, 59, 88, 88, 88, 25000
 };
 
 static int FREQ_TO_REG(const int *map,
@@ -1424,10 +1424,28 @@
 	.attrs = lm85_attributes_in567,
 };
 
-static void lm85_init_client(struct i2c_client *client)
+static void lm85_init_client(struct i2c_client *client, struct lm85_data *data)
 {
 	int value;
 
+	/* workaround for emc2300 (emc6d103s), when auto temp min is
+	 * the default value, pwm can never be controlled manually, so
+	 * change this */
+	if (data->type == emc6d103s) {
+		int nr;
+
+		for (nr = 0; nr < 3; nr++) {
+			data->zone[nr].limit = TEMP_TO_REG(-127000);
+			lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr),
+					 data->zone[nr].limit);
+
+			/* also force high frequency */
+			data->pwm_freq[nr] = 0xa;
+			lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
+					 data->pwm_freq[nr]);
+		}
+	}
+
 	/* Start monitoring if needed */
 	value = lm85_read_value(client, LM85_REG_CONFIG);
 	if (!(value & 0x01)) {
@@ -1589,7 +1607,7 @@
 	data->vrm = vid_which_vrm();
 
 	/* Initialize the LM85 chip */
-	lm85_init_client(client);
+	lm85_init_client(client, data);
 
 	/* sysfs hooks */
 	data->groups[idx++] = &lm85_group;
diff -ruw linux-6.4/drivers/i2c/busses/Kconfig linux-6.4-fbx/drivers/i2c/busses/Kconfig
--- linux-6.4/drivers/i2c/busses/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/i2c/busses/Kconfig	2023-11-29 17:07:09.661655242 +0100
@@ -1433,6 +1433,10 @@
 	  to SLIMpro (On chip coprocessor) mailbox mechanism.
 	  If unsure, say N.
 
+config I2C_WP3
+	tristate "Wintegra WP3 I2C controll"
+	depends on WINTEGRA_WINPATH3
+
 config SCx200_ACB
 	tristate "Geode ACCESS.bus support"
 	depends on X86_32 && PCI
diff -ruw linux-6.4/drivers/i2c/busses/Makefile linux-6.4-fbx/drivers/i2c/busses/Makefile
--- linux-6.4/drivers/i2c/busses/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/i2c/busses/Makefile	2023-11-29 17:07:09.661655242 +0100
@@ -129,6 +129,7 @@
 obj-$(CONFIG_I2C_XLP9XX)	+= i2c-xlp9xx.o
 obj-$(CONFIG_I2C_RCAR)		+= i2c-rcar.o
 obj-$(CONFIG_I2C_GXP)		+= i2c-gxp.o
+obj-$(CONFIG_I2C_WP3)		+= i2c-wp3.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_DIOLAN_U2C)	+= i2c-diolan-u2c.o
diff -ruw linux-6.4/drivers/i2c/busses/i2c-pxa-pci.c linux-6.4-fbx/drivers/i2c/busses/i2c-pxa-pci.c
--- linux-6.4/drivers/i2c/busses/i2c-pxa-pci.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/i2c/busses/i2c-pxa-pci.c	2023-11-29 17:07:09.674988596 +0100
@@ -9,6 +9,7 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/i2c-pxa.h>
 #include <linux/of.h>
@@ -41,6 +42,8 @@
 	res[1].start = dev->irq;
 	res[1].end = dev->irq;
 
+	child = NULL;
+	if (dev->dev.of_node) {
 	for_each_child_of_node(dev->dev.of_node, child) {
 		const void *prop;
 		struct resource r;
@@ -69,6 +72,9 @@
 		ret = -EINVAL;
 		goto out;
 	}
+	}
+
+	pdata.class = I2C_CLASS_HWMON;
 
 	pdev = platform_device_alloc("ce4100-i2c", devnum);
 	if (!pdev) {
@@ -109,10 +115,6 @@
 	if (ret)
 		return ret;
 
-	if (!dev->dev.of_node) {
-		dev_err(&dev->dev, "Missing device tree node.\n");
-		return -EINVAL;
-	}
 	sds = kzalloc(sizeof(*sds), GFP_KERNEL);
 	if (!sds)
 		return -ENOMEM;
diff -ruw linux-6.4/drivers/i2c/busses/i2c-pxa.c linux-6.4-fbx/drivers/i2c/busses/i2c-pxa.c
--- linux-6.4/drivers/i2c/busses/i2c-pxa.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/i2c/busses/i2c-pxa.c	2023-11-29 17:07:09.674988596 +0100
@@ -952,8 +952,14 @@
 		icr &= ~ICR_ALDIE;
 		icr |= ICR_START | ICR_TB;
 	} else {
-		if (i2c->msg->len == 0)
-			icr |= ICR_MA;
+		if (i2c->msg->len == 0) {
+			/*
+			 * Device probes have a message length of zero
+			 * and need the bus to be reset before it can
+			 * be used again.
+			 */
+			i2c_pxa_reset(i2c);
+		}
 		i2c_pxa_master_complete(i2c, 0);
 	}
 
@@ -1120,9 +1126,21 @@
 		ret = xfer(i2c, msgs, num);
 		if (ret != I2C_RETRY && ret != NO_SLAVE)
 			goto out;
-		if (++i >= i2c->adap.retries)
+
+		if (++i >= i2c->adap.retries &&
+		    (readl(_ISR(i2c)) & ISR_UB) &&
+		    (readl(_IBMR(i2c)) != 3)) {
+			/* last try and bus is still busy, try
+			 * reset */
+			dev_err(&i2c->adap.dev, "%s: unit still busy after "
+				"hw reset\n", __func__);
+			i2c_pxa_reset(i2c);
+		}
+
+		if (i >= i2c->adap.retries)
 			break;
 
+
 		if (i2c_debug)
 			dev_dbg(&i2c->adap.dev, "Retrying transmission\n");
 		udelay(100);
@@ -1405,8 +1423,13 @@
 
 	i2c->clk = devm_clk_get(&dev->dev, NULL);
 	if (IS_ERR(i2c->clk)) {
-		dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk));
-		return PTR_ERR(i2c->clk);
+		int ret = PTR_ERR(i2c->clk);
+
+		if (ret != -ENOENT) {
+			dev_err(&dev->dev, "failed to get the clk: %d\n", ret);
+			return ret;
+		}
+		i2c->clk = NULL;
 	}
 
 	i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
diff -ruw linux-6.4/drivers/i2c/i2c-core-base.c linux-6.4-fbx/drivers/i2c/i2c-core-base.c
--- linux-6.4/drivers/i2c/i2c-core-base.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/i2c/i2c-core-base.c	2023-11-29 17:07:09.681655273 +0100
@@ -249,12 +249,14 @@
 			bri->set_sda(adap, scl);
 		ndelay(RECOVERY_NDELAY / 2);
 
+		if (0) {
 		if (scl) {
 			ret = i2c_generic_bus_free(adap);
 			if (ret == 0)
 				break;
 		}
 	}
+	}
 
 	/* If we can't check bus status, assume recovery worked */
 	if (ret == -EOPNOTSUPP)
diff -ruw linux-6.4/drivers/input/misc/Kconfig linux-6.4-fbx/drivers/input/misc/Kconfig
--- linux-6.4/drivers/input/misc/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/input/misc/Kconfig	2023-11-29 17:07:09.901655615 +0100
@@ -939,4 +939,9 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called stpmic1_onkey.
 
+config INPUT_SMSC_CAP1066
+	tristate "SMSC CAP1066 capacitive sensor driver"
+	select I2C
+	select INPUT_POLLDEV
+
 endif
diff -ruw linux-6.4/drivers/input/misc/Makefile linux-6.4-fbx/drivers/input/misc/Makefile
--- linux-6.4/drivers/input/misc/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/input/misc/Makefile	2023-11-29 17:07:09.901655615 +0100
@@ -90,3 +90,4 @@
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
 obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR)	+= ideapad_slidebar.o
+obj-$(CONFIG_INPUT_SMSC_CAP1066)	+= smsc_cap1066.o
diff -ruw linux-6.4/drivers/leds/Kconfig linux-6.4-fbx/drivers/leds/Kconfig
--- linux-6.4/drivers/leds/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/leds/Kconfig	2023-11-29 17:07:09.988322417 +0100
@@ -328,6 +328,10 @@
 	  defined as platform devices and/or OpenFirmware platform devices.
 	  The code to use these bindings can be selected below.
 
+config LEDS_FBXGWR_PMU
+	tristate "Freebox GWR PMU LED controller"
+	depends on MFD_FBXGWR_PMU
+
 config LEDS_LP3944
 	tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
 	depends on LEDS_CLASS
@@ -710,6 +714,13 @@
 	  LED controllers. They are I2C devices with multiple constant-current
 	  channels, each with independent 256-level PWM control.
 
+config LEDS_IS31FL3299
+	tristate "LED support for ISSI IS31FL3299 I2C LED controller"
+	depends on LEDS_CLASS && I2C && OF
+	select REGMAP_I2C
+	help
+	  This option enables support for the IS31FL3299 LED driver.
+
 config LEDS_SC27XX_BLTC
 	tristate "LED support for the SC27xx breathing light controller"
 	depends on LEDS_CLASS && MFD_SC27XX_PMIC
@@ -859,6 +870,17 @@
 	  This option enables support for the Power Button LED of
 	  Acer Iconia Tab A500.
 
+config LEDS_LED1202
+	tristate "LED support for STMicroElectronics LED1202"
+	depends on LEDS_CLASS && I2C && OF
+	select REGMAP_I2C
+	help
+	  This option enables support for the LED1202 12-channel
+	  LED driver.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called leds-led1202.
+
 source "drivers/leds/blink/Kconfig"
 
 comment "Flash and Torch LED drivers"
diff -ruw linux-6.4/drivers/leds/Makefile linux-6.4-fbx/drivers/leds/Makefile
--- linux-6.4/drivers/leds/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/leds/Makefile	2023-11-29 17:07:09.988322417 +0100
@@ -28,12 +28,14 @@
 obj-$(CONFIG_LEDS_DA9052)		+= leds-da9052.o
 obj-$(CONFIG_LEDS_GPIO)			+= leds-gpio.o
 obj-$(CONFIG_LEDS_GPIO_REGISTER)	+= leds-gpio-register.o
+obj-$(CONFIG_LEDS_FBXGWR_PMU)		+= leds-fbxgwr-pmu.o
 obj-$(CONFIG_LEDS_HP6XX)		+= leds-hp6xx.o
 obj-$(CONFIG_LEDS_INTEL_SS4200)		+= leds-ss4200.o
 obj-$(CONFIG_LEDS_IP30)			+= leds-ip30.o
 obj-$(CONFIG_LEDS_IPAQ_MICRO)		+= leds-ipaq-micro.o
 obj-$(CONFIG_LEDS_IS31FL319X)		+= leds-is31fl319x.o
 obj-$(CONFIG_LEDS_IS31FL32XX)		+= leds-is31fl32xx.o
+obj-$(CONFIG_LEDS_IS31FL3299)		+= leds-is31fl3299.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
 obj-$(CONFIG_LEDS_LM3532)		+= leds-lm3532.o
 obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
@@ -85,6 +87,7 @@
 obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o
 obj-$(CONFIG_LEDS_WM8350)		+= leds-wm8350.o
 obj-$(CONFIG_LEDS_WRAP)			+= leds-wrap.o
+obj-$(CONFIG_LEDS_LED1202)		+= leds-led1202.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_CR0014114)		+= leds-cr0014114.o
diff -ruw linux-6.4/drivers/media/dvb-core/dvb_frontend.c linux-6.4-fbx/drivers/media/dvb-core/dvb_frontend.c
--- linux-6.4/drivers/media/dvb-core/dvb_frontend.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/media/dvb-core/dvb_frontend.c	2023-11-29 17:07:10.061655864 +0100
@@ -820,6 +820,7 @@
 	if (fe->exit != DVB_FE_DEVICE_REMOVED)
 		fe->exit = DVB_FE_NORMAL_EXIT;
 	mb();
+	wake_up_all(&fepriv->events.wait_queue);
 
 	if (!fepriv->thread)
 		return;
@@ -2755,6 +2756,9 @@
 
 	poll_wait(file, &fepriv->events.wait_queue, wait);
 
+	if (fe->exit)
+		return POLLERR | POLLHUP;
+
 	if (fepriv->events.eventw != fepriv->events.eventr)
 		return (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
 
diff -ruw linux-6.4/drivers/media/rc/ir-rc6-decoder.c linux-6.4-fbx/drivers/media/rc/ir-rc6-decoder.c
--- linux-6.4/drivers/media/rc/ir-rc6-decoder.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/media/rc/ir-rc6-decoder.c	2023-11-29 17:07:10.308322914 +0100
@@ -242,7 +242,6 @@
 				case RC6_6A_ZOTAC_CC:
 					protocol = RC_PROTO_RC6_MCE;
 					toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
-					scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
 					break;
 				default:
 					protocol = RC_PROTO_RC6_6A_32;
@@ -255,6 +254,7 @@
 				goto out;
 			}
 
+			scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
 			dev_dbg(&dev->dev, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
 				protocol, scancode, toggle);
 			break;
diff -ruw linux-6.4/drivers/media/rc/keymaps/Makefile linux-6.4-fbx/drivers/media/rc/keymaps/Makefile
--- linux-6.4/drivers/media/rc/keymaps/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/media/rc/keymaps/Makefile	2023-11-29 17:07:10.308322914 +0100
@@ -103,6 +103,7 @@
 			rc-purpletv.o \
 			rc-pv951.o \
 			rc-rc6-mce.o \
+			rc-rc6-freebox.o \
 			rc-real-audio-220-32-keys.o \
 			rc-reddo.o \
 			rc-snapstream-firefly.o \
diff -ruw linux-6.4/drivers/media/rc/mceusb.c linux-6.4-fbx/drivers/media/rc/mceusb.c
--- linux-6.4/drivers/media/rc/mceusb.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/media/rc/mceusb.c	2023-11-29 17:07:10.311656252 +0100
@@ -182,6 +182,7 @@
 	HAUPPAUGE_CX_HYBRID_TV,
 	EVROMEDIA_FULL_HYBRID_FULLHD,
 	ASTROMETA_T2HYBRID,
+	MCE_FREEBOX,
 };
 
 struct mceusb_model {
@@ -276,7 +277,12 @@
 		.name = "Astrometa T2Hybrid",
 		.no_tx = 1,
 		.rc_map = RC_MAP_ASTROMETA_T2HYBRID,
-	}
+	},
+	[MCE_FREEBOX] = {
+		.mce_gen2 = 1,
+		.no_tx = 1,
+		.rc_map = "rc-rc6-freebox",
+	},
 };
 
 static const struct usb_device_id mceusb_dev_table[] = {
@@ -375,7 +381,8 @@
 	/* Formosa Industrial Computing AIM IR605/A */
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
 	/* Formosa Industrial Computing */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e),
+	  .driver_info = MCE_FREEBOX },
 	/* Formosa Industrial Computing */
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe042) },
 	/* Fintek eHome Infrared Transceiver (HP branded) */
@@ -1203,7 +1210,7 @@
 	switch (subcmd) {
 	/* 2-byte return value commands */
 	case MCE_RSP_EQIRTIMEOUT:
-		ir->rc->timeout = (*hi << 8 | *lo) * MCE_TIME_UNIT;
+		ir->rc->timeout = (*hi << 8 | *lo) * MCE_TIME_UNIT / 1000;
 		break;
 	case MCE_RSP_EQIRNUMPORTS:
 		ir->num_txports = *hi;
@@ -1608,7 +1615,7 @@
 	rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
 	rc->rx_resolution = MCE_TIME_UNIT;
 	rc->min_timeout = MCE_TIME_UNIT;
-	rc->timeout = MS_TO_US(100);
+	rc->timeout = MS_TO_US(50);
 	if (!mceusb_model[ir->model].broken_irtimeout) {
 		rc->s_timeout = mceusb_set_timeout;
 		rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
diff -ruw linux-6.4/drivers/media/usb/dvb-usb/dib0700_devices.c linux-6.4-fbx/drivers/media/usb/dvb-usb/dib0700_devices.c
--- linux-6.4/drivers/media/usb/dvb-usb/dib0700_devices.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/media/usb/dvb-usb/dib0700_devices.c	2023-11-29 17:07:10.334989622 +0100
@@ -3897,6 +3897,7 @@
 	DIBCOM_STK8096PVR,
 	HAMA_DVBT_HYBRID,
 	MICROSOFT_XBOX_ONE_TUNER,
+	DIBCOM_HOOK_DEFAULT_STK7770P,
 };
 
 struct usb_device_id dib0700_usb_id_table[] = {
@@ -3987,6 +3988,7 @@
 	DVB_USB_DEV(DIBCOM, DIBCOM_STK8096PVR),
 	DVB_USB_DEV(HAMA, HAMA_DVBT_HYBRID),
 	DVB_USB_DEV(MICROSOFT, MICROSOFT_XBOX_ONE_TUNER),
+	DVB_USB_DEV(DIBCOM, DIBCOM_HOOK_DEFAULT_STK7770P),
 	{ }
 };
 
@@ -5230,6 +5232,30 @@
 				{ NULL },
 			},
 		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+			DIB0700_NUM_FRONTENDS(1),
+			.fe = {{
+				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter       = stk70x0p_pid_filter,
+				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = stk7770p_frontend_attach,
+				.tuner_attach     = dib7770p_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
+			},
+		},
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom STK7770P reference design no IR",
+				{ &dib0700_usb_id_table[DIBCOM_HOOK_DEFAULT_STK7770P], NULL },
+				{ NULL },
+			},
+		},
 	},
 };
 
diff -ruw linux-6.4/drivers/mfd/Kconfig linux-6.4-fbx/drivers/mfd/Kconfig
--- linux-6.4/drivers/mfd/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mfd/Kconfig	2023-11-29 17:07:10.381656361 +0100
@@ -2052,6 +2052,24 @@
 	  additional drivers must be enabled in order to use the functionality
 	  of the device.
 
+config MFD_FBXGW7R_PANEL
+	tristate "Freebox fbxgw7r panel support"
+	depends on FB
+	depends on SPI_MASTER
+	depends on OF
+	select FB_SYS_FOPS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_DEFERRED_IO
+
+config MFD_FBXGWR_PMU
+	tristate "Freebox fbxgwr PMU"
+	depends on I2C
+	depends on OF
+	select MFD_CORE
+	select REGMAP_I2C
+
 config MFD_WCD934X
 	tristate "Support for WCD9340/WCD9341 Codec"
 	depends on SLIMBUS
diff -ruw linux-6.4/drivers/mfd/Makefile linux-6.4-fbx/drivers/mfd/Makefile
--- linux-6.4/drivers/mfd/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mfd/Makefile	2023-11-29 17:07:10.381656361 +0100
@@ -270,6 +270,8 @@
 
 obj-$(CONFIG_MFD_ATC260X)	+= atc260x-core.o
 obj-$(CONFIG_MFD_ATC260X_I2C)	+= atc260x-i2c.o
+obj-$(CONFIG_MFD_FBXGW7R_PANEL)	+= fbxgw7r-panel.o
+obj-$(CONFIG_MFD_FBXGWR_PMU)	+= fbxgwr-pmu.o
 
 rsmu-i2c-objs			:= rsmu_core.o rsmu_i2c.o
 rsmu-spi-objs			:= rsmu_core.o rsmu_spi.o
diff -ruw linux-6.4/drivers/misc/Kconfig linux-6.4-fbx/drivers/misc/Kconfig
--- linux-6.4/drivers/misc/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/misc/Kconfig	2023-11-29 17:07:10.408323069 +0100
@@ -5,6 +5,9 @@
 
 menu "Misc devices"
 
+config WINTEGRA_MMAP
+	bool "wintegra mmap driver"
+
 config SENSORS_LIS3LV02D
 	tristate
 	depends on INPUT
@@ -403,6 +406,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called vmw_balloon.
 
+config INTELCE_PIC16PMU
+	tristate "PIC16 PMU, LED, hwmon support"
+	select INPUT_POLLDEV
+	select NEW_LEDS
+	select I2C
+	select HWMON
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Freebox v6 HD PIC16 PMU interface support, enables
+	  control of the on-board LEDs and reports the power status,
+	  reset status and button status.
+
 config PCH_PHUB
 	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
 	select GENERIC_NET_UTILS
@@ -424,6 +439,11 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called pch_phub.
 
+config FBXSERIAL_OF
+	bool "read fbxserial through DT chosen node"
+	depends on OF
+	select ARCH_HAS_FBXSERIAL
+
 config LATTICE_ECP3_CONFIG
 	tristate "Lattice ECP3 FPGA bitstream configuration via SPI"
 	depends on SPI && SYSFS
@@ -538,6 +558,9 @@
 
 	  Say N here unless you know what you are doing.
 
+config DGASP
+	bool "dying gasp infrastructure"
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
@@ -555,4 +578,6 @@
 source "drivers/misc/uacce/Kconfig"
 source "drivers/misc/pvpanic/Kconfig"
 source "drivers/misc/mchp_pci1xxxx/Kconfig"
+source "drivers/misc/remoti/Kconfig"
+source "drivers/misc/hdmi-cec/Kconfig"
 endmenu
diff -ruw linux-6.4/drivers/misc/Makefile linux-6.4-fbx/drivers/misc/Makefile
--- linux-6.4/drivers/misc/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/misc/Makefile	2023-11-29 17:07:10.408323069 +0100
@@ -3,6 +3,7 @@
 # Makefile for misc devices that really don't fit anywhere else.
 #
 
+obj-$(CONFIG_WINTEGRA_MMAP)	+= wintegra_mmap.o
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_IBMVMC)		+= ibmvmc.o
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
@@ -21,7 +22,9 @@
 obj-$(CONFIG_SENSORS_APDS990X)	+= apds990x.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
+obj-$(CONFIG_FBXSERIAL_OF)	+= fbxserial_of.o
 obj-$(CONFIG_SGI_XP)		+= sgi-xp/
+obj-$(CONFIG_INTELCE_PIC16PMU)	+= pic16-pmu.o
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
 obj-$(CONFIG_SMPRO_ERRMON)	+= smpro-errmon.o
 obj-$(CONFIG_SMPRO_MISC)	+= smpro-misc.o
@@ -39,6 +42,7 @@
 obj-y				+= cb710/
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
 obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
+obj-y				+= hdmi-cec/
 obj-y				+= ti-st/
 obj-y				+= lis3lv02d/
 obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
@@ -65,3 +69,5 @@
 obj-$(CONFIG_VCPU_STALL_DETECTOR)	+= vcpu_stall_detector.o
 obj-$(CONFIG_TMR_MANAGER)      += xilinx_tmr_manager.o
 obj-$(CONFIG_TMR_INJECT)	+= xilinx_tmr_inject.o
+obj-y				+= remoti/
+obj-$(CONFIG_DGASP)		+= dgasp.o
diff -ruw linux-6.4/drivers/misc/eeprom/Kconfig linux-6.4-fbx/drivers/misc/eeprom/Kconfig
--- linux-6.4/drivers/misc/eeprom/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/misc/eeprom/Kconfig	2023-11-29 17:07:10.418323085 +0100
@@ -131,4 +131,8 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called ee1004.
 
+config EEPROM_EE1004_RAW
+	tristate "SPD EEPROMs on DDR4 memory modules (non smbus)"
+	depends on I2C && SYSFS
+
 endmenu
diff -ruw linux-6.4/drivers/misc/eeprom/Makefile linux-6.4-fbx/drivers/misc/eeprom/Makefile
--- linux-6.4/drivers/misc/eeprom/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/misc/eeprom/Makefile	2020-02-08 00:30:20.208489446 +0100
@@ -8,3 +8,4 @@
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
 obj-$(CONFIG_EEPROM_IDT_89HPESX) += idt_89hpesx.o
 obj-$(CONFIG_EEPROM_EE1004)	+= ee1004.o
+obj-$(CONFIG_EEPROM_EE1004_RAW)	+= ee1004_raw.o
diff -ruw linux-6.4/drivers/mmc/host/Kconfig linux-6.4-fbx/drivers/mmc/host/Kconfig
--- linux-6.4/drivers/mmc/host/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mmc/host/Kconfig	2023-11-29 17:07:10.444989793 +0100
@@ -997,7 +997,7 @@
 
 config MMC_SDHCI_BRCMSTB
 	tristate "Broadcom SDIO/SD/MMC support"
-	depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
+	depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCMBCA || COMPILE_TEST
 	depends on MMC_SDHCI_PLTFM
 	select MMC_CQHCI
 	default ARCH_BRCMSTB || BMIPS_GENERIC
diff -ruw linux-6.4/drivers/mtd/Kconfig linux-6.4-fbx/drivers/mtd/Kconfig
--- linux-6.4/drivers/mtd/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/Kconfig	2022-08-30 19:20:26.159578782 +0200
@@ -23,6 +23,9 @@
 	  WARNING: some of the tests will ERASE entire MTD device which they
 	  test. Do not use these tests unless you really know what you do.
 
+config MTD_ERASE_PRINTK
+	bool "write to kernel log when a block is erased"
+
 menu "Partition parsers"
 source "drivers/mtd/parsers/Kconfig"
 endmenu
diff -ruw linux-6.4/drivers/mtd/mtdchar.c linux-6.4-fbx/drivers/mtd/mtdchar.c
--- linux-6.4/drivers/mtd/mtdchar.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/mtdchar.c	2023-11-29 17:07:10.474989840 +0100
@@ -168,6 +168,7 @@
 		{
 			struct mtd_oob_ops ops = {};
 
+			memset(&ops, 0, sizeof (ops));
 			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
@@ -262,6 +263,7 @@
 		{
 			struct mtd_oob_ops ops = {};
 
+			memset(&ops, 0, sizeof (ops));
 			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
@@ -947,6 +949,11 @@
 				erase->len = einfo32.length;
 			}
 
+#ifdef CONFIG_MTD_ERASE_PRINTK
+			printk(KERN_DEBUG "mtd: %s: ERASE offset=@%08llx\n",
+			       mtd->name, erase->addr);
+#endif
+
 			ret = mtd_erase(mtd, erase);
 			kfree(erase);
 		}
diff -ruw linux-6.4/drivers/mtd/mtdcore.c linux-6.4-fbx/drivers/mtd/mtdcore.c
--- linux-6.4/drivers/mtd/mtdcore.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/mtdcore.c	2023-11-29 17:07:10.474989840 +0100
@@ -308,6 +308,56 @@
 }
 MTD_DEVICE_ATTR_RO(bbt_blocks);
 
+static ssize_t mtd_nand_type_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", mtd->nand_type);
+}
+static DEVICE_ATTR(nand_type, S_IRUGO, mtd_nand_type_show, NULL);
+
+static ssize_t mtd_nand_manufacturer_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", mtd->nand_manufacturer);
+}
+static DEVICE_ATTR(nand_manufacturer, S_IRUGO, mtd_nand_manufacturer_show, NULL);
+
+static ssize_t mtd_nand_onfi_ecc_bits_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", mtd->onfi_ecc_bits);
+}
+static DEVICE_ATTR(onfi_ecc_bits, S_IRUGO, mtd_nand_onfi_ecc_bits_show, NULL);
+
+static ssize_t mtd_nand_onfi_model_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			mtd->onfi_model ? mtd->onfi_model : "unknown");
+}
+static DEVICE_ATTR(onfi_model, S_IRUGO, mtd_nand_onfi_model_show, NULL);
+
+static ssize_t mtd_nand_ids_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%02x%02x%02x%02x%02x%02x%02x%02x\n",
+			mtd->nand_ids[0], mtd->nand_ids[1],
+			mtd->nand_ids[2], mtd->nand_ids[3],
+			mtd->nand_ids[4], mtd->nand_ids[5],
+			mtd->nand_ids[6], mtd->nand_ids[7]);
+}
+static DEVICE_ATTR(nand_ids, S_IRUGO, mtd_nand_ids_show, NULL);
+
 static struct attribute *mtd_attrs[] = {
 	&dev_attr_type.attr,
 	&dev_attr_flags.attr,
@@ -326,6 +376,11 @@
 	&dev_attr_bad_blocks.attr,
 	&dev_attr_bbt_blocks.attr,
 	&dev_attr_bitflip_threshold.attr,
+	&dev_attr_nand_type.attr,
+	&dev_attr_nand_manufacturer.attr,
+	&dev_attr_onfi_ecc_bits.attr,
+	&dev_attr_onfi_model.attr,
+	&dev_attr_nand_ids.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(mtd);
diff -ruw linux-6.4/drivers/mtd/mtdpart.c linux-6.4-fbx/drivers/mtd/mtdpart.c
--- linux-6.4/drivers/mtd/mtdpart.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/mtdpart.c	2023-11-29 17:07:10.478323178 +0100
@@ -68,6 +68,11 @@
 	child->oobsize = parent->oobsize;
 	child->oobavail = parent->oobavail;
 	child->subpage_sft = parent->subpage_sft;
+	child->nand_type = parent->nand_type;
+	child->nand_manufacturer = parent->nand_manufacturer;
+	child->onfi_ecc_bits = parent->onfi_ecc_bits;
+	child->onfi_model = parent->onfi_model;
+	memcpy(child->nand_ids, parent->nand_ids, 8);
 
 	child->name = name;
 	child->owner = parent->owner;
diff -ruw linux-6.4/drivers/mtd/nand/ecc-sw-bch.c linux-6.4-fbx/drivers/mtd/nand/ecc-sw-bch.c
--- linux-6.4/drivers/mtd/nand/ecc-sw-bch.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/ecc-sw-bch.c	2022-08-30 19:20:26.175578963 +0200
@@ -67,7 +67,8 @@
 				 errloc[i]);
 		}
 	} else if (count < 0) {
-		pr_err("ECC unrecoverable error\n");
+		if (printk_ratelimit())
+			pr_err("ecc unrecoverable error\n");
 		count = -EBADMSG;
 	}
 
diff -ruw linux-6.4/drivers/mtd/nand/ecc-sw-hamming.c linux-6.4-fbx/drivers/mtd/nand/ecc-sw-hamming.c
--- linux-6.4/drivers/mtd/nand/ecc-sw-hamming.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/ecc-sw-hamming.c	2023-11-29 17:07:10.478323178 +0100
@@ -437,6 +437,7 @@
 	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
 		return 1;	/* error in ECC data; no action needed */
 
+	if (printk_ratelimit())
 	pr_err("%s: uncorrectable ECC error\n", __func__);
 	return -EBADMSG;
 }
diff -ruw linux-6.4/drivers/mtd/nand/raw/Kconfig linux-6.4-fbx/drivers/mtd/nand/raw/Kconfig
--- linux-6.4/drivers/mtd/nand/raw/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/raw/Kconfig	2023-11-29 17:07:10.481656517 +0100
@@ -12,6 +12,14 @@
 
 comment "Raw/parallel NAND flash controllers"
 
+config MTD_FORCE_BAD_BLOCK_ERASE
+	bool "Force erase on bad blocks (useful for bootloader parts)"
+	default n
+	help
+	  Enable this option only when you need to force an erase on
+	  blocks being marked as "bad" by Linux (i.e: other ECC/bad block
+	  marker layout).
+
 config MTD_NAND_DENALI
 	tristate
 
@@ -31,6 +39,18 @@
 	  Enable the driver for NAND flash on platforms using a Denali NAND
 	  controller as a DT device.
 
+config MTD_NAND_DENALI_FBX
+	tristate "NAND Denali controller support"
+	depends on PCI
+	select BCH_CONST_PARAMS
+
+if MTD_NAND_DENALI_FBX
+	config BCH_CONST_M
+		default 13
+	config BCH_CONST_T
+		default 4
+endif
+
 config MTD_NAND_AMS_DELTA
 	tristate "Amstrad E3 NAND controller"
 	depends on MACH_AMS_DELTA || COMPILE_TEST
diff -ruw linux-6.4/drivers/mtd/nand/raw/Makefile linux-6.4-fbx/drivers/mtd/nand/raw/Makefile
--- linux-6.4/drivers/mtd/nand/raw/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/raw/Makefile	2023-11-29 17:07:10.481656517 +0100
@@ -8,6 +8,7 @@
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
 obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
 obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= denali_dt.o
+obj-$(CONFIG_MTD_NAND_DENALI_FBX)	+= denali_nand.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_S3C2410)		+= s3c2410.o
 obj-$(CONFIG_MTD_NAND_DAVINCI)		+= davinci_nand.o
diff -ruw linux-6.4/drivers/mtd/nand/raw/nand_base.c linux-6.4-fbx/drivers/mtd/nand/raw/nand_base.c
--- linux-6.4/drivers/mtd/nand/raw/nand_base.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/raw/nand_base.c	2023-11-29 17:07:10.491656532 +0100
@@ -4609,6 +4609,7 @@
 		loff_t ofs = (loff_t)page << chip->page_shift;
 
 		/* Check if we have a bad block, we do not erase bad blocks! */
+#ifndef CONFIG_MTD_FORCE_BAD_BLOCK_ERASE
 		if (nand_block_checkbad(chip, ((loff_t) page) <<
 					chip->page_shift, allowbbt)) {
 			pr_warn("%s: attempt to erase a bad block at 0x%08llx\n",
@@ -4616,6 +4617,7 @@
 			ret = -EIO;
 			goto erase_exit;
 		}
+#endif
 
 		/*
 		 * Invalidate the page cache, if we erase the block which
@@ -5312,6 +5314,15 @@
 	pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
 		(int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
 		mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
+
+	mtd->nand_type = chip->parameters.model;
+	mtd->nand_manufacturer = nand_manufacturer_name(manufacturer_desc);
+	if (chip->parameters.onfi) {
+		mtd->onfi_ecc_bits = chip->ecc.strength;
+		mtd->onfi_model = chip->parameters.model;
+	}
+	memcpy(mtd->nand_ids, id_data, 8);
+
 	return 0;
 
 free_detect_allocation:
@@ -5842,7 +5853,9 @@
 			ecc->read_page_raw = nand_read_page_raw;
 		if (!ecc->write_page_raw)
 			ecc->write_page_raw = nand_write_page_raw;
+		if (!ecc->read_oob)
 		ecc->read_oob = nand_read_oob_std;
+		if (!ecc->write_oob)
 		ecc->write_oob = nand_write_oob_std;
 		if (!ecc->size)
 			ecc->size = 256;
@@ -5873,7 +5886,9 @@
 			ecc->read_page_raw = nand_read_page_raw;
 		if (!ecc->write_page_raw)
 			ecc->write_page_raw = nand_write_page_raw;
+		if (!ecc->read_oob)
 		ecc->read_oob = nand_read_oob_std;
+		if (!ecc->write_oob)
 		ecc->write_oob = nand_write_oob_std;
 
 		/*
@@ -6410,7 +6425,7 @@
 	/* Large page NAND with SOFT_ECC should support subpage reads */
 	switch (ecc->engine_type) {
 	case NAND_ECC_ENGINE_TYPE_SOFT:
-		if (chip->page_shift > 9)
+		if (chip->page_shift > 9 && !(chip->options & NAND_NO_RNDOUT))
 			chip->options |= NAND_SUBPAGE_READ;
 		break;
 
diff -ruw linux-6.4/drivers/mtd/nand/raw/nand_ids.c linux-6.4-fbx/drivers/mtd/nand/raw/nand_ids.c
--- linux-6.4/drivers/mtd/nand/raw/nand_ids.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/raw/nand_ids.c	2023-11-29 17:07:10.491656532 +0100
@@ -55,12 +55,18 @@
 		{ .id = {0xad, 0xde, 0x14, 0xa7, 0x42, 0x4a} },
 		  SZ_16K, SZ_8K, SZ_4M, NAND_NEED_SCRAMBLING, 6, 1664,
 		  NAND_ECC_INFO(40, SZ_1K) },
+	{"TC58NVG1S3EBAI4 256MiB 3.3V 8-bit",
+		{ .id = {0x98, 0xda, 0x90, 0x15, 0x76, 0x14, 0x03} },
+		  SZ_2K, SZ_256, SZ_128K, 0, 7, 64, NAND_ECC_INFO(1, SZ_512) },
 	{"TH58NVG2S3HBAI4 4G 3.3V 8-bit",
 		{ .id = {0x98, 0xdc, 0x91, 0x15, 0x76} },
 		  SZ_2K, SZ_512, SZ_128K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) },
 	{"TH58NVG3S0HBAI4 8G 3.3V 8-bit",
 		{ .id = {0x98, 0xd3, 0x91, 0x26, 0x76} },
 		  SZ_4K, SZ_1K, SZ_256K, 0, 5, 256, NAND_ECC_INFO(8, SZ_512)},
+	{"K9F2G08U0C 256MiB 3.3V 8-bit",
+		{ .id = {0xec, 0xda, 0x10, 0x95, 0x44} },
+		  SZ_2K, SZ_256, SZ_128K, 0, 5, 64, NAND_ECC_INFO(1, SZ_512) },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff -ruw linux-6.4/drivers/mtd/nand/raw/nand_samsung.c linux-6.4-fbx/drivers/mtd/nand/raw/nand_samsung.c
--- linux-6.4/drivers/mtd/nand/raw/nand_samsung.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/raw/nand_samsung.c	2022-09-28 14:08:49.904733886 +0200
@@ -118,6 +118,38 @@
 	nanddev_set_ecc_requirements(base, &requirements);
 }
 
+static int
+k9f2g08u0c_choose_interface_config(struct nand_chip *chip,
+				   struct nand_interface_config *iface)
+{
+	struct nand_sdr_timings *sdr = &iface->timings.sdr;
+
+	/* Start with timings from the closest timing mode, mode 4. */
+	onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4);
+
+	/* Patch timings that differ from mode 4. */
+	sdr->tR_max = 40000000;
+	sdr->tALS_min = 12000;
+	sdr->tCLS_min = 12000;
+	sdr->tDS_min = 12000;
+	sdr->tREH_min = 15000;
+	sdr->tWHR_min = 60000;
+
+	/* Patch timings not part of onfi timing mode. */
+	sdr->tPROG_max = 750000000;
+	sdr->tBERS_max = 10000000000ULL;
+
+	return nand_choose_best_sdr_timings(chip, iface, sdr);
+}
+
+static int k9f2g08u0c_init(struct nand_chip *chip)
+{
+	chip->ops.choose_interface_config =
+		&k9f2g08u0c_choose_interface_config;
+
+	return 0;
+}
+
 static int samsung_nand_init(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
@@ -130,6 +162,10 @@
 	else
 		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
 
+	if (!strncmp("K9F2G08U0C", chip->parameters.model,
+		     sizeof("K9F2G08U0C") - 1))
+		k9f2g08u0c_init(chip);
+
 	return 0;
 }
 
diff -ruw linux-6.4/drivers/mtd/nand/raw/nand_toshiba.c linux-6.4-fbx/drivers/mtd/nand/raw/nand_toshiba.c
--- linux-6.4/drivers/mtd/nand/raw/nand_toshiba.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/nand/raw/nand_toshiba.c	2023-11-29 17:07:10.491656532 +0100
@@ -217,6 +217,34 @@
 }
 
 static int
+tc58nvg1s3ebai4_choose_interface_config(struct nand_chip *chip,
+					struct nand_interface_config *iface)
+{
+	struct nand_sdr_timings *sdr = &iface->timings.sdr;
+
+	/* Start with timings from the closest timing mode, mode 4. */
+	onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4);
+
+	/* Patch timings that differ from mode 4. */
+	sdr->tR_max = 25000000;
+	sdr->tALS_min = 12000;
+	sdr->tCHZ_max = 20000;
+	sdr->tCLS_min = 12000;
+	sdr->tCOH_min = 0;
+	sdr->tDS_min = 12000;
+	sdr->tRHOH_min = 22000;
+	sdr->tRHW_min = 30000;
+	sdr->tRHZ_max = 60000;
+	sdr->tWHR_min = 60000;
+
+	/* Patch timings not part of onfi timing mode. */
+	sdr->tPROG_max = 700000000;
+	sdr->tBERS_max = 10000000000ULL;
+
+	return nand_choose_best_sdr_timings(chip, iface, sdr);
+}
+
+static int
 th58nvg2s3hbai4_choose_interface_config(struct nand_chip *chip,
 					struct nand_interface_config *iface)
 {
@@ -263,6 +291,14 @@
 	return 0;
 }
 
+static int tc58nvg1s3ebai4_init(struct nand_chip *chip)
+{
+	chip->ops.choose_interface_config =
+		&tc58nvg1s3ebai4_choose_interface_config;
+
+	return 0;
+}
+
 static int th58nvg2s3hbai4_init(struct nand_chip *chip)
 {
 	chip->ops.choose_interface_config =
@@ -287,6 +323,9 @@
 	if (!strncmp("TC58NVG0S3E", chip->parameters.model,
 		     sizeof("TC58NVG0S3E") - 1))
 		tc58nvg0s3e_init(chip);
+	if (!strncmp("TC58NVG1S3EBAI4", chip->parameters.model,
+		     sizeof("TC58NVG1S3EBAI4") - 1))
+		tc58nvg1s3ebai4_init(chip);
 	if ((!strncmp("TH58NVG2S3HBAI4", chip->parameters.model,
 		     sizeof("TH58NVG2S3HBAI4") - 1)) ||
 	    (!strncmp("TH58NVG3S0HBAI4", chip->parameters.model,
diff -ruw linux-6.4/drivers/mtd/parsers/Kconfig linux-6.4-fbx/drivers/mtd/parsers/Kconfig
--- linux-6.4/drivers/mtd/parsers/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/parsers/Kconfig	2023-11-29 17:07:10.498323209 +0100
@@ -96,6 +96,10 @@
 	  two "firmware" partitions. Currently used firmware has to be detected
 	  using CFE environment variable.
 
+config MTD_OF_PARTS_IGNORE_RO
+	bool "ignore read-only flag"
+	depends on MTD_OF_PARTS
+
 config MTD_PARSER_IMAGETAG
 	tristate "Parser for BCM963XX Image Tag format partitions"
 	depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
@@ -220,3 +224,14 @@
 	  partition map. This partition table contains real partition
 	  offsets, which may differ from device to device depending on the
 	  number and location of bad blocks on NAND.
+
+config MTD_FBX6HD_PARTS
+	tristate "Freebox V6 HD partitioning support"
+	help
+	  Freebox V6 HD partitioning support
+
+config MTD_FBX6HD_PARTS_WRITE_ALL
+	bool "make all partitions writeable"
+	depends on MTD_FBX6HD_PARTS
+	help
+	  Freebox V6 HD partitions support
diff -ruw linux-6.4/drivers/mtd/parsers/Makefile linux-6.4-fbx/drivers/mtd/parsers/Makefile
--- linux-6.4/drivers/mtd/parsers/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/parsers/Makefile	2023-11-29 17:07:10.501656548 +0100
@@ -16,3 +16,4 @@
 obj-$(CONFIG_MTD_SHARPSL_PARTS)		+= sharpslpart.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS)		+= redboot.o
 obj-$(CONFIG_MTD_QCOMSMEM_PARTS)	+= qcomsmempart.o
+obj-$(CONFIG_MTD_FBX6HD_PARTS)	+= fbx6hd-mtdparts.o
diff -ruw linux-6.4/drivers/mtd/parsers/ofpart_core.c linux-6.4-fbx/drivers/mtd/parsers/ofpart_core.c
--- linux-6.4/drivers/mtd/parsers/ofpart_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/mtd/parsers/ofpart_core.c	2023-11-29 17:07:10.501656548 +0100
@@ -157,8 +157,10 @@
 			partname = of_get_property(pp, "name", &len);
 		parts[i].name = partname;
 
+#ifndef CONFIG_MTD_OF_PARTS_IGNORE_RO
 		if (of_get_property(pp, "read-only", &len))
 			parts[i].mask_flags |= MTD_WRITEABLE;
+#endif
 
 		if (of_get_property(pp, "lock", &len))
 			parts[i].mask_flags |= MTD_POWERUP_LOCK;
diff -ruw linux-6.4/drivers/net/ethernet/Kconfig linux-6.4-fbx/drivers/net/ethernet/Kconfig
--- linux-6.4/drivers/net/ethernet/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/Kconfig	2023-11-29 17:07:10.571656656 +0100
@@ -190,6 +190,7 @@
 source "drivers/net/ethernet/via/Kconfig"
 source "drivers/net/ethernet/wangxun/Kconfig"
 source "drivers/net/ethernet/wiznet/Kconfig"
+source "drivers/net/ethernet/wintegra/Kconfig"
 source "drivers/net/ethernet/xilinx/Kconfig"
 source "drivers/net/ethernet/xircom/Kconfig"
 
diff -ruw linux-6.4/drivers/net/ethernet/Makefile linux-6.4-fbx/drivers/net/ethernet/Makefile
--- linux-6.4/drivers/net/ethernet/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/Makefile	2023-11-29 17:07:10.571656656 +0100
@@ -100,6 +100,7 @@
 obj-$(CONFIG_NET_VENDOR_VIA) += via/
 obj-$(CONFIG_NET_VENDOR_WANGXUN) += wangxun/
 obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
+obj-$(CONFIG_NET_VENDOR_WINTEGRA) += wintegra/
 obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
 obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
 obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
diff -ruw linux-6.4/drivers/net/ethernet/broadcom/Kconfig linux-6.4-fbx/drivers/net/ethernet/broadcom/Kconfig
--- linux-6.4/drivers/net/ethernet/broadcom/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/broadcom/Kconfig	2023-11-29 17:07:10.604990042 +0100
@@ -68,6 +68,39 @@
 	  This driver supports the ethernet MACs in the Broadcom 63xx
 	  MIPS chipset family (BCM63XX).
 
+config BCM63XX_ENET_RUNNER
+	tristate "Broadcom 63xx (63138) runner ethernet support"
+	select MII
+	select FIXED_PHY
+	select PHYLIB
+	select BCM7XXX_PHY
+	select BROADCOM_PHY
+	select SOC_BCM63XX_RDP
+
+config BCM63158_SF2
+	tristate "Broadcom 63158 SF2 support"
+	select MII
+	select PHYLINK
+	select BCM7XXX_PHY
+	select BROADCOM_PHY
+	select NET_DSA
+	select NET_DSA_TAG_BRCM_FBX
+
+config BCM63158_ENET_RUNNER
+	tristate "Broadcom 63158 runner ethernet support"
+	select MII
+	select PHYLINK
+	select SOC_BCM63XX_XRDP
+
+config BCM63158_ENET_RUNNER_FF
+	bool "fastpath support for freebox boards"
+	depends on BCM63158_ENET_RUNNER
+	select IP_FFN
+	select IPV6_FFN
+	select IPV6_SIT_6RD
+	select BRIDGE
+	select FBXBRIDGE
+
 config BCMGENET
 	tristate "Broadcom GENET internal MAC support"
 	depends on HAS_IOMEM
diff -ruw linux-6.4/drivers/net/ethernet/broadcom/Makefile linux-6.4-fbx/drivers/net/ethernet/broadcom/Makefile
--- linux-6.4/drivers/net/ethernet/broadcom/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/broadcom/Makefile	2022-08-31 16:27:50.672428989 +0200
@@ -17,3 +17,5 @@
 obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o
 obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
 obj-$(CONFIG_BNXT) += bnxt/
+obj-$(CONFIG_BCM63XX_ENET_RUNNER) += bcm63xx_enet_runner/
+obj-y += bcm63158/
diff -ruw linux-6.4/drivers/net/ethernet/intel/e1000/e1000.h linux-6.4-fbx/drivers/net/ethernet/intel/e1000/e1000.h
--- linux-6.4/drivers/net/ethernet/intel/e1000/e1000.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/intel/e1000/e1000.h	2022-08-30 19:20:26.707584973 +0200
@@ -42,6 +42,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#include <linux/gpio/consumer.h>
 
 #define BAR_0		0
 #define BAR_1		1
@@ -299,6 +300,10 @@
 	struct delayed_work watchdog_task;
 	struct delayed_work fifo_stall_task;
 	struct delayed_work phy_info_task;
+
+	struct gpio_desc *phy_link_gpio;
+	int phy_link_gpio_lastval;
+	bool last_link_active;
 };
 
 enum e1000_state_t {
diff -ruw linux-6.4/drivers/net/ethernet/intel/e1000/e1000_main.c linux-6.4-fbx/drivers/net/ethernet/intel/e1000/e1000_main.c
--- linux-6.4/drivers/net/ethernet/intel/e1000/e1000_main.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/intel/e1000/e1000_main.c	2023-11-29 17:07:10.758323613 +0100
@@ -7,6 +7,8 @@
 #include <linux/prefetch.h>
 #include <linux/bitops.h>
 #include <linux/if_vlan.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
 
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
@@ -920,10 +922,11 @@
  **/
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	struct device_node *np;
 	struct net_device *netdev;
 	struct e1000_adapter *adapter = NULL;
 	struct e1000_hw *hw;
-
+	struct gpio_desc *phy_link_gpio;
 	static int cards_found;
 	static int global_quad_port_a; /* global ksp3 port a indication */
 	int i, err, pci_using_dac;
@@ -933,6 +936,26 @@
 	int bars, need_ioport;
 	bool disable_dev = false;
 
+	phy_link_gpio = NULL;
+	np = pci_device_to_OF_node(pdev);
+	if (np) {
+		phy_link_gpio = fwnode_gpiod_get_index(&np->fwnode,
+						       "phy-link", 0,
+						       GPIOD_IN,
+						       "e1000-phy-link");
+		if (IS_ERR(phy_link_gpio)) {
+			err = PTR_ERR(phy_link_gpio);
+			if (err == -EPROBE_DEFER)
+				return err;
+
+			if (err != -ENOENT) {
+				dev_err(&pdev->dev,
+					"could not get phy-link: %d\n", err);
+				return err;
+			}
+		}
+	}
+
 	/* do not allocate ioport bars when not needed */
 	need_ioport = e1000_is_need_ioport(pdev);
 	if (need_ioport) {
@@ -968,6 +991,8 @@
 	adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 	adapter->bars = bars;
 	adapter->need_ioport = need_ioport;
+	adapter->phy_link_gpio = phy_link_gpio;
+	adapter->phy_link_gpio_lastval = -1;
 
 	hw = &adapter->hw;
 	hw->back = adapter;
@@ -1085,6 +1110,13 @@
 
 	e1000_reset_hw(hw);
 
+	if (np) {
+		int err = of_get_mac_address(np, hw->mac_addr);
+
+		if (!err)
+			goto eeprom_ok;
+	}
+
 	/* make sure the EEPROM is good */
 	if (e1000_validate_eeprom_checksum(hw) < 0) {
 		e_err(probe, "The EEPROM Checksum Is Not Valid\n");
@@ -1102,6 +1134,8 @@
 		if (e1000_read_mac_addr(hw))
 			e_err(probe, "EEPROM Read Error\n");
 	}
+
+eeprom_ok:
 	/* don't block initialization here due to bad MAC address */
 	eth_hw_addr_set(netdev, hw->mac_addr);
 
@@ -1205,14 +1239,15 @@
 	e1000_vlan_filter_on_off(adapter, false);
 
 	/* print bus type/speed/width info */
-	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
+	e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM %s\n",
 	       ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
 	       ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
 		(hw->bus_speed == e1000_bus_speed_120) ? 120 :
 		(hw->bus_speed == e1000_bus_speed_100) ? 100 :
 		(hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
 	       ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
-	       netdev->dev_addr);
+	       netdev->dev_addr,
+	       adapter->phy_link_gpio ? "phy-link-gpio set" : "");
 
 	/* carrier off reporting is important to ethtool even BEFORE open */
 	netif_carrier_off(netdev);
@@ -1280,6 +1315,10 @@
 	pci_release_selected_regions(pdev, adapter->bars);
 
 	disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags);
+
+	if (adapter->phy_link_gpio)
+		gpiod_put(adapter->phy_link_gpio);
+
 	free_netdev(netdev);
 
 	if (disable_dev)
@@ -2387,6 +2426,18 @@
 	struct e1000_hw *hw = &adapter->hw;
 	bool link_active = false;
 
+	if (adapter->phy_link_gpio) {
+		bool changed;
+		int val;
+
+		val = gpiod_get_value(adapter->phy_link_gpio);
+		changed = (val != adapter->phy_link_gpio_lastval);
+		adapter->phy_link_gpio_lastval = val;
+
+		if (!changed)
+			return adapter->last_link_active;
+	}
+
 	/* get_link_status is set on LSC (link status) interrupt or rx
 	 * sequence error interrupt (except on intel ce4100).
 	 * get_link_status will stay false until the
@@ -2395,6 +2446,7 @@
 	 */
 	switch (hw->media_type) {
 	case e1000_media_type_copper:
+	{
 		if (hw->mac_type == e1000_ce4100)
 			hw->get_link_status = 1;
 		if (hw->get_link_status) {
@@ -2404,6 +2456,8 @@
 			link_active = true;
 		}
 		break;
+	}
+
 	case e1000_media_type_fiber:
 		e1000_check_for_link(hw);
 		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
@@ -2416,6 +2470,7 @@
 		break;
 	}
 
+	adapter->last_link_active = link_active;
 	return link_active;
 }
 
@@ -3715,7 +3770,8 @@
 
 	/* Phy Stats */
 	if (hw->media_type == e1000_media_type_copper) {
-		if ((adapter->link_speed == SPEED_1000) &&
+		if (!adapter->phy_link_gpio &&
+		    (adapter->link_speed == SPEED_1000) &&
 		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
 			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
 			adapter->phy_stats.idle_errors += phy_tmp;
diff -ruw linux-6.4/drivers/net/ethernet/marvell/Kconfig linux-6.4-fbx/drivers/net/ethernet/marvell/Kconfig
--- linux-6.4/drivers/net/ethernet/marvell/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/marvell/Kconfig	2023-11-29 17:07:10.848323753 +0100
@@ -23,6 +23,7 @@
 	depends on INET
 	select PHYLIB
 	select MVMDIO
+	select MII
 	help
 	  This driver supports the gigabit ethernet MACs in the
 	  Marvell Discovery PPC/MIPS chipset family (MV643XX) and
@@ -31,6 +32,15 @@
 	  Some boards that use the Discovery chipset are the Momenco
 	  Ocelot C and Jaguar ATX and Pegasos II.
 
+config MV643XX_ETH_FBX_FF
+	bool "fastpath support for freebox boards"
+	depends on MV643XX_ETH
+	select IP_FFN
+	select IPV6_FFN
+	select IPV6_SIT_6RD
+	select BRIDGE
+	select FBXBRIDGE
+
 config MVMDIO
 	tristate "Marvell MDIO interface support"
 	depends on HAS_IOMEM
@@ -90,6 +100,7 @@
 	select MVMDIO
 	select PHYLINK
 	select PAGE_POOL
+	select MII
 	help
 	  This driver supports the network interface units in the
 	  Marvell ARMADA 375, 7K and 8K SoCs.
@@ -99,6 +110,15 @@
 	depends on (PTP_1588_CLOCK = y && MVPP2 = y) || \
 		   (PTP_1588_CLOCK && MVPP2 = m)
 
+config MVPP2_FBX_FF
+	bool "fastpath support for freebox boards"
+	depends on MVPP2
+	select IP_FFN
+	select IPV6_FFN
+	select IPV6_SIT_6RD
+	select BRIDGE
+	select FBXBRIDGE
+
 config PXA168_ETH
 	tristate "Marvell pxa168 ethernet support"
 	depends on HAS_IOMEM
diff -ruw linux-6.4/drivers/net/ethernet/qualcomm/Kconfig linux-6.4-fbx/drivers/net/ethernet/qualcomm/Kconfig
--- linux-6.4/drivers/net/ethernet/qualcomm/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/qualcomm/Kconfig	2023-11-29 17:07:11.038324048 +0100
@@ -62,5 +62,6 @@
 	  Precision Clock Synchronization Protocol.
 
 source "drivers/net/ethernet/qualcomm/rmnet/Kconfig"
+source "drivers/net/ethernet/qualcomm/ipq95xx/Kconfig"
 
 endif # NET_VENDOR_QUALCOMM
diff -ruw linux-6.4/drivers/net/ethernet/qualcomm/Makefile linux-6.4-fbx/drivers/net/ethernet/qualcomm/Makefile
--- linux-6.4/drivers/net/ethernet/qualcomm/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/ethernet/qualcomm/Makefile	2023-11-29 17:07:11.038324048 +0100
@@ -12,3 +12,4 @@
 obj-y += emac/
 
 obj-$(CONFIG_RMNET) += rmnet/
+obj-y += ipq95xx/
diff -ruw linux-6.4/drivers/net/phy/Kconfig linux-6.4-fbx/drivers/net/phy/Kconfig
--- linux-6.4/drivers/net/phy/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/phy/Kconfig	2023-11-29 17:07:11.174990927 +0100
@@ -309,6 +309,12 @@
 	  Currently supports the AR8030, AR8031, AR8033, AR8035 and internal
 	  QCA8337(Internal qca8k PHY) model
 
+config QCA807X_PHY
+	tristate "Qualcomm QCA870x PHYs"
+
+config QCA8084_PHY
+	tristate "Qualcomm QCA8084 Quad-PHY"
+
 config QSEMI_PHY
 	tristate "Quality Semiconductor PHYs"
 	help
diff -ruw linux-6.4/drivers/net/phy/Makefile linux-6.4-fbx/drivers/net/phy/Makefile
--- linux-6.4/drivers/net/phy/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/phy/Makefile	2023-11-29 17:07:11.174990927 +0100
@@ -82,7 +82,13 @@
 obj-$(CONFIG_NXP_C45_TJA11XX_PHY)	+= nxp-c45-tja11xx.o
 obj-$(CONFIG_NXP_CBTX_PHY)	+= nxp-cbtx.o
 obj-$(CONFIG_NXP_TJA11XX_PHY)	+= nxp-tja11xx.o
+obj-$(CONFIG_QCA807X_PHY) 	+= qca807x.o
+obj-$(CONFIG_QCA8084_PHY) 	+= qca8084.o
 obj-$(CONFIG_QSEMI_PHY)		+= qsemi.o
+realtek-objs += realtek.o
+ifdef CONFIG_HWMON
+realtek-objs += realtek-hwmon.o
+endif
 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
 obj-$(CONFIG_RENESAS_PHY)	+= uPD60620.o
 obj-$(CONFIG_ROCKCHIP_PHY)	+= rockchip.o
diff -ruw linux-6.4/drivers/net/wireless/ath/Kconfig linux-6.4-fbx/drivers/net/wireless/ath/Kconfig
--- linux-6.4/drivers/net/wireless/ath/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/wireless/ath/Kconfig	2023-11-29 17:07:11.218324328 +0100
@@ -37,6 +37,9 @@
 	  This option enables tracepoints for atheros wireless drivers.
 	  Currently, ath9k makes use of this facility.
 
+config ATH_REG_IGNORE
+	bool "ignore all eeprom regulation"
+
 config ATH_REG_DYNAMIC_USER_REG_HINTS
 	bool "Atheros dynamic user regulatory hints"
 	depends on CFG80211_CERTIFICATION_ONUS
diff -ruw linux-6.4/drivers/net/wireless/ath/ath11k/Kconfig linux-6.4-fbx/drivers/net/wireless/ath/ath11k/Kconfig
--- linux-6.4/drivers/net/wireless/ath/ath11k/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/wireless/ath/ath11k/Kconfig	2023-11-29 17:07:11.238324359 +0100
@@ -57,3 +57,15 @@
 	  Enable ath11k spectral scan support
 
 	  Say Y to enable access to the FFT/spectral data via debugfs.
+
+config ATH11K_SMALL_DP_RINGS
+	bool "ath11k small datapath DMA rings for memory challenged platforms"
+	depends on ATH11K
+	help
+	  Select this to lower the memory requirements for DMA rings
+	  in the datapath code. This can free up to 17 MiB of RAM per
+	  chip.
+
+config ATH11K_QCN9074_FIXED_MEM_REGION
+	bool "QCA ath11k fixed memory region mode on QCN9074"
+	depends on ATH11K
diff -ruw linux-6.4/drivers/net/wireless/ath/ath12k/Kconfig linux-6.4-fbx/drivers/net/wireless/ath/ath12k/Kconfig
--- linux-6.4/drivers/net/wireless/ath/ath12k/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/wireless/ath/ath12k/Kconfig	2024-02-21 16:43:28.653136585 +0100
@@ -32,3 +32,7 @@
 
 	  If unsure, say Y to make it easier to debug problems. But if
 	  you want optimal performance choose N.
+
+config ATH12K_DEBUGFS
+	bool "ath12k custom debugfs support"
+	depends on ATH12K
diff -ruw linux-6.4/drivers/net/wireless/ath/ath12k/Makefile linux-6.4-fbx/drivers/net/wireless/ath/ath12k/Makefile
--- linux-6.4/drivers/net/wireless/ath/ath12k/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/wireless/ath/ath12k/Makefile	2024-02-21 16:43:28.653136585 +0100
@@ -18,10 +18,23 @@
 	    dbring.o \
 	    hw.o \
 	    mhi.o \
+	    pcic.o \
 	    pci.o \
-	    dp_mon.o
+	    dp_mon.o \
+	    vendor.o \
+	    umac_reset.o
 
+ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
+ath12k-$(CONFIG_NL80211_TESTMODE) += testmode.o
 ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
+ath12k-$(CONFIG_THERMAL) += thermal.o
+ath12k-$(CONFIG_ATH12K_SPECTRAL) += spectral.o
+ath12k-$(CONFIG_WANT_DEV_COREDUMP) += coredump.o
+ath12k-$(CONFIG_ATH12K_PKTLOG) += pktlog.o
+ath12k-$(CONFIG_ATH12K_AHB) += ahb.o
+ath12k-$(CONFIG_ATH12K_PPE_DS_SUPPORT) += ppe.o
+ath12k-$(CONFIG_ATH12K_BONDED_DS_SUPPORT) += bondif.o
+ath12k-$(CONFIG_ATH12K_SAWF) += sawf.o telemetry.o telemetry_agent_if.o
 
 # for tracing framework to find trace.h
 CFLAGS_trace.o := -I$(src)
diff -ruw linux-6.4/drivers/net/wireless/marvell/Kconfig linux-6.4-fbx/drivers/net/wireless/marvell/Kconfig
--- linux-6.4/drivers/net/wireless/marvell/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/wireless/marvell/Kconfig	2022-08-30 19:20:27.747596724 +0200
@@ -25,4 +25,8 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called mwl8k.  If unsure, say N.
 
+config MWL8K_NEW
+	tristate "Marvell 88W8xxx PCI/PCIe NEW"
+	depends on MAC80211 && PCI
+
 endif # WLAN_VENDOR_MARVELL
diff -ruw linux-6.4/drivers/net/wireless/marvell/Makefile linux-6.4-fbx/drivers/net/wireless/marvell/Makefile
--- linux-6.4/drivers/net/wireless/marvell/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/net/wireless/marvell/Makefile	2020-06-11 10:15:40.279294436 +0200
@@ -5,3 +5,4 @@
 obj-$(CONFIG_MWIFIEX)	+= mwifiex/
 
 obj-$(CONFIG_MWL8K)	+= mwl8k.o
+obj-$(CONFIG_MWL8K_NEW)	+= mwl8k_new/
diff -ruw linux-6.4/drivers/nvmem/Kconfig linux-6.4-fbx/drivers/nvmem/Kconfig
--- linux-6.4/drivers/nvmem/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/nvmem/Kconfig	2023-11-29 17:07:11.588324903 +0100
@@ -59,6 +59,9 @@
 	  This driver provides support for Broadcom's NVRAM that can be accessed
 	  using I/O mapping.
 
+config NVMEM_IGNORE_RO
+	bool "ignore read-only flags"
+
 config NVMEM_IMX_IIM
 	tristate "i.MX IC Identification Module support"
 	depends on ARCH_MXC || COMPILE_TEST
diff -ruw linux-6.4/drivers/of/Kconfig linux-6.4-fbx/drivers/of/Kconfig
--- linux-6.4/drivers/of/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/of/Kconfig	2023-11-29 17:07:11.591658242 +0100
@@ -47,6 +47,11 @@
 
 	  If unsure, say N here, but this option is safe to enable.
 
+config OF_DTB_BUILTIN_LIST
+	string "Link given list of DTB files into kernel"
+	help
+	  Specify filename without .dtb extension
+
 config OF_FLATTREE
 	bool
 	select DTC
@@ -102,4 +107,11 @@
 config OF_NUMA
 	bool
 
+config OF_CONFIGFS
+	bool "Device Tree Overlay ConfigFS interface"
+	select CONFIGFS_FS
+	select OF_OVERLAY
+	help
+	  Enable a simple user-space driven DT overlay interface.
+
 endif # OF
diff -ruw linux-6.4/drivers/of/Makefile linux-6.4-fbx/drivers/of/Makefile
--- linux-6.4/drivers/of/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/of/Makefile	2023-11-29 17:07:11.591658242 +0100
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y = base.o cpu.o device.o module.o platform.o property.o
 obj-$(CONFIG_OF_KOBJ) += kobj.o
+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
 obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
 obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
diff -ruw linux-6.4/drivers/of/fdt.c linux-6.4-fbx/drivers/of/fdt.c
--- linux-6.4/drivers/of/fdt.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/of/fdt.c	2023-11-29 17:07:11.594991580 +0100
@@ -29,6 +29,7 @@
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #include <asm/page.h>
+#include <asm-generic/vmlinux.lds.h>
 
 #include "of_private.h"
 
@@ -787,6 +788,39 @@
 	return 0;
 }
 
+/*
+ * iterate list of built-in dtb to find a compatible match
+ */
+const void __init *of_fdt_find_compatible_dtb(const char *name)
+{
+	struct fdt_header {
+		__be32 magic;
+		__be32 totalsize;
+	};
+	const struct fdt_header *blob, *best;
+	unsigned int best_score = ~0;
+
+	best = NULL;
+	blob = (const struct fdt_header *)__dtb_start;
+	while ((void *)blob < (void *)__dtb_end &&
+	       (be32_to_cpu(blob->magic) == OF_DT_HEADER)) {
+		unsigned int score;
+		u32 size;
+
+		score = of_fdt_is_compatible(blob, 0, name);
+		if (score > 0 && score < best_score) {
+			best = blob;
+			best_score = score;
+		}
+
+		size = be32_to_cpu(blob->totalsize);
+		blob = (const struct fdt_header *)
+			PTR_ALIGN((void *)blob + size, STRUCT_ALIGNMENT);
+	}
+
+	return best;
+}
+
 /**
  * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
  * @node: node to test
diff -ruw linux-6.4/drivers/pci/controller/Kconfig linux-6.4-fbx/drivers/pci/controller/Kconfig
--- linux-6.4/drivers/pci/controller/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pci/controller/Kconfig	2023-11-29 17:07:11.604991596 +0100
@@ -179,7 +179,6 @@
 	depends on MVEBU_MBUS
 	depends on ARM
 	depends on OF
-	depends on BROKEN
 	select PCI_BRIDGE_EMUL
 	help
 	 Add support for Marvell EBU PCIe controller. This PCIe controller
@@ -208,6 +207,12 @@
 	  Say Y here if you want to enable Gen3 PCIe controller support on
 	  MediaTek SoCs.
 
+config PCIE_BCM63XX
+	tristate "BCM63XX SoCs PCIe endpoint driver."
+	depends on ARCH_BCMBCA || COMPILE_TEST
+	depends on OF
+	depends on PCI_MSI
+
 config PCIE_MT7621
 	tristate "MediaTek MT7621 PCIe controller"
 	depends on SOC_MT7621 || COMPILE_TEST
diff -ruw linux-6.4/drivers/pci/controller/Makefile linux-6.4-fbx/drivers/pci/controller/Makefile
--- linux-6.4/drivers/pci/controller/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pci/controller/Makefile	2023-11-29 17:07:11.604991596 +0100
@@ -33,6 +33,7 @@
 obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
 obj-$(CONFIG_PCIE_MEDIATEK_GEN3) += pcie-mediatek-gen3.o
 obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
+obj-$(CONFIG_PCIE_BCM63XX) += pcie-bcm63xx.o
 obj-$(CONFIG_VMD) += vmd.o
 obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
 obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
diff -ruw linux-6.4/drivers/pci/pci-sysfs.c linux-6.4-fbx/drivers/pci/pci-sysfs.c
--- linux-6.4/drivers/pci/pci-sysfs.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pci/pci-sysfs.c	2023-11-29 17:07:11.631658304 +0100
@@ -1149,6 +1149,7 @@
 {
 	int i;
 
+	mutex_lock(&pdev->sysfs_init_lock);
 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 		struct bin_attribute *res_attr;
 
@@ -1164,6 +1165,9 @@
 			kfree(res_attr);
 		}
 	}
+
+	pdev->sysfs_init_done = 0;
+	mutex_unlock(&pdev->sysfs_init_lock);
 }
 
 static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
@@ -1226,6 +1230,12 @@
 	int i;
 	int retval;
 
+	mutex_lock(&pdev->sysfs_init_lock);
+	if (pdev->sysfs_init_done) {
+		mutex_unlock(&pdev->sysfs_init_lock);
+		return 0;
+	}
+
 	/* Expose the PCI resources from this device as files */
 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 
@@ -1239,10 +1249,14 @@
 		    pdev->resource[i].flags & IORESOURCE_PREFETCH)
 			retval = pci_create_attr(pdev, i, 1);
 		if (retval) {
+			mutex_unlock(&pdev->sysfs_init_lock);
 			pci_remove_resource_files(pdev);
 			return retval;
 		}
 	}
+
+	pdev->sysfs_init_done = 1;
+	mutex_unlock(&pdev->sysfs_init_lock);
 	return 0;
 }
 #else /* !(defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE)) */
diff -ruw linux-6.4/drivers/pci/probe.c linux-6.4-fbx/drivers/pci/probe.c
--- linux-6.4/drivers/pci/probe.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pci/probe.c	2024-02-21 16:43:28.689803708 +0100
@@ -2310,6 +2310,7 @@
 		return NULL;
 
 	INIT_LIST_HEAD(&dev->bus_list);
+	mutex_init(&dev->sysfs_init_lock);
 	dev->dev.type = &pci_dev_type;
 	dev->bus = pci_bus_get(bus);
 	dev->driver_exclusive_resource = (struct resource) {
@@ -3270,6 +3271,34 @@
 	return max;
 }
 
+/*
+ * Walks the PCI/PCIe tree to find the first instance of a PCIe device and
+ * hands off the PCIe bus to pcie_bus_configure_settings to walk the rest.
+ */
+static int pcie_rescan_bus_configure_settings(struct pci_dev *dev, void *data)
+{
+	if (pci_is_pcie(dev)) {
+		struct pci_bus *child, *bus = dev->bus;
+
+		list_for_each_entry(child, &bus->children, node)
+			pcie_bus_configure_settings(child);
+
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * pci_bus_configure_settings - Configure bus settings
+ * @bus: PCI/PCIE bus to configure
+ *
+ * Currently only configures PCIe bus settings related to MPS and MRRS.
+ */
+static void pci_bus_configure_settings(struct pci_bus *bus)
+{
+	pci_walk_bus(bus, pcie_rescan_bus_configure_settings, NULL);
+}
+
 /**
  * pci_rescan_bus - Scan a PCI bus for devices
  * @bus: PCI bus to scan
@@ -3285,6 +3314,7 @@
 
 	max = pci_scan_child_bus(bus);
 	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_configure_settings(bus);
 	pci_bus_add_devices(bus);
 
 	return max;
diff -ruw linux-6.4/drivers/pci/quirks.c linux-6.4-fbx/drivers/pci/quirks.c
--- linux-6.4/drivers/pci/quirks.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pci/quirks.c	2023-11-29 17:07:11.638324981 +0100
@@ -3150,6 +3150,8 @@
 	dev->is_hotplug_bridge = 1;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0020, quirk_hotplug_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PI7C9X20303SL,
+			 quirk_hotplug_bridge);
 
 /*
  * This is a quirk for the Ricoh MMC controller found as a part of some
diff -ruw linux-6.4/drivers/phy/Kconfig linux-6.4-fbx/drivers/phy/Kconfig
--- linux-6.4/drivers/phy/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/phy/Kconfig	2023-11-29 17:07:11.654991673 +0100
@@ -71,6 +71,10 @@
 	  functional modes using gpios and sets the attribute max link
 	  rate, for CAN drivers.
 
+config XDSL_PHY_API
+	tristate "xDSL PHY API"
+	select GENERIC_PHY
+
 source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/broadcom/Kconfig"
diff -ruw linux-6.4/drivers/phy/Makefile linux-6.4-fbx/drivers/phy/Makefile
--- linux-6.4/drivers/phy/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/phy/Makefile	2023-11-29 17:07:11.654991673 +0100
@@ -10,6 +10,8 @@
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_USB_LGM_PHY)		+= phy-lgm-usb.o
+obj-$(CONFIG_XDSL_PHY_API)		+= xdsl_phy_api.o
+
 obj-y					+= allwinner/	\
 					   amlogic/	\
 					   broadcom/	\
diff -ruw linux-6.4/drivers/phy/broadcom/Kconfig linux-6.4-fbx/drivers/phy/broadcom/Kconfig
--- linux-6.4/drivers/phy/broadcom/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/phy/broadcom/Kconfig	2023-11-29 17:07:11.658325012 +0100
@@ -39,6 +39,11 @@
 	help
 	  Enable this to support the Broadcom Kona USB 2.0 PHY.
 
+config PHY_BRCM_USB_63138
+	tristate "Broadcom 63138 USB 2.0/3.0 PHY Driver"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+	select GENERIC_PHY
+
 config PHY_BCM_NS_USB2
 	tristate "Broadcom Northstar USB 2.0 PHY Driver"
 	depends on ARCH_BCM_IPROC || COMPILE_TEST
diff -ruw linux-6.4/drivers/phy/broadcom/Makefile linux-6.4-fbx/drivers/phy/broadcom/Makefile
--- linux-6.4/drivers/phy/broadcom/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/phy/broadcom/Makefile	2022-08-30 19:20:28.367603728 +0200
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_PHY_BCM63XX_USBH)		+= phy-bcm63xx-usbh.o
 obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
+obj-$(CONFIG_PHY_BRCM_USB_63138)	+= phy-brcm-usb-63138.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_BCM_NS_USB2)		+= phy-bcm-ns-usb2.o
 obj-$(CONFIG_PHY_BCM_NS_USB3)		+= phy-bcm-ns-usb3.o
diff -ruw linux-6.4/drivers/phy/marvell/Kconfig linux-6.4-fbx/drivers/phy/marvell/Kconfig
--- linux-6.4/drivers/phy/marvell/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/phy/marvell/Kconfig	2022-08-30 19:20:28.379603864 +0200
@@ -136,3 +136,11 @@
 	  components on MMP3-based boards.
 
 	  To compile this driver as a module, choose M here.
+
+config PHY_UTMI_CP110
+	bool "Marvell CP110 UTMI PHY Driver"
+	depends on ARCH_MVEBU
+	depends on OF
+	help
+	  Enable this to support Marvell USB2.0 PHY driver for Marvell
+	  CP110-based SoCs (A7K and A8K).
diff -ruw linux-6.4/drivers/phy/marvell/Makefile linux-6.4-fbx/drivers/phy/marvell/Makefile
--- linux-6.4/drivers/phy/marvell/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/phy/marvell/Makefile	2022-08-30 19:20:28.379603864 +0200
@@ -13,3 +13,4 @@
 obj-$(CONFIG_PHY_PXA_28NM_HSIC)		+= phy-pxa-28nm-hsic.o
 obj-$(CONFIG_PHY_PXA_28NM_USB2)		+= phy-pxa-28nm-usb2.o
 obj-$(CONFIG_PHY_PXA_USB)		+= phy-pxa-usb.o
+obj-$(CONFIG_PHY_UTMI_CP110)		+= phy-utmi-cp110.o
diff -ruw linux-6.4/drivers/pinctrl/bcm/Kconfig linux-6.4-fbx/drivers/pinctrl/bcm/Kconfig
--- linux-6.4/drivers/pinctrl/bcm/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pinctrl/bcm/Kconfig	2023-11-29 17:07:11.688325059 +0100
@@ -52,6 +52,16 @@
 	select REGMAP
 	select GPIO_REGMAP
 
+config PINCTRL_BCM63138
+	bool "Broadcom 63138 pinmux driver"
+	depends on OF && (ARCH_BCMBCA || COMPILE_TEST)
+	default ARCH_BCMBCA
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIOLIB_IRQCHIP
+
 config PINCTRL_BCM6318
 	bool "Broadcom BCM6318 GPIO driver"
 	depends on (BMIPS_GENERIC || COMPILE_TEST)
diff -ruw linux-6.4/drivers/pinctrl/bcm/Makefile linux-6.4-fbx/drivers/pinctrl/bcm/Makefile
--- linux-6.4/drivers/pinctrl/bcm/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/pinctrl/bcm/Makefile	2023-11-29 17:07:11.688325059 +0100
@@ -11,6 +11,7 @@
 obj-$(CONFIG_PINCTRL_BCM6362)		+= pinctrl-bcm6362.o
 obj-$(CONFIG_PINCTRL_BCM6368)		+= pinctrl-bcm6368.o
 obj-$(CONFIG_PINCTRL_BCM63268)		+= pinctrl-bcm63268.o
+obj-$(CONFIG_PINCTRL_BCM63138)		+= pinctrl-bcm63138.o
 obj-$(CONFIG_PINCTRL_IPROC_GPIO)	+= pinctrl-iproc-gpio.o
 obj-$(CONFIG_PINCTRL_CYGNUS_MUX)	+= pinctrl-cygnus-mux.o
 obj-$(CONFIG_PINCTRL_NS)		+= pinctrl-ns.o
diff -ruw linux-6.4/drivers/platform/Kconfig linux-6.4-fbx/drivers/platform/Kconfig
--- linux-6.4/drivers/platform/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/platform/Kconfig	2023-11-29 17:07:11.771658521 +0100
@@ -14,3 +14,11 @@
 source "drivers/platform/surface/Kconfig"
 
 source "drivers/platform/x86/Kconfig"
+
+if X86_INTEL_CE
+source "drivers/platform/intelce/Kconfig"
+endif
+
+source "drivers/platform/fbxgw7r/Kconfig"
+
+source "drivers/platform/ipq/Kconfig"
diff -ruw linux-6.4/drivers/platform/Makefile linux-6.4-fbx/drivers/platform/Makefile
--- linux-6.4/drivers/platform/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/platform/Makefile	2023-11-29 17:07:11.771658521 +0100
@@ -11,3 +11,6 @@
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_CHROME_PLATFORMS)	+= chrome/
 obj-$(CONFIG_SURFACE_PLATFORMS)	+= surface/
+obj-$(CONFIG_X86_INTEL_CE)	+= intelce/
+obj-$(CONFIG_FBXGW7R_PLATFORM)	+= fbxgw7r/
+obj-$(CONFIG_QCOM_IPQ_PLATFORM)	+= ipq/
diff -ruw linux-6.4/drivers/regulator/Kconfig linux-6.4-fbx/drivers/regulator/Kconfig
--- linux-6.4/drivers/regulator/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/regulator/Kconfig	2023-11-29 17:07:11.861658661 +0100
@@ -30,6 +30,12 @@
 	help
 	  Say yes here to enable debugging support.
 
+config REGULATOR_FAULT_SENSING
+	bool "Regulator fault-sensing detection"
+	help
+	  Add support for fault-sensing gpio which will cause
+	  regulator to be forced-disabled.
+
 config REGULATOR_FIXED_VOLTAGE
 	tristate "Fixed voltage regulator support"
 	help
diff -ruw linux-6.4/drivers/rtc/Kconfig linux-6.4-fbx/drivers/rtc/Kconfig
--- linux-6.4/drivers/rtc/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/rtc/Kconfig	2024-01-12 13:49:05.000035648 +0100
@@ -1391,6 +1391,15 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-meson-vrtc.
 
+config RTC_DRV_MESON_AXG
+	tristate "Amlogic Meson AXG RTC + wakeup"
+	depends on RTC_HCTOSYS
+	depends on ARCH_MESON || COMPILE_TEST
+	default m if ARCH_MESON
+	help
+	  If you say yes here you will get support for the RTC of Amlogic SoCs
+	  as implemented in M3's firmware for AXG platform by Freebox.
+
 config RTC_DRV_OMAP
 	tristate "TI OMAP Real Time Clock"
 	depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
diff -ruw linux-6.4/drivers/rtc/Makefile linux-6.4-fbx/drivers/rtc/Makefile
--- linux-6.4/drivers/rtc/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/rtc/Makefile	2024-01-12 13:49:05.000035648 +0100
@@ -97,6 +97,7 @@
 obj-$(CONFIG_RTC_DRV_MAX8997)	+= rtc-max8997.o
 obj-$(CONFIG_RTC_DRV_MAX8998)	+= rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MESON_VRTC)+= rtc-meson-vrtc.o
+obj-$(CONFIG_RTC_DRV_MESON_AXG)	+= rtc-meson-axg.o
 obj-$(CONFIG_RTC_DRV_MC13XXX)	+= rtc-mc13xxx.o
 obj-$(CONFIG_RTC_DRV_MCP795)	+= rtc-mcp795.o
 obj-$(CONFIG_RTC_DRV_MESON)	+= rtc-meson.o
diff -ruw linux-6.4/drivers/soc/bcm/Kconfig linux-6.4-fbx/drivers/soc/bcm/Kconfig
--- linux-6.4/drivers/soc/bcm/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/soc/bcm/Kconfig	2023-11-29 17:07:12.164992466 +0100
@@ -24,7 +24,8 @@
 
 config SOC_BCM63XX
 	bool "Broadcom 63xx SoC drivers"
-	depends on BMIPS_GENERIC || COMPILE_TEST
+	depends on BMIPS_GENERIC || ARCH_BCMBCA || COMPILE_TEST
+	select RESET_CONTROLLER
 	help
 	  Enables drivers for the Broadcom 63xx series of chips.
 	  Drivers can be enabled individually within this menu.
diff -ruw linux-6.4/drivers/soc/bcm/Makefile linux-6.4-fbx/drivers/soc/bcm/Makefile
--- linux-6.4/drivers/soc/bcm/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/soc/bcm/Makefile	2023-11-29 17:07:12.164992466 +0100
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_BCM2835_POWER)	+= bcm2835-power.o
 obj-$(CONFIG_RASPBERRYPI_POWER)	+= raspberrypi-power.o
-obj-y				+= bcm63xx/
 obj-$(CONFIG_SOC_BRCMSTB)	+= brcmstb/
+obj-$(CONFIG_SOC_BCM63XX)	+= bcm63xx/
diff -ruw linux-6.4/drivers/soc/bcm/bcm63xx/Kconfig linux-6.4-fbx/drivers/soc/bcm/bcm63xx/Kconfig
--- linux-6.4/drivers/soc/bcm/bcm63xx/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/soc/bcm/bcm63xx/Kconfig	2023-11-29 17:07:12.164992466 +0100
@@ -9,6 +9,31 @@
 	  This enables support for the BCM63xx power domains controller on
 	  BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
 
+config SOC_BCM63XX_RDP
+	bool "rdp subsystem"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+
+config SOC_BCM63XX_XRDP
+	tristate "xrdp subsystem"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+	select UBUS4_BCM63158
+
+config SOC_BCM63XX_XRDP_IOCTL
+	bool "ioctl interface"
+	depends on SOC_BCM63XX_XRDP
+
+config UBUS4_BCM63158
+	bool "Broadcom 63158 UBUS4 driver"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+
+config SOC_MEMC_BCM63158
+	tristate "Broadcom 63158 MEMC driver"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+
+config PROCMON_BCM63158
+	bool "Broadcom 63158 PROCMON driver"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+
 endif # SOC_BCM63XX
 
 config BCM_PMB
@@ -19,3 +44,4 @@
 	help
 	  This enables support for the Broadcom's PMB (Power Management Bus) that
 	  is used for disabling and enabling SoC devices.
+
diff -ruw linux-6.4/drivers/soc/bcm/bcm63xx/Makefile linux-6.4-fbx/drivers/soc/bcm/bcm63xx/Makefile
--- linux-6.4/drivers/soc/bcm/bcm63xx/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/soc/bcm/bcm63xx/Makefile	2023-11-29 17:07:12.164992466 +0100
@@ -1,3 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o
 obj-$(CONFIG_BCM_PMB)		+= bcm-pmb.o
+
+obj-$(CONFIG_ARCH_BCMBCA) += pmc.o
+obj-$(CONFIG_SOC_BCM63XX_RDP) += rdp/
+obj-$(CONFIG_SOC_BCM63XX_XRDP) += xrdp/
+obj-$(CONFIG_UBUS4_BCM63158)	+= ubus4-bcm63158.o
+obj-$(CONFIG_PROCMON_BCM63158)	+= procmon-bcm63158.o
+obj-$(CONFIG_SOC_MEMC_BCM63158)	+= memc-bcm63158.o
diff -ruw linux-6.4/drivers/spi/Kconfig linux-6.4-fbx/drivers/spi/Kconfig
--- linux-6.4/drivers/spi/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/spi/Kconfig	2023-11-29 17:07:12.201659190 +0100
@@ -771,6 +771,12 @@
 	help
 	  This selects a driver for the PPC4xx SPI Controller.
 
+config SPI_TDM_ORION
+	tristate "Orion TDM SPI master"
+	depends on PLAT_ORION
+	help
+	  This enables using the TDM SPI master controller on the Orion chips.
+
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
 	depends on ARCH_PXA || ARCH_MMP || PCI || ACPI || COMPILE_TEST
diff -ruw linux-6.4/drivers/spi/Makefile linux-6.4-fbx/drivers/spi/Makefile
--- linux-6.4/drivers/spi/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/spi/Makefile	2023-11-29 17:07:12.201659190 +0100
@@ -99,6 +99,7 @@
 obj-$(CONFIG_SPI_PCI1XXXX)		+= spi-pci1xxxx.o
 obj-$(CONFIG_SPI_PIC32)			+= spi-pic32.o
 obj-$(CONFIG_SPI_PIC32_SQI)		+= spi-pic32-sqi.o
+obj-$(CONFIG_SPI_TDM_ORION)		+= orion_tdm_spi.o
 obj-$(CONFIG_SPI_PL022)			+= spi-pl022.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi-ppc4xx.o
 spi-pxa2xx-platform-objs		:= spi-pxa2xx.o spi-pxa2xx-dma.o
diff -ruw linux-6.4/drivers/thermal/thermal_core.c linux-6.4-fbx/drivers/thermal/thermal_core.c
--- linux-6.4/drivers/thermal/thermal_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/thermal/thermal_core.c	2023-11-29 17:07:12.418326193 +0100
@@ -810,6 +810,7 @@
 
 /**
  * __thermal_cooling_device_register() - register a new thermal cooling device
+ * @dev:	parent device
  * @np:		a pointer to a device tree node.
  * @type:	the thermal cooling device type.
  * @devdata:	device private data.
@@ -825,7 +826,7 @@
  * ERR_PTR. Caller must check return value with IS_ERR*() helpers.
  */
 static struct thermal_cooling_device *
-__thermal_cooling_device_register(struct device_node *np,
+__thermal_cooling_device_register(struct device *pdev, struct device_node *np,
 				  const char *type, void *devdata,
 				  const struct thermal_cooling_device_ops *ops)
 {
@@ -873,6 +874,7 @@
 	ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
 	if (ret)
 		goto out_cooling_dev;
+	cdev->device.parent = pdev;
 
 	ret = device_register(&cdev->device);
 	if (ret) {
@@ -926,11 +928,30 @@
 thermal_cooling_device_register(const char *type, void *devdata,
 				const struct thermal_cooling_device_ops *ops)
 {
-	return __thermal_cooling_device_register(NULL, type, devdata, ops);
+	return __thermal_cooling_device_register(NULL, NULL, type, devdata, ops);
 }
 EXPORT_SYMBOL_GPL(thermal_cooling_device_register);
 
 /**
+ * thermal_cooling_device_register_with_parent() - register a new thermal cooling device
+ * @pdev:	parent device
+ * @type:	the thermal cooling device type.
+ * @devdata:	device private data.
+ * @ops:		standard thermal cooling devices callbacks.
+ *
+ * Same as thermal_cooling_device_register but take also the parent device.
+ * Then, hwpath will include the parent device to uniquely identify this device
+ */
+struct thermal_cooling_device *
+thermal_cooling_device_register_with_parent(struct device *pdev,
+				const char *type, void *devdata,
+				const struct thermal_cooling_device_ops *ops)
+{
+	return __thermal_cooling_device_register(pdev, NULL, type, devdata, ops);
+}
+EXPORT_SYMBOL_GPL(thermal_cooling_device_register_with_parent);
+
+/**
  * thermal_of_cooling_device_register() - register an OF thermal cooling device
  * @np:		a pointer to a device tree node.
  * @type:	the thermal cooling device type.
@@ -950,7 +971,7 @@
 				   const char *type, void *devdata,
 				   const struct thermal_cooling_device_ops *ops)
 {
-	return __thermal_cooling_device_register(np, type, devdata, ops);
+	return __thermal_cooling_device_register(NULL, np, type, devdata, ops);
 }
 EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register);
 
@@ -990,7 +1011,7 @@
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	tcd = __thermal_cooling_device_register(np, type, devdata, ops);
+	tcd = __thermal_cooling_device_register(NULL, np, type, devdata, ops);
 	if (IS_ERR(tcd)) {
 		devres_free(ptr);
 		return tcd;
diff -ruw linux-6.4/drivers/tty/serial/Kconfig linux-6.4-fbx/drivers/tty/serial/Kconfig
--- linux-6.4/drivers/tty/serial/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/tty/serial/Kconfig	2023-11-29 17:07:12.444992901 +0100
@@ -1075,6 +1075,11 @@
 	    BCM68xx (PON)
 	    BCM7xxx (STB) - DOCSIS console
 
+config SERIAL_BCM63XX_HS
+	tristate "Broadcom BCM63xx HS UART support"
+	select SERIAL_CORE
+	depends on ARCH_BCMBCA || COMPILE_TEST
+
 config SERIAL_BCM63XX_CONSOLE
 	bool "Console on BCM63xx serial port"
 	depends on SERIAL_BCM63XX=y
diff -ruw linux-6.4/drivers/tty/serial/Makefile linux-6.4-fbx/drivers/tty/serial/Makefile
--- linux-6.4/drivers/tty/serial/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/tty/serial/Makefile	2023-11-29 17:07:12.444992901 +0100
@@ -30,6 +30,7 @@
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
 obj-$(CONFIG_SERIAL_SAMSUNG) += samsung_tty.o
+obj-$(CONFIG_SERIAL_BCM63XX_HS) += bcm63xx-hs-uart.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
 obj-$(CONFIG_SERIAL_MAX310X) += max310x.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
diff -ruw linux-6.4/drivers/usb/host/Kconfig linux-6.4-fbx/drivers/usb/host/Kconfig
--- linux-6.4/drivers/usb/host/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/usb/host/Kconfig	2023-11-29 17:07:12.591659796 +0100
@@ -78,13 +78,13 @@
 	  If unsure, say N.
 
 config USB_XHCI_MVEBU
-	tristate "xHCI support for Marvell Armada 375/38x/37xx"
+	tristate "xHCI support for Marvell Armada 375/38x/37xx/70x0/80x0"
 	select USB_XHCI_PLATFORM
 	depends on HAS_IOMEM
 	depends on ARCH_MVEBU || COMPILE_TEST
 	help
 	  Say 'Y' to enable the support for the xHCI host controller
-	  found in Marvell Armada 375/38x/37xx ARM SOCs.
+	  found in Marvell Armada 375/38x/37xx/70x0/80x0 ARM SOCs.
 
 config USB_XHCI_RCAR
 	tristate "xHCI support for Renesas R-Car SoCs"
@@ -690,6 +690,10 @@
 
 	  If unsure, say N.
 
+config USB_BCM63158
+	tristate "Broadcom BCM63158 SoC USB host driver"
+	depends on ARCH_BCMBCA || COMPILE_TEST
+
 config USB_HCD_SSB
 	tristate "SSB usb host driver"
 	depends on SSB
diff -ruw linux-6.4/drivers/usb/host/Makefile linux-6.4-fbx/drivers/usb/host/Makefile
--- linux-6.4/drivers/usb/host/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/usb/host/Makefile	2023-11-29 17:07:12.591659796 +0100
@@ -85,3 +85,4 @@
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)	+= max3421-hcd.o
 obj-$(CONFIG_USB_XEN_HCD)	+= xen-hcd.o
+obj-$(CONFIG_USB_BCM63158)	+= usb-bcm63158.o
diff -ruw linux-6.4/drivers/usb/storage/usb.c linux-6.4-fbx/drivers/usb/storage/usb.c
--- linux-6.4/drivers/usb/storage/usb.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/usb/storage/usb.c	2023-11-29 17:07:12.711659982 +0100
@@ -67,7 +67,7 @@
 MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
 MODULE_LICENSE("GPL");
 
-static unsigned int delay_use = 1;
+static unsigned int delay_use = 5;
 module_param(delay_use, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
 
diff -ruw linux-6.4/drivers/video/Kconfig linux-6.4-fbx/drivers/video/Kconfig
--- linux-6.4/drivers/video/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/video/Kconfig	2023-11-29 17:07:12.851660200 +0100
@@ -59,5 +59,4 @@
 
 endif
 
-
 endmenu
diff -ruw linux-6.4/drivers/video/fbdev/Kconfig linux-6.4-fbx/drivers/video/fbdev/Kconfig
--- linux-6.4/drivers/video/fbdev/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/video/fbdev/Kconfig	2023-11-29 17:07:12.864993554 +0100
@@ -2208,6 +2208,24 @@
 	  called sm712fb. If you want to compile it as a module, say M
 	  here and read <file:Documentation/kbuild/modules.rst>.
 
+config FB_SSD1320
+	tristate "SSD1320 OLED driver"
+	depends on FB && SPI
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_BACKLIGHT
+
+config FB_SSD1327
+	tristate "SSD1327 OLED driver"
+	depends on FB && SPI
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_BACKLIGHT
+
 source "drivers/video/fbdev/omap/Kconfig"
 source "drivers/video/fbdev/omap2/Kconfig"
 source "drivers/video/fbdev/mmp/Kconfig"
diff -ruw linux-6.4/drivers/video/fbdev/Makefile linux-6.4-fbx/drivers/video/fbdev/Makefile
--- linux-6.4/drivers/video/fbdev/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/drivers/video/fbdev/Makefile	2023-11-29 17:07:12.864993554 +0100
@@ -126,6 +126,8 @@
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
 obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
 obj-$(CONFIG_FB_SIMPLE)           += simplefb.o
+obj-$(CONFIG_FB_SSD1327)          += ssd1327.o
+obj-$(CONFIG_FB_SSD1320)          += ssd1320.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff -ruw linux-6.4/fs/Kconfig linux-6.4-fbx/fs/Kconfig
--- linux-6.4/fs/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/Kconfig	2023-11-29 17:07:12.991660417 +0100
@@ -156,6 +156,7 @@
 source "fs/exfat/Kconfig"
 source "fs/ntfs/Kconfig"
 source "fs/ntfs3/Kconfig"
+source "fs/exfat-fbx/Kconfig"
 
 endmenu
 endif # BLOCK
diff -ruw linux-6.4/fs/Makefile linux-6.4-fbx/fs/Makefile
--- linux-6.4/fs/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/Makefile	2023-11-29 17:07:12.991660417 +0100
@@ -135,3 +135,4 @@
 obj-$(CONFIG_EROFS_FS)		+= erofs/
 obj-$(CONFIG_VBOXSF_FS)		+= vboxsf/
 obj-$(CONFIG_ZONEFS_FS)		+= zonefs/
+obj-$(CONFIG_EXFAT_FS_FBX)		+= exfat-fbx/
diff -ruw linux-6.4/fs/exec.c linux-6.4-fbx/fs/exec.c
--- linux-6.4/fs/exec.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/exec.c	2023-11-29 17:07:13.081660557 +0100
@@ -1895,6 +1895,23 @@
 		return PTR_ERR(filename);
 
 	/*
+	 * handle current->exec_mode:
+	 * - if unlimited, then nothing to do.
+	 * - if once, then set it to denied and continue (next execve
+	 *   after this one will fail).
+	 * - if denied, then effectively fail the execve call with EPERM.
+	 */
+	switch (current->exec_mode) {
+	case EXEC_MODE_UNLIMITED:
+		break;
+	case EXEC_MODE_ONCE:
+		current->exec_mode = EXEC_MODE_DENIED;
+		break;
+	case EXEC_MODE_DENIED:
+		return -EPERM;
+	}
+
+	/*
 	 * We move the actual failure in case of RLIMIT_NPROC excess from
 	 * set*uid() to execve() because too many poorly written programs
 	 * don't check setuid() return code.  Here we additionally recheck
diff -ruw linux-6.4/fs/proc/array.c linux-6.4-fbx/fs/proc/array.c
--- linux-6.4/fs/proc/array.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/proc/array.c	2023-11-29 17:07:13.248327483 +0100
@@ -145,6 +145,21 @@
 	return task_state_array[task_state_index(tsk)];
 }
 
+static const char *const task_exec_mode_array[] = {
+	"0 (Denied)",
+	"1 (Once)",
+	"2 (Unlimited)",
+};
+
+static inline const char *get_task_exec_mode(struct task_struct *tsk)
+{
+	unsigned int exec_mode = tsk->exec_mode;
+
+	if (exec_mode > EXEC_MODE_UNLIMITED)
+		return "? (Invalid)";
+	return task_exec_mode_array[exec_mode];
+}
+
 static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
 				struct pid *pid, struct task_struct *p)
 {
@@ -403,6 +418,12 @@
 	seq_putc(m, '\n');
 }
 
+static inline void task_exec_mode(struct seq_file *m,
+				  struct task_struct *p)
+{
+	seq_printf(m, "Exec mode: %s\n", get_task_exec_mode(p));
+}
+
 static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
 {
 	seq_printf(m, "Cpus_allowed:\t%*pb\n",
@@ -455,6 +476,7 @@
 	task_cpus_allowed(m, task);
 	cpuset_task_status_allowed(m, task);
 	task_context_switch_counts(m, task);
+	task_exec_mode(m, task);
 	return 0;
 }
 
diff -ruw linux-6.4/fs/pstore/inode.c linux-6.4-fbx/fs/pstore/inode.c
--- linux-6.4/fs/pstore/inode.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/pstore/inode.c	2023-11-29 17:07:13.254994160 +0100
@@ -371,9 +371,10 @@
 		goto fail;
 	inode->i_mode = S_IFREG | 0444;
 	inode->i_fop = &pstore_file_operations;
-	scnprintf(name, sizeof(name), "%s-%s-%llu%s",
+	scnprintf(name, sizeof(name), "%s-%s-%s%llu%s",
 			pstore_type_to_name(record->type),
-			record->psi->name, record->id,
+		        record->psi->name, record->old ? "old-" : "",
+		        record->id,
 			record->compressed ? ".enc.z" : "");
 
 	private = kzalloc(sizeof(*private), GFP_KERNEL);
diff -ruw linux-6.4/fs/pstore/ram.c linux-6.4-fbx/fs/pstore/ram.c
--- linux-6.4/fs/pstore/ram.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/pstore/ram.c	2023-11-29 17:07:13.254994160 +0100
@@ -137,6 +137,7 @@
 
 	record->type = prz->type;
 	record->id = id;
+	record->old = prz->old_zone;
 
 	return prz;
 }
@@ -481,7 +482,7 @@
 static int ramoops_init_przs(const char *name,
 			     struct device *dev, struct ramoops_context *cxt,
 			     struct persistent_ram_zone ***przs,
-			     phys_addr_t *paddr, size_t mem_sz,
+			     phys_addr_t *paddr, void *vaddr, size_t mem_sz,
 			     ssize_t record_size,
 			     unsigned int *cnt, u32 sig, u32 flags)
 {
@@ -545,7 +546,7 @@
 		else
 			label = kasprintf(GFP_KERNEL, "ramoops:%s(%d/%d)",
 					  name, i, *cnt - 1);
-		prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig,
+		prz_ar[i] = persistent_ram_new(*paddr, vaddr, zone_sz, sig,
 					       &cxt->ecc_info,
 					       cxt->memtype, flags, label);
 		kfree(label);
@@ -578,7 +579,7 @@
 static int ramoops_init_prz(const char *name,
 			    struct device *dev, struct ramoops_context *cxt,
 			    struct persistent_ram_zone **prz,
-			    phys_addr_t *paddr, size_t sz, u32 sig)
+			    phys_addr_t *paddr, void *vaddr, size_t sz, u32 sig)
 {
 	char *label;
 
@@ -593,7 +594,7 @@
 	}
 
 	label = kasprintf(GFP_KERNEL, "ramoops:%s", name);
-	*prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
+	*prz = persistent_ram_new(*paddr, vaddr, sz, sig, &cxt->ecc_info,
 				  cxt->memtype, PRZ_FLAG_ZAP_OLD, label);
 	kfree(label);
 	if (IS_ERR(*prz)) {
@@ -781,17 +782,20 @@
 	dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size
 			- cxt->pmsg_size;
 	err = ramoops_init_przs("dmesg", dev, cxt, &cxt->dprzs, &paddr,
+				pdata->mem_ptr,
 				dump_mem_sz, cxt->record_size,
 				&cxt->max_dump_cnt, 0, 0);
 	if (err)
 		goto fail_init;
 
 	err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr,
+			       pdata->mem_ptr,
 			       cxt->console_size, 0);
 	if (err)
 		goto fail_init;
 
 	err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
+			       pdata->mem_ptr,
 				cxt->pmsg_size, 0);
 	if (err)
 		goto fail_init;
@@ -800,6 +804,7 @@
 				? nr_cpu_ids
 				: 1;
 	err = ramoops_init_przs("ftrace", dev, cxt, &cxt->fprzs, &paddr,
+				pdata->mem_ptr,
 				cxt->ftrace_size, -1,
 				&cxt->max_ftrace_cnt, LINUX_VERSION_CODE,
 				(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
diff -ruw linux-6.4/fs/pstore/ram_core.c linux-6.4-fbx/fs/pstore/ram_core.c
--- linux-6.4/fs/pstore/ram_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/pstore/ram_core.c	2023-11-29 17:07:13.254994160 +0100
@@ -35,6 +35,7 @@
 	uint32_t    sig;
 	atomic_t    start;
 	atomic_t    size;
+	atomic_t    flags;
 	uint8_t     data[];
 };
 
@@ -394,6 +395,7 @@
 {
 	atomic_set(&prz->buffer->start, 0);
 	atomic_set(&prz->buffer->size, 0);
+	atomic_set(&prz->buffer->flags, 0);
 	persistent_ram_update_header_ecc(prz);
 }
 
@@ -480,13 +482,16 @@
 	return va;
 }
 
-static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
+static int persistent_ram_buffer_map(phys_addr_t start, void *vaddr,
+				     phys_addr_t size,
 		struct persistent_ram_zone *prz, int memtype)
 {
 	prz->paddr = start;
 	prz->size = size;
 
-	if (pfn_valid(start >> PAGE_SHIFT))
+	if (vaddr)
+		prz->vaddr = vaddr;
+	else if (pfn_valid(start >> PAGE_SHIFT))
 		prz->vaddr = persistent_ram_vmap(start, size, memtype);
 	else
 		prz->vaddr = persistent_ram_iomap(start, size, memtype,
@@ -533,6 +538,15 @@
 			pr_debug("found existing buffer, size %zu, start %zu\n",
 				 buffer_size(prz), buffer_start(prz));
 			persistent_ram_save_old(prz);
+
+			if (atomic_read(&prz->buffer->flags) > 0) {
+				pr_info("old ramoops!\n");
+				prz->old_zone = true;
+			} else {
+				pr_info("fresh ramoops!\n");
+				atomic_set(&prz->buffer->flags, 1);
+			}
+			persistent_ram_update_header_ecc(prz);
 		}
 	} else {
 		pr_debug("no valid data in buffer (sig = 0x%08x)\n",
@@ -582,7 +596,8 @@
 	*_prz = NULL;
 }
 
-struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
+struct persistent_ram_zone *persistent_ram_new(phys_addr_t start,
+					       void *vaddr, size_t size,
 			u32 sig, struct persistent_ram_ecc_info *ecc_info,
 			unsigned int memtype, u32 flags, char *label)
 {
@@ -600,7 +615,7 @@
 	prz->flags = flags;
 	prz->label = kstrdup(label, GFP_KERNEL);
 
-	ret = persistent_ram_buffer_map(start, size, prz, memtype);
+	ret = persistent_ram_buffer_map(start, vaddr, size, prz, memtype);
 	if (ret)
 		goto err;
 
diff -ruw linux-6.4/fs/pstore/ram_internal.h linux-6.4-fbx/fs/pstore/ram_internal.h
--- linux-6.4/fs/pstore/ram_internal.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/pstore/ram_internal.h	2023-11-29 17:07:13.254994160 +0100
@@ -55,6 +55,10 @@
  * @old_log_size:
  *	bytes contained in @old_log
  *
+ * @old_zone:
+ *      tells whether the zone has just been freshly created, and has
+ *      been read for the first time, this boot, or if it is old, and
+ *      has been created many boots ago.
  */
 struct persistent_ram_zone {
 	phys_addr_t paddr;
@@ -77,9 +81,12 @@
 
 	char *old_log;
 	size_t old_log_size;
+
+	bool old_zone;
 };
 
-struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
+struct persistent_ram_zone *persistent_ram_new(phys_addr_t start,
+					       void *addr, size_t size,
 			u32 sig, struct persistent_ram_ecc_info *ecc_info,
 			unsigned int memtype, u32 flags, char *label);
 void persistent_ram_free(struct persistent_ram_zone **_prz);
diff -ruw linux-6.4/fs/smb/server/Kconfig linux-6.4-fbx/fs/smb/server/Kconfig
--- linux-6.4/fs/smb/server/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/smb/server/Kconfig	2023-11-29 17:07:13.294994222 +0100
@@ -56,6 +56,16 @@
 	  SMB Direct allows transferring SMB packets over RDMA. If unsure,
 	  say N.
 
+config SMB_INSECURE_SERVER
+	bool "Support for insecure SMB1/CIFS and SMB2.0 protocols"
+	depends on SMB_SERVER
+	select CRYPTO_MD4
+	default n
+
+	help
+	  This enables deprecated insecure protocols dialects: SMB1/CIFS
+	  and SMB2.0
+
 endif
 
 config SMB_SERVER_CHECK_CAP_NET_ADMIN
diff -ruw linux-6.4/fs/smb/server/Makefile linux-6.4-fbx/fs/smb/server/Makefile
--- linux-6.4/fs/smb/server/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/fs/smb/server/Makefile	2023-11-29 17:07:13.294994222 +0100
@@ -18,3 +18,4 @@
 $(obj)/ksmbd_spnego_negtokentarg.asn1.o: $(obj)/ksmbd_spnego_negtokentarg.asn1.c $(obj)/ksmbd_spnego_negtokentarg.asn1.h
 
 ksmbd-$(CONFIG_SMB_SERVER_SMBDIRECT) += transport_rdma.o
+ksmbd-$(CONFIG_SMB_INSECURE_SERVER) += smb1pdu.o smb1ops.o smb1misc.o netmisc.o
diff -ruw linux-6.4/include/asm-generic/vmlinux.lds.h linux-6.4-fbx/include/asm-generic/vmlinux.lds.h
--- linux-6.4/include/asm-generic/vmlinux.lds.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/asm-generic/vmlinux.lds.h	2023-11-29 17:07:13.391661039 +0100
@@ -350,7 +350,7 @@
 #define KERNEL_DTB()							\
 	STRUCT_ALIGN();							\
 	__dtb_start = .;						\
-	KEEP(*(.dtb.init.rodata))					\
+	KEEP(*(.dtb.rodata))						\
 	__dtb_end = .;
 
 /*
@@ -462,6 +462,7 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		__start_rodata = .;					\
+		KERNEL_DTB()						\
 		*(.rodata) *(.rodata.*)					\
 		SCHED_DATA						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
@@ -703,7 +704,6 @@
 	TIMER_OF_TABLES()						\
 	CPU_METHOD_OF_TABLES()						\
 	CPUIDLE_METHOD_OF_TABLES()					\
-	KERNEL_DTB()							\
 	IRQCHIP_OF_MATCH_TABLE()					\
 	ACPI_PROBE_TABLE(irqchip)					\
 	ACPI_PROBE_TABLE(timer)						\
diff -ruw linux-6.4/include/dt-bindings/input/linux-event-codes.h linux-6.4-fbx/include/dt-bindings/input/linux-event-codes.h
--- linux-6.4/include/dt-bindings/input/linux-event-codes.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/dt-bindings/input/linux-event-codes.h	2023-11-29 17:07:13.751661598 +0100
@@ -803,6 +803,18 @@
 #define BTN_TRIGGER_HAPPY39		0x2e6
 #define BTN_TRIGGER_HAPPY40		0x2e7
 
+#define KEY_APP_TV			0x2f1
+#define KEY_APP_REPLAY			0x2f2
+#define KEY_APP_VIDEOCLUB		0x2f3
+#define KEY_APP_WHATSON			0x2f4
+#define KEY_APP_RECORDS			0x2f5
+#define KEY_APP_MEDIA			0x2f6
+#define KEY_APP_YOUTUBE			0x2f7
+#define KEY_APP_RADIOS			0x2f8
+#define KEY_APP_CANALVOD		0x2f9
+#define KEY_APP_PIP			0x2fa
+#define KEY_APP_NETFLIX			0x2fb
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING	KEY_MUTE
 #define KEY_MAX			0x2ff
diff -ruw linux-6.4/include/linux/compiler_attributes.h linux-6.4-fbx/include/linux/compiler_attributes.h
--- linux-6.4/include/linux/compiler_attributes.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/compiler_attributes.h	2023-11-29 17:07:13.461661148 +0100
@@ -89,6 +89,19 @@
 #endif
 
 /*
+ * Optional: only supported since gcc >= 14
+ * Optional: only supported since clang >= 18
+ *
+ *   gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
+ * clang: https://reviews.llvm.org/D148381
+ */
+#if __has_attribute(__counted_by__)
+# define __counted_by(member)		__attribute__((__counted_by__(member)))
+#else
+# define __counted_by(member)
+#endif
+
+/*
  * Optional: not supported by gcc
  * Optional: only supported since clang >= 14.0
  *
diff -ruw linux-6.4/include/linux/ethtool.h linux-6.4-fbx/include/linux/ethtool.h
--- linux-6.4/include/linux/ethtool.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/ethtool.h	2023-11-29 17:07:13.478327840 +0100
@@ -912,6 +912,15 @@
 	int	(*set_mm)(struct net_device *dev, struct ethtool_mm_cfg *cfg,
 			  struct netlink_ext_ack *extack);
 	void	(*get_mm_stats)(struct net_device *dev, struct ethtool_mm_stats *stats);
+	int	(*set_shaper_param)(struct net_device *,
+				    const struct ethtool_shaper_params *);
+	int	(*get_shaper_param)(struct net_device *,
+				    struct ethtool_shaper_params *);
+	int	(*get_epon_param)(struct net_device *,
+				  struct ethtool_epon_param *);
+	int	(*set_epon_param)(struct net_device *,
+				  const struct ethtool_epon_param *);
+	struct phylink *(*get_phylink)(struct net_device *);
 };
 
 int ethtool_check_ops(const struct ethtool_ops *ops);
diff -ruw linux-6.4/include/linux/ieee80211.h linux-6.4-fbx/include/linux/ieee80211.h
--- linux-6.4/include/linux/ieee80211.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/ieee80211.h	2024-02-21 16:43:28.699803832 +0100
@@ -307,6 +307,13 @@
 #define IEEE80211_TRIGGER_TYPE_BQRP		0x6
 #define IEEE80211_TRIGGER_TYPE_NFRP		0x7
 
+/* UL-bandwidth within common_info of trigger frame */
+#define IEEE80211_TRIGGER_ULBW_MASK		0xc0000
+#define IEEE80211_TRIGGER_ULBW_20MHZ		0x0
+#define IEEE80211_TRIGGER_ULBW_40MHZ		0x1
+#define IEEE80211_TRIGGER_ULBW_80MHZ		0x2
+#define IEEE80211_TRIGGER_ULBW_160_80P80MHZ	0x3
+
 struct ieee80211_hdr {
 	__le16 frame_control;
 	__le16 duration_id;
@@ -836,9 +843,14 @@
 };
 
 /**
- * struct ieee80211_quiet_ie
+ * struct ieee80211_quiet_ie - Quiet element
+ * @count: Quiet Count
+ * @period: Quiet Period
+ * @duration: Quiet Duration
+ * @offset: Quiet Offset
  *
- * This structure refers to "Quiet information element"
+ * This structure represents the payload of the "Quiet element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.22.
  */
 struct ieee80211_quiet_ie {
 	u8 count;
@@ -848,9 +860,15 @@
 } __packed;
 
 /**
- * struct ieee80211_msrment_ie
- *
- * This structure refers to "Measurement Request/Report information element"
+ * struct ieee80211_msrment_ie - Measurement element
+ * @token: Measurement Token
+ * @mode: Measurement Report Mode
+ * @type: Measurement Type
+ * @request: Measurement Request or Measurement Report
+ *
+ * This structure represents the payload of both the "Measurement
+ * Request element" and the "Measurement Report element" as described
+ * in IEEE Std 802.11-2020 sections 9.4.2.20 and 9.4.2.21.
  */
 struct ieee80211_msrment_ie {
 	u8 token;
@@ -860,9 +878,14 @@
 } __packed;
 
 /**
- * struct ieee80211_channel_sw_ie
- *
- * This structure refers to "Channel Switch Announcement information element"
+ * struct ieee80211_channel_sw_ie - Channel Switch Announcement element
+ * @mode: Channel Switch Mode
+ * @new_ch_num: New Channel Number
+ * @count: Channel Switch Count
+ *
+ * This structure represents the payload of the "Channel Switch
+ * Announcement element" as described in IEEE Std 802.11-2020 section
+ * 9.4.2.18.
  */
 struct ieee80211_channel_sw_ie {
 	u8 mode;
@@ -871,9 +894,14 @@
 } __packed;
 
 /**
- * struct ieee80211_ext_chansw_ie
+ * struct ieee80211_ext_chansw_ie - Extended Channel Switch Announcement element
+ * @mode: Channel Switch Mode
+ * @new_operating_class: New Operating Class
+ * @new_ch_num: New Channel Number
+ * @count: Channel Switch Count
  *
- * This structure represents the "Extended Channel Switch Announcement element"
+ * This structure represents the "Extended Channel Switch Announcement
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.52.
  */
 struct ieee80211_ext_chansw_ie {
 	u8 mode;
@@ -894,8 +922,14 @@
 
 /**
  * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE
- *
- * This structure represents the "Mesh Channel Switch Paramters element"
+ * @mesh_ttl: Time To Live
+ * @mesh_flags: Flags
+ * @mesh_reason: Reason Code
+ * @mesh_pre_value: Precedence Value
+ *
+ * This structure represents the payload of the "Mesh Channel Switch
+ * Parameters element" as described in IEEE Std 802.11-2020 section
+ * 9.4.2.102.
  */
 struct ieee80211_mesh_chansw_params_ie {
 	u8 mesh_ttl;
@@ -906,6 +940,13 @@
 
 /**
  * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
+ * @new_channel_width: New Channel Width
+ * @new_center_freq_seg0: New Channel Center Frequency Segment 0
+ * @new_center_freq_seg1: New Channel Center Frequency Segment 1
+ *
+ * This structure represents the payload of the "Wide Bandwidth
+ * Channel Switch element" as described in IEEE Std 802.11-2020
+ * section 9.4.2.160.
  */
 struct ieee80211_wide_bw_chansw_ie {
 	u8 new_channel_width;
@@ -913,22 +954,42 @@
 } __packed;
 
 /**
- * struct ieee80211_tim
- *
- * This structure refers to "Traffic Indication Map information element"
+ * struct ieee80211_tim_ie - Traffic Indication Map information element
+ * @dtim_count: DTIM Count
+ * @dtim_period: DTIM Period
+ * @bitmap_ctrl: Bitmap Control
+ * @required_octet: "Syntatic sugar" to force the struct size to the
+ *                  minimum valid size when carried in a non-S1G PPDU
+ * @virtual_map: Partial Virtual Bitmap
+ *
+ * This structure represents the payload of the "TIM element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.5. Note that this
+ * definition is only applicable when the element is carried in a
+ * non-S1G PPDU. When the TIM is carried in an S1G PPDU, the Bitmap
+ * Control and Partial Virtual Bitmap may not be present.
  */
 struct ieee80211_tim_ie {
 	u8 dtim_count;
 	u8 dtim_period;
 	u8 bitmap_ctrl;
-	/* variable size: 1 - 251 bytes */
-	u8 virtual_map[1];
+	union {
+		u8 required_octet;
+		DECLARE_FLEX_ARRAY(u8, virtual_map);
+	};
 } __packed;
 
 /**
- * struct ieee80211_meshconf_ie
+ * struct ieee80211_meshconf_ie - Mesh Configuration element
+ * @meshconf_psel: Active Path Selection Protocol Identifier
+ * @meshconf_pmetric: Active Path Selection Metric Identifier
+ * @meshconf_congest: Congestion Control Mode Identifier
+ * @meshconf_synch: Synchronization Method Identifier
+ * @meshconf_auth: Authentication Protocol Identifier
+ * @meshconf_form: Mesh Formation Info
+ * @meshconf_cap: Mesh Capability (see &enum mesh_config_capab_flags)
  *
- * This structure refers to "Mesh Configuration information element"
+ * This structure represents the payload of the "Mesh Configuration
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.97.
  */
 struct ieee80211_meshconf_ie {
 	u8 meshconf_psel;
@@ -950,6 +1011,9 @@
  *	is ongoing
  * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has
  *	neighbors in deep sleep mode
+ *
+ * Enumerates the "Mesh Capability" as described in IEEE Std
+ * 802.11-2020 section 9.4.2.97.7.
  */
 enum mesh_config_capab_flags {
 	IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS		= 0x01,
@@ -960,7 +1024,7 @@
 
 #define IEEE80211_MESHCONF_FORM_CONNECTED_TO_GATE 0x1
 
-/**
+/*
  * mesh channel switch parameters element's flag indicator
  *
  */
@@ -969,9 +1033,17 @@
 #define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2)
 
 /**
- * struct ieee80211_rann_ie
+ * struct ieee80211_rann_ie - RANN (root announcement) element
+ * @rann_flags: Flags
+ * @rann_hopcount: Hop Count
+ * @rann_ttl: Element TTL
+ * @rann_addr: Root Mesh STA Address
+ * @rann_seq: HWMP Sequence Number
+ * @rann_interval: Interval
+ * @rann_metric: Metric
  *
- * This structure refers to "Root Announcement information element"
+ * This structure represents the payload of the "RANN element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.111.
  */
 struct ieee80211_rann_ie {
 	u8 rann_flags;
@@ -993,7 +1065,7 @@
 };
 
 /**
- * enum ieee80211_opmode_bits - VHT operating mode field bits
+ * enum ieee80211_vht_opmode_bits - VHT operating mode field bits
  * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK: channel width mask
  * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: 20 MHz channel width
  * @IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ: 40 MHz channel width
@@ -1042,9 +1114,12 @@
 #define WLAN_USER_POSITION_LEN 16
 
 /**
- * struct ieee80211_tpc_report_ie
+ * struct ieee80211_tpc_report_ie - TPC Report element
+ * @tx_power: Transmit Power
+ * @link_margin: Link Margin
  *
- * This structure refers to "TPC Report element"
+ * This structure represents the payload of the "TPC Report element" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.16.
  */
 struct ieee80211_tpc_report_ie {
 	u8 tx_power;
@@ -1062,9 +1137,14 @@
 } __packed;
 
 /**
- * struct ieee80211_s1g_bcn_compat_ie
- *
- * S1G Beacon Compatibility element
+ * struct ieee80211_s1g_bcn_compat_ie - S1G Beacon Compatibility element
+ * @compat_info: Compatibility Information
+ * @beacon_int: Beacon Interval
+ * @tsf_completion: TSF Completion
+ *
+ * This structure represents the payload of the "S1G Beacon
+ * Compatibility element" as described in IEEE Std 802.11-2020 section
+ * 9.4.2.196.
  */
 struct ieee80211_s1g_bcn_compat_ie {
 	__le16 compat_info;
@@ -1073,9 +1153,15 @@
 } __packed;
 
 /**
- * struct ieee80211_s1g_oper_ie
+ * struct ieee80211_s1g_oper_ie - S1G Operation element
+ * @ch_width: S1G Operation Information Channel Width
+ * @oper_class: S1G Operation Information Operating Class
+ * @primary_ch: S1G Operation Information Primary Channel Number
+ * @oper_ch: S1G Operation Information  Channel Center Frequency
+ * @basic_mcs_nss: Basic S1G-MCS and NSS Set
  *
- * S1G Operation element
+ * This structure represents the payload of the "S1G Operation
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.212.
  */
 struct ieee80211_s1g_oper_ie {
 	u8 ch_width;
@@ -1086,9 +1172,13 @@
 } __packed;
 
 /**
- * struct ieee80211_aid_response_ie
+ * struct ieee80211_aid_response_ie - AID Response element
+ * @aid: AID/Group AID
+ * @switch_count: AID Switch Count
+ * @response_int: AID Response Interval
  *
- * AID Response element
+ * This structure represents the payload of the "AID Response element"
+ * as described in IEEE Std 802.11-2020 section 9.4.2.194.
  */
 struct ieee80211_aid_response_ie {
 	__le16 aid;
@@ -1163,6 +1253,30 @@
 	u8 params[];
 } __packed;
 
+#define IEEE80211_TTLM_MAX_CNT				2
+#define IEEE80211_TTLM_CONTROL_DIRECTION		0x03
+#define IEEE80211_TTLM_CONTROL_DEF_LINK_MAP		0x04
+#define IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT	0x08
+#define IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT	0x10
+#define IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE		0x20
+
+#define IEEE80211_TTLM_DIRECTION_DOWN		0
+#define IEEE80211_TTLM_DIRECTION_UP		1
+#define IEEE80211_TTLM_DIRECTION_BOTH		2
+
+/**
+ * struct ieee80211_ttlm_elem - TID-To-Link Mapping element
+ *
+ * Defined in section 9.4.2.314 in P802.11be_D4
+ *
+ * @control: the first part of control field
+ * @optional: the second part of control field
+ */
+struct ieee80211_ttlm_elem {
+	u8 control;
+	u8 optional[];
+} __packed;
+
 struct ieee80211_mgmt {
 	__le16 frame_control;
 	__le16 duration;
@@ -1349,8 +1463,11 @@
 /* Supported rates membership selectors */
 #define BSS_MEMBERSHIP_SELECTOR_HT_PHY	127
 #define BSS_MEMBERSHIP_SELECTOR_VHT_PHY	126
-#define BSS_MEMBERSHIP_SELECTOR_HE_PHY	122
+#define BSS_MEMBERSHIP_SELECTOR_GLK	125
+#define BSS_MEMBERSHIP_SELECTOR_EPS	124
 #define BSS_MEMBERSHIP_SELECTOR_SAE_H2E 123
+#define BSS_MEMBERSHIP_SELECTOR_HE_PHY	122
+#define BSS_MEMBERSHIP_SELECTOR_EHT_PHY	121
 
 /* mgmt header + 1 byte category code */
 #define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
@@ -1486,7 +1603,7 @@
 /*
  * Peer-to-Peer IE attribute related definitions.
  */
-/**
+/*
  * enum ieee80211_p2p_attr_id - identifies type of peer-to-peer attribute.
  */
 enum ieee80211_p2p_attr_id {
@@ -1536,10 +1653,16 @@
 #define IEEE80211_P2P_OPPPS_CTWINDOW_MASK	0x7F
 
 /**
- * struct ieee80211_bar - HT Block Ack Request
+ * struct ieee80211_bar - Block Ack Request frame format
+ * @frame_control: Frame Control
+ * @duration: Duration
+ * @ra: RA
+ * @ta: TA
+ * @control: BAR Control
+ * @start_seq_num: Starting Sequence Number (see Figure 9-37)
  *
- * This structure refers to "HT BlockAckReq" as
- * described in 802.11n draft section 7.2.1.7.1
+ * This structure represents the "BlockAckReq frame format"
+ * as described in IEEE Std 802.11-2020 section 9.3.1.7.
  */
 struct ieee80211_bar {
 	__le16 frame_control;
@@ -1560,13 +1683,17 @@
 #define IEEE80211_HT_MCS_MASK_LEN		10
 
 /**
- * struct ieee80211_mcs_info - MCS information
+ * struct ieee80211_mcs_info - Supported MCS Set field
  * @rx_mask: RX mask
  * @rx_highest: highest supported RX rate. If set represents
  *	the highest supported RX data rate in units of 1 Mbps.
  *	If this field is 0 this value should not be used to
  *	consider the highest RX data rate supported.
  * @tx_params: TX parameters
+ * @reserved: Reserved bits
+ *
+ * This structure represents the "Supported MCS Set field" as
+ * described in IEEE Std 802.11-2020 section 9.4.2.55.4.
  */
 struct ieee80211_mcs_info {
 	u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
@@ -1585,6 +1712,8 @@
 #define		IEEE80211_HT_MCS_TX_MAX_STREAMS	4
 #define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION	0x10
 
+#define IEEE80211_HT_MCS_CHAINS(mcs) ((mcs) == 32 ? 1 : (1 + ((mcs) >> 3)))
+
 /*
  * 802.11n D5.0 20.3.5 / 20.6 says:
  * - indices 0 to 7 and 32 are single spatial stream
@@ -1597,10 +1726,16 @@
 	(IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8)
 
 /**
- * struct ieee80211_ht_cap - HT capabilities
+ * struct ieee80211_ht_cap - HT capabilities element
+ * @cap_info: HT Capability Information
+ * @ampdu_params_info: A-MPDU Parameters
+ * @mcs: Supported MCS Set
+ * @extended_ht_cap_info: HT Extended Capabilities
+ * @tx_BF_cap_info: Transmit Beamforming Capabilities
+ * @antenna_selection_info: ASEL Capability
  *
- * This structure is the "HT capabilities element" as
- * described in 802.11n D5.0 7.3.2.57
+ * This structure represents the payload of the "HT Capabilities
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.55.
  */
 struct ieee80211_ht_cap {
 	__le16 cap_info;
@@ -1688,9 +1823,14 @@
 
 /**
  * struct ieee80211_ht_operation - HT operation IE
+ * @primary_chan: Primary Channel
+ * @ht_param: HT Operation Information parameters
+ * @operation_mode: HT Operation Information operation mode
+ * @stbc_param: HT Operation Information STBC params
+ * @basic_set: Basic HT-MCS Set
  *
- * This structure is the "HT operation element" as
- * described in 802.11n-2009 7.3.2.57
+ * This structure represents the payload of the "HT Operation
+ * element" as described in IEEE Std 802.11-2020 section 9.4.2.56.
  */
 struct ieee80211_ht_operation {
 	u8 primary_chan;
@@ -1859,9 +1999,12 @@
 
 /**
  * struct ieee80211_he_cap_elem - HE capabilities element
+ * @mac_cap_info: HE MAC Capabilities Information
+ * @phy_cap_info: HE PHY Capabilities Information
  *
- * This structure is the "HE capabilities element" fixed fields as
- * described in P802.11ax_D4.0 section 9.4.2.242.2 and 9.4.2.242.3
+ * This structure represents the fixed fields of the payload of the
+ * "HE capabilities element" as described in IEEE Std 802.11ax-2021
+ * sections 9.4.2.248.2 and 9.4.2.248.3.
  */
 struct ieee80211_he_cap_elem {
 	u8 mac_cap_info[6];
@@ -1920,35 +2063,45 @@
 } __packed;
 
 /**
- * struct ieee80211_he_operation - HE capabilities element
+ * struct ieee80211_he_operation - HE Operation element
+ * @he_oper_params: HE Operation Parameters + BSS Color Information
+ * @he_mcs_nss_set: Basic HE-MCS And NSS Set
+ * @optional: Optional fields VHT Operation Information, Max Co-Hosted
+ *            BSSID Indicator, and 6 GHz Operation Information
  *
- * This structure is the "HE operation element" fields as
- * described in P802.11ax_D4.0 section 9.4.2.243
+ * This structure represents the payload of the "HE Operation
+ * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.249.
  */
 struct ieee80211_he_operation {
 	__le32 he_oper_params;
 	__le16 he_mcs_nss_set;
-	/* Optional 0,1,3,4,5,7 or 8 bytes: depends on @he_oper_params */
 	u8 optional[];
 } __packed;
 
 /**
- * struct ieee80211_he_spr - HE spatial reuse element
- *
- * This structure is the "HE spatial reuse element" element as
- * described in P802.11ax_D4.0 section 9.4.2.241
+ * struct ieee80211_he_spr - Spatial Reuse Parameter Set element
+ * @he_sr_control: SR Control
+ * @optional: Optional fields Non-SRG OBSS PD Max Offset, SRG OBSS PD
+ *            Min Offset, SRG OBSS PD Max Offset, SRG BSS Color
+ *            Bitmap, and SRG Partial BSSID Bitmap
+ *
+ * This structure represents the payload of the "Spatial Reuse
+ * Parameter Set element" as described in IEEE Std 802.11ax-2021
+ * section 9.4.2.252.
  */
 struct ieee80211_he_spr {
 	u8 he_sr_control;
-	/* Optional 0 to 19 bytes: depends on @he_sr_control */
 	u8 optional[];
 } __packed;
 
 /**
  * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field
+ * @aifsn: ACI/AIFSN
+ * @ecw_min_max: ECWmin/ECWmax
+ * @mu_edca_timer: MU EDCA Timer
  *
- * This structure is the "MU AC Parameter Record" fields as
- * described in P802.11ax_D4.0 section 9.4.2.245
+ * This structure represents the "MU AC Parameter Record" as described
+ * in IEEE Std 802.11ax-2021 section 9.4.2.251, Figure 9-788p.
  */
 struct ieee80211_he_mu_edca_param_ac_rec {
 	u8 aifsn;
@@ -1958,9 +2111,14 @@
 
 /**
  * struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element
+ * @mu_qos_info: QoS Info
+ * @ac_be: MU AC_BE Parameter Record
+ * @ac_bk: MU AC_BK Parameter Record
+ * @ac_vi: MU AC_VI Parameter Record
+ * @ac_vo: MU AC_VO Parameter Record
  *
- * This structure is the "MU EDCA Parameter Set element" fields as
- * described in P802.11ax_D4.0 section 9.4.2.245
+ * This structure represents the payload of the "MU EDCA Parameter Set
+ * element" as described in IEEE Std 802.11ax-2021 section 9.4.2.251.
  */
 struct ieee80211_mu_edca_param_set {
 	u8 mu_qos_info;
@@ -1993,13 +2151,19 @@
  * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
  *     supported for reception and the maximum number of spatial streams
  *     supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
  */
 struct ieee80211_eht_mcs_nss_supp_20mhz_only {
+	union {
+		struct {
 	u8 rx_tx_mcs7_max_nss;
 	u8 rx_tx_mcs9_max_nss;
 	u8 rx_tx_mcs11_max_nss;
 	u8 rx_tx_mcs13_max_nss;
 };
+		u8 rx_tx_max_nss[4];
+	};
+};
 
 /**
  * struct ieee80211_eht_mcs_nss_supp_bw - EHT max supported NSS per MCS (except
@@ -2018,12 +2182,18 @@
  * @rx_tx_mcs13_max_nss: indicates the maximum number of spatial streams
  *     supported for reception and the maximum number of spatial streams
  *     supported for transmission for MCS 12 - 13.
+ * @rx_tx_max_nss: array of the previous fields for easier loop access
  */
 struct ieee80211_eht_mcs_nss_supp_bw {
+	union {
+		struct {
 	u8 rx_tx_mcs9_max_nss;
 	u8 rx_tx_mcs11_max_nss;
 	u8 rx_tx_mcs13_max_nss;
 };
+		u8 rx_tx_max_nss[3];
+	};
+};
 
 /**
  * struct ieee80211_eht_cap_elem_fixed - EHT capabilities fixed data
@@ -2075,7 +2245,7 @@
  */
 struct ieee80211_eht_operation {
 	u8 params;
-	__le32 basic_mcs_nss;
+	struct ieee80211_eht_mcs_nss_supp_20mhz_only basic_mcs_nss;
 	u8 optional[];
 } __packed;
 
@@ -2162,9 +2332,9 @@
  * enum ieee80211_ap_reg_power - regulatory power for a Access Point
  *
  * @IEEE80211_REG_UNSET_AP: Access Point has no regulatory power mode
- * @IEEE80211_REG_LPI: Indoor Access Point
- * @IEEE80211_REG_SP: Standard power Access Point
- * @IEEE80211_REG_VLP: Very low power Access Point
+ * @IEEE80211_REG_LPI_AP: Indoor Access Point
+ * @IEEE80211_REG_SP_AP: Standard power Access Point
+ * @IEEE80211_REG_VLP_AP: Very low power Access Point
  * @IEEE80211_REG_AP_POWER_AFTER_LAST: internal
  * @IEEE80211_REG_AP_POWER_MAX: maximum value
  */
@@ -2552,7 +2722,7 @@
 #define IEEE80211_6GHZ_CTRL_REG_SP_AP	1
 
 /**
- * ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
+ * struct ieee80211_he_6ghz_oper - HE 6 GHz operation Information field
  * @primary: primary channel
  * @control: control flags
  * @ccfs0: channel center frequency segment 0
@@ -2599,9 +2769,13 @@
 };
 
 /**
- * struct ieee80211_tx_pwr_env
- *
- * This structure represents the "Transmit Power Envelope element"
+ * struct ieee80211_tx_pwr_env - Transmit Power Envelope
+ * @tx_power_info: Transmit Power Information field
+ * @tx_power: Maximum Transmit Power field
+ *
+ * This structure represents the payload of the "Transmit Power
+ * Envelope element" as described in IEEE Std 802.11ax-2021 section
+ * 9.4.2.161
  */
 struct ieee80211_tx_pwr_env {
 	u8 tx_power_info;
@@ -2856,6 +3030,7 @@
 
 /* Maximum number of supported EHT LTF is split */
 #define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK	0xc0
+#define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF		0x40
 #define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK	0x07
 
 #define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK			0x78
@@ -2918,6 +3093,7 @@
 #define IEEE80211_EHT_PPE_THRES_NSS_POS			0
 #define IEEE80211_EHT_PPE_THRES_NSS_MASK		0xf
 #define IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK	0x1f0
+#define IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_POS   4
 #define IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE		3
 #define IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE	9
 
@@ -2997,6 +3173,28 @@
 	return len >= needed;
 }
 
+#define IEEE80211_BW_IND_DIS_SUBCH_PRESENT	BIT(1)
+
+struct ieee80211_bandwidth_indication {
+	u8 params;
+	struct ieee80211_eht_operation_info info;
+} __packed;
+
+static inline bool
+ieee80211_bandwidth_indication_size_ok(const u8 *data, u8 len)
+{
+	const struct ieee80211_bandwidth_indication *bwi = (const void *)data;
+
+	if (len < sizeof(*bwi))
+		return false;
+
+	if (bwi->params & IEEE80211_BW_IND_DIS_SUBCH_PRESENT &&
+	    len < sizeof(*bwi) + 2)
+		return false;
+
+	return true;
+}
+
 #define LISTEN_INT_USF	GENMASK(15, 14)
 #define LISTEN_INT_UI	GENMASK(13, 0)
 
@@ -3454,6 +3652,8 @@
 	WLAN_EID_EXT_EHT_OPERATION = 106,
 	WLAN_EID_EXT_EHT_MULTI_LINK = 107,
 	WLAN_EID_EXT_EHT_CAPABILITY = 108,
+	WLAN_EID_EXT_TID_TO_LINK_MAPPING = 109,
+	WLAN_EID_EXT_BANDWIDTH_INDICATION = 135,
 };
 
 /* Action category code */
@@ -3493,6 +3693,16 @@
 	WLAN_ACTION_SPCT_CHL_SWITCH = 4,
 };
 
+/* RADIO_MEASUREMENT action code */
+enum ieee80211_radio_measurement_actioncode {
+	WLAN_ACTION_RADIO_MSR_RM_REQ = 0,
+	WLAN_ACTION_RADIO_MSR_RM_REP = 1,
+	WLAN_ACTION_RADIO_MSR_LINK_MSR_REQ = 2,
+	WLAN_ACTION_RADIO_MSR_LINK_MSR_REP = 3,
+	WLAN_ACTION_RADIO_MSR_NBOR_REP_REQ = 4,
+	WLAN_ACTION_RADIO_MSR_NBOR_REP_REP = 5,
+};
+
 /* HT action codes */
 enum ieee80211_ht_actioncode {
 	WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0,
@@ -4221,6 +4431,35 @@
 }
 
 /**
+ * ieee80211_is_protected_dual_of_public_action - check if skb contains a
+ * protected dual of public action management frame
+ * @skb: the skb containing the frame, length will be checked
+ *
+ * Return: true if the skb contains a protected dual of public action
+ * management frame, false otherwise.
+ */
+static inline bool
+ieee80211_is_protected_dual_of_public_action(struct sk_buff *skb)
+{
+	u8 action;
+
+	if (!ieee80211_is_public_action((void *)skb->data, skb->len) ||
+	    skb->len < IEEE80211_MIN_ACTION_SIZE + 1)
+		return false;
+
+	action = *(u8 *)(skb->data + IEEE80211_MIN_ACTION_SIZE);
+
+	return action != WLAN_PUB_ACTION_20_40_BSS_COEX &&
+		action != WLAN_PUB_ACTION_DSE_REG_LOC_ANN &&
+		action != WLAN_PUB_ACTION_MSMT_PILOT &&
+		action != WLAN_PUB_ACTION_TDLS_DISCOVER_RES &&
+		action != WLAN_PUB_ACTION_LOC_TRACK_NOTI &&
+		action != WLAN_PUB_ACTION_FTM_REQUEST &&
+		action != WLAN_PUB_ACTION_FTM_RESPONSE &&
+		action != WLAN_PUB_ACTION_FILS_DISCOVERY;
+}
+
+/**
  * _ieee80211_is_group_privacy_action - check if frame is a group addressed
  * privacy action frame
  * @hdr: the frame
@@ -4291,12 +4530,11 @@
 /**
  * ieee80211_get_tdls_action - get tdls packet action (or -1, if not tdls packet)
  * @skb: the skb containing the frame, length will not be checked
- * @hdr_size: the size of the ieee80211_hdr that starts at skb->data
  *
  * This function assumes the frame is a data frame, and that the network header
  * is in the correct place.
  */
-static inline int ieee80211_get_tdls_action(struct sk_buff *skb, u32 hdr_size)
+static inline int ieee80211_get_tdls_action(struct sk_buff *skb)
 {
 	if (!skb_is_nonlinear(skb) &&
 	    skb->len > (skb_network_offset(skb) + 2)) {
@@ -4462,7 +4700,7 @@
 	return (const u8 *)element == (const u8 *)data + datalen;
 }
 
-/**
+/*
  * RSNX Capabilities:
  * bits 0-3: Field length (n-1)
  */
@@ -4477,8 +4715,8 @@
 #define IEEE80211_AP_INFO_TBTT_HDR_FILTERED			0x04
 #define IEEE80211_AP_INFO_TBTT_HDR_COLOC			0x08
 #define IEEE80211_AP_INFO_TBTT_HDR_COUNT			0xF0
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM		9
-#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM	13
+#define IEEE80211_TBTT_INFO_TYPE_TBTT				0
+#define IEEE80211_TBTT_INFO_TYPE_MLD				1
 
 #define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED		0x01
 #define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID			0x02
@@ -4488,6 +4726,9 @@
 #define IEEE80211_RNR_TBTT_PARAMS_PROBE_ACTIVE			0x20
 #define IEEE80211_RNR_TBTT_PARAMS_COLOC_AP			0x40
 
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_NO_LIMIT			127
+#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED			-128
+
 struct ieee80211_neighbor_ap_info {
 	u8 tbtt_info_hdr;
 	u8 tbtt_info_len;
@@ -4502,6 +4743,42 @@
 	IEEE80211_RANGE_PARAMS_MAX_TOTAL_LTF_UNSPECIFIED,
 };
 
+/*
+ * reduced neighbor report, based on Draft P802.11be_D3.0,
+ * section 9.4.2.170.2.
+ */
+struct ieee80211_rnr_mld_params {
+	u8 mld_id;
+	__le16 params;
+} __packed;
+
+#define IEEE80211_RNR_MLD_PARAMS_LINK_ID			0x000F
+#define IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT		0x0FF0
+#define IEEE80211_RNR_MLD_PARAMS_UPDATES_INCLUDED		0x1000
+#define IEEE80211_RNR_MLD_PARAMS_DISABLED_LINK			0x2000
+
+/* Format of the TBTT information element if it has 7, 8 or 9 bytes */
+struct ieee80211_tbtt_info_7_8_9 {
+	u8 tbtt_offset;
+	u8 bssid[ETH_ALEN];
+
+	/* The following element is optional, structure may not grow */
+	u8 bss_params;
+	s8 psd_20;
+} __packed;
+
+/* Format of the TBTT information element if it has >= 11 bytes */
+struct ieee80211_tbtt_info_ge_11 {
+	u8 tbtt_offset;
+	u8 bssid[ETH_ALEN];
+	__le32 short_ssid;
+
+	/* The following elements are optional, structure may grow */
+	u8 bss_params;
+	s8 psd_20;
+	struct ieee80211_rnr_mld_params mld_params;
+} __packed;
+
 /* multi-link device */
 #define IEEE80211_MLD_MAX_NUM_LINKS	15
 
@@ -4529,6 +4806,14 @@
 #define IEEE80211_MED_SYNC_DELAY_SYNC_OFDM_ED_THRESH	0x0f00
 #define IEEE80211_MED_SYNC_DELAY_SYNC_MAX_NUM_TXOPS	0xf000
 
+/*
+ * Described in P802.11be_D3.0
+ * dot11MSDTimerDuration should default to 5484 (i.e. 171.375)
+ * dot11MSDOFDMEDthreshold defaults to -72 (i.e. 0)
+ * dot11MSDTXOPMAX defaults to 1
+ */
+#define IEEE80211_MED_SYNC_DELAY_DEFAULT		0x10ac
+
 #define IEEE80211_EML_CAP_EMLSR_SUPP			0x0001
 #define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY		0x000e
 #define  IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_0US		0
@@ -4611,15 +4896,12 @@
 	case IEEE80211_ML_CONTROL_TYPE_BASIC:
 	case IEEE80211_ML_CONTROL_TYPE_PREQ:
 	case IEEE80211_ML_CONTROL_TYPE_TDLS:
+	case IEEE80211_ML_CONTROL_TYPE_RECONF:
 		/*
 		 * The length is the first octet pointed by mle->variable so no
 		 * need to add anything
 		 */
 		break;
-	case IEEE80211_ML_CONTROL_TYPE_RECONF:
-		if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR)
-			common += ETH_ALEN;
-		return common;
 	case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS:
 		if (control & IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR)
 			common += ETH_ALEN;
@@ -4633,6 +4915,95 @@
 }
 
 /**
+ * ieee80211_mle_get_bss_param_ch_cnt - returns the BSS parameter change count
+ * @mle: the basic multi link element
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the BSS parameter change count value can't be found (the presence bit
+ * for it is clear), 0 will be returned.
+ */
+static inline u8
+ieee80211_mle_get_bss_param_ch_cnt(const struct ieee80211_multi_link_elem *mle)
+{
+	u16 control = le16_to_cpu(mle->control);
+	const u8 *common = mle->variable;
+
+	/* common points now at the beginning of ieee80211_mle_basic_common_info */
+	common += sizeof(struct ieee80211_mle_basic_common_info);
+
+	if (!(control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT))
+		return 0;
+
+	if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+		common += 1;
+
+	return *common;
+}
+
+/**
+ * ieee80211_mle_get_eml_med_sync_delay - returns the medium sync delay
+ * @data: pointer to the multi link EHT IE
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the medium synchronization is not present, then the default value is
+ * returned.
+ */
+static inline u16 ieee80211_mle_get_eml_med_sync_delay(const u8 *data)
+{
+	const struct ieee80211_multi_link_elem *mle = (const void *)data;
+	u16 control = le16_to_cpu(mle->control);
+	const u8 *common = mle->variable;
+
+	/* common points now at the beginning of ieee80211_mle_basic_common_info */
+	common += sizeof(struct ieee80211_mle_basic_common_info);
+
+	if (!(control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY))
+		return IEEE80211_MED_SYNC_DELAY_DEFAULT;
+
+	if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+		common += 1;
+	if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
+		common += 1;
+
+	return get_unaligned_le16(common);
+}
+
+/**
+ * ieee80211_mle_get_eml_cap - returns the EML capability
+ * @data: pointer to the multi link EHT IE
+ *
+ * The element is assumed to be of the correct type (BASIC) and big enough,
+ * this must be checked using ieee80211_mle_type_ok().
+ *
+ * If the EML capability is not present, 0 will be returned.
+ */
+static inline u16 ieee80211_mle_get_eml_cap(const u8 *data)
+{
+	const struct ieee80211_multi_link_elem *mle = (const void *)data;
+	u16 control = le16_to_cpu(mle->control);
+	const u8 *common = mle->variable;
+
+	/* common points now at the beginning of ieee80211_mle_basic_common_info */
+	common += sizeof(struct ieee80211_mle_basic_common_info);
+
+	if (!(control & IEEE80211_MLC_BASIC_PRES_EML_CAPA))
+		return 0;
+
+	if (control & IEEE80211_MLC_BASIC_PRES_LINK_ID)
+		common += 1;
+	if (control & IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT)
+		common += 1;
+	if (control & IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY)
+		common += 2;
+
+	return get_unaligned_le16(common);
+}
+
+/**
  * ieee80211_mle_size_ok - validate multi-link element size
  * @data: pointer to the element data
  * @len: length of the containing element
@@ -4700,6 +5071,28 @@
 	return mle->variable[0] >= common;
 }
 
+/**
+ * ieee80211_mle_type_ok - validate multi-link element type and size
+ * @data: pointer to the element data
+ * @type: expected type of the element
+ * @len: length of the containing element
+ */
+static inline bool ieee80211_mle_type_ok(const u8 *data, u8 type, size_t len)
+{
+	const struct ieee80211_multi_link_elem *mle = (const void *)data;
+	u16 control;
+
+	if (!ieee80211_mle_size_ok(data, len))
+		return false;
+
+	control = le16_to_cpu(mle->control);
+
+	if (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE) == type)
+		return true;
+
+	return false;
+}
+
 enum ieee80211_mle_subelems {
 	IEEE80211_MLE_SUBELEM_PER_STA_PROFILE		= 0,
 	IEEE80211_MLE_SUBELEM_FRAGMENT		        = 254,
@@ -4722,11 +5115,13 @@
 } __packed;
 
 /**
- * ieee80211_mle_sta_prof_size_ok - validate multi-link element sta profile size
+ * ieee80211_mle_basic_sta_prof_size_ok - validate basic multi-link element sta
+ *	profile size
  * @data: pointer to the sub element data
  * @len: length of the containing sub element
  */
-static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len)
+static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data,
+							size_t len)
 {
 	const struct ieee80211_mle_per_sta_profile *prof = (const void *)data;
 	u16 control;
@@ -4746,25 +5141,196 @@
 		info_len += 8;
 	if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
 		info_len += 2;
-	if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)
-		info_len += 1;
-
 	if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
-	    control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) {
+	    control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {
 		if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
 			info_len += 2;
 		else
 			info_len += 1;
 	}
+	if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)
+		info_len += 1;
 
 	return prof->sta_info_len >= info_len &&
 	       fixed + prof->sta_info_len <= len;
 }
 
+/**
+ * ieee80211_mle_basic_sta_prof_bss_param_ch_cnt - get per-STA profile BSS
+ *	parameter change count
+ * @prof: the per-STA profile, having been checked with
+ *	ieee80211_mle_basic_sta_prof_size_ok() for the correct length
+ *
+ * Return: The BSS parameter change count value if present, 0 otherwise.
+ */
+static inline u8
+ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(const struct ieee80211_mle_per_sta_profile *prof)
+{
+	u16 control = le16_to_cpu(prof->control);
+	const u8 *pos = prof->variable;
+
+	if (!(control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT))
+		return 0;
+
+	if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT)
+		pos += 6;
+	if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT)
+		pos += 2;
+	if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT)
+		pos += 8;
+	if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
+		pos += 2;
+	if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
+	    control & IEEE80211_MLE_STA_CONTROL_NSTR_LINK_PAIR_PRESENT) {
+		if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
+			pos += 2;
+		else
+			pos += 1;
+	}
+
+	return *pos;
+}
+
+#define IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID			0x000f
+#define IEEE80211_MLE_STA_RECONF_CONTROL_COMPLETE_PROFILE		0x0010
+#define IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT		0x0020
+#define IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT		0x0040
+#define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_UPDATE_TYPE		0x0780
+#define IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT	0x0800
+
+/**
+ * ieee80211_mle_reconf_sta_prof_size_ok - validate reconfiguration multi-link
+ *	element sta profile size.
+ * @data: pointer to the sub element data
+ * @len: length of the containing sub element
+ */
+static inline bool ieee80211_mle_reconf_sta_prof_size_ok(const u8 *data,
+							 size_t len)
+{
+	const struct ieee80211_mle_per_sta_profile *prof = (const void *)data;
+	u16 control;
+	u8 fixed = sizeof(*prof);
+	u8 info_len = 1;
+
+	if (len < fixed)
+		return false;
+
+	control = le16_to_cpu(prof->control);
+
+	if (control & IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT)
+		info_len += ETH_ALEN;
+	if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT)
+		info_len += 2;
+	if (control & IEEE80211_MLE_STA_RECONF_CONTROL_OPERATION_PARAMS_PRESENT)
+		info_len += 2;
+
+	return prof->sta_info_len >= info_len &&
+	       fixed + prof->sta_info_len - 1 <= len;
+}
+
+static inline bool ieee80211_tid_to_link_map_size_ok(const u8 *data, size_t len)
+{
+	const struct ieee80211_ttlm_elem *t2l = (const void *)data;
+	u8 control, fixed = sizeof(*t2l), elem_len = 0;
+
+	if (len < fixed)
+		return false;
+
+	control = t2l->control;
+
+	if (control & IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT)
+		elem_len += 2;
+	if (control & IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT)
+		elem_len += 3;
+
+	if (!(control & IEEE80211_TTLM_CONTROL_DEF_LINK_MAP)) {
+		u8 bm_size;
+
+		elem_len += 1;
+		if (len < fixed + elem_len)
+			return false;
+
+		if (control & IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE)
+			bm_size = 1;
+		else
+			bm_size = 2;
+
+		elem_len += hweight8(t2l->optional[0]) * bm_size;
+	}
+
+	return len >= fixed + elem_len;
+}
+
 #define for_each_mle_subelement(_elem, _data, _len)			\
 	if (ieee80211_mle_size_ok(_data, _len))				\
 		for_each_element(_elem,					\
 				 _data + ieee80211_mle_common_size(_data),\
 				 _len - ieee80211_mle_common_size(_data))
 
+/**
+ * enum ieee80211_critical_updates - Critical Update (CU) flags
+ *
+ * These flags are used to indicate the type of critical update happening
+ * on a link in an interface.
+ *
+ * @IEEE80211_CU_INCLUDE_CSA_ELEM: critical update due to inclusion of a Channel
+ *	Switch Announcement element.
+ * @IEEE80211_CU_INCLUDE_ECSA_ELEM: critical update due to inclusion of an
+ *	Extended Channel Switch Announcement element.
+ * @IEEE80211_CU_MODIFY_EDCA_PARAM_ELEM: critical update due to modification of
+ *	the EDCA parameters element.
+ * @IEEE80211_CU_INCLUDE_QUIET_ELEM: critical update due to inclusion of a Quiet
+ *	element.
+ * @IEEE80211_CU_MODIFY_DSSS_PARAM_ELEM: critical update due to modification of
+ *	the DSSS Parameter Set.
+ * @IEEE80211_CU_MODIFY_HT_OPER_ELEM: critical update due to modification of the
+ *	HT Operation element
+ * @IEEE80211_CU_INCLUDE_WBCS_ELEM: critical update due to inclusion of a Wide
+ *	Bandwidth Channel Switch element.
+ * @IEEE80211_CU_INCLUDE_CSW_ELEM: critical update due to inclusion of a Channel
+ *	Switch Wrapper element.
+ * @IEEE80211_CU_INCLUDE_OMN_ELEM: critical update due to inclusion of an
+ *	Operating Mode Notification element.
+ * @IEEE80211_CU_INCLUDE_Q_CHAN_ELEM: critical update due to inclusion of a
+ *	Quiet Channel element.
+ * @IEEE80211_CU_MODIFY_VHT_OPER_ELEM: critical update due to modification of the
+ *	VHT Operation element.
+ * @IEEE80211_CU_MODIFY_HE_OPER_ELEM: critical update due to modification of the
+ *	HE Operation element.
+ * @IEEE80211_CU_INCLUDE_B_TWT_ELEM: critical update due to inclusion a
+ *	Broadcast TWT element.
+ * @IEEE80211_CU_INCLUDE_B_TWT_EXIST_ELEM: critical update due to inclusion of a
+ *	Broadcast TWT Parameter Set field in an existing Broadcast TWT element.
+ * @IEEE80211_CU_INCLUDE_BCCA_ELEM: critical update due to inclusion of the BSS
+ *	Color Change Announcement element.
+ * @IEEE80211_CU_MODIFY_MU_EDCA_PARAM_ELEM: critical update due to modification
+ *	of the MU EDCA Parameter Set element.
+ * @IEEE80211_CU_MODIFY_SR_PARAM_ELEM: critical update due to modification of the
+ *	Spatial Reuse Parameter Set element.
+ * @IEEE80211_CU_MODIFY_UORA_PARAM_ELEM: critical update due to modification of
+ *	the UORA Parameter Set element.
+ * @IEEE80211_CU_MODIFY_EHT_OPER_ELEM: critical update due to modification of the
+ *	EHT Operation element.
+ */
+enum ieee80211_critical_updates {
+	IEEE80211_CU_INCLUDE_CSA_ELEM			= 1 << 0,
+	IEEE80211_CU_INCLUDE_ECSA_ELEM			= 1 << 1,
+	IEEE80211_CU_MODIFY_EDCA_PARAM_ELEM		= 1 << 2,
+	IEEE80211_CU_INCLUDE_QUIET_ELEM			= 1 << 3,
+	IEEE80211_CU_MODIFY_DSSS_PARAM_ELEM		= 1 << 4,
+	IEEE80211_CU_MODIFY_HT_OPER_ELEM		= 1 << 5,
+	IEEE80211_CU_INCLUDE_WBCS_ELEM			= 1 << 6,
+	IEEE80211_CU_INCLUDE_CSW_ELEM			= 1 << 7,
+	IEEE80211_CU_INCLUDE_OMN_ELEM			= 1 << 8,
+	IEEE80211_CU_INCLUDE_Q_CHAN_ELEM		= 1 << 9,
+	IEEE80211_CU_MODIFY_VHT_OPER_ELEM		= 1 << 10,
+	IEEE80211_CU_MODIFY_HE_OPER_ELEM		= 1 << 11,
+	IEEE80211_CU_INCLUDE_B_TWT_ELEM			= 1 << 12,
+	IEEE80211_CU_INCLUDE_B_TWT_EXIST_ELEM		= 1 << 13,
+	IEEE80211_CU_INCLUDE_BCCA_ELEM			= 1 << 14,
+	IEEE80211_CU_MODIFY_MU_EDCA_PARAM_ELEM		= 1 << 15,
+	IEEE80211_CU_MODIFY_SR_PARAM_ELEM		= 1 << 16,
+	IEEE80211_CU_MODIFY_UORA_PARAM_ELEM		= 1 << 17,
+	IEEE80211_CU_MODIFY_EHT_OPER_ELEM		= 1 << 18,
+};
 #endif /* LINUX_IEEE80211_H */
diff -ruw linux-6.4/include/linux/if_vlan.h linux-6.4-fbx/include/linux/if_vlan.h
--- linux-6.4/include/linux/if_vlan.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/if_vlan.h	2024-02-21 16:43:28.699803832 +0100
@@ -12,6 +12,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/bug.h>
 #include <uapi/linux/if_vlan.h>
+#include <uapi/linux/pkt_sched.h>
 
 #define VLAN_HLEN	4		/* The additional bytes required by VLAN
 					 * (in addition to the Ethernet header)
@@ -144,6 +145,7 @@
 			 int (*action)(struct net_device *dev, int vid,
 				       void *arg), void *arg);
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
+extern struct net_device *vlan_dev_upper_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
 
@@ -213,7 +215,7 @@
 
 	mp = vlan_dev_priv(dev)->egress_priority_map[(skprio & 0xF)];
 	while (mp) {
-		if (mp->priority == skprio) {
+		if (mp->priority == (skprio & TC_H_MIN_MASK)) {
 			return mp->vlan_qos; /* This should already be shifted
 					      * to mask correctly with the
 					      * VLAN's TCI */
@@ -257,6 +259,12 @@
 	return NULL;
 }
 
+static inline struct net_device *vlan_dev_upper_dev(const struct net_device *dev)
+{
+	BUG();
+	return NULL;
+}
+
 static inline u16 vlan_dev_vlan_id(const struct net_device *dev)
 {
 	BUG();
@@ -317,6 +325,9 @@
 	switch (ethertype) {
 	case htons(ETH_P_8021Q):
 	case htons(ETH_P_8021AD):
+#ifdef CONFIG_VLAN_FBX
+	case htons(ETH_P_FBXVLAN):
+#endif
 		return true;
 	default:
 		return false;
diff -ruw linux-6.4/include/linux/in.h linux-6.4-fbx/include/linux/in.h
--- linux-6.4/include/linux/in.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/in.h	2020-02-08 00:30:24.268528896 +0100
@@ -30,6 +30,9 @@
 		return 0;
 	case IPPROTO_AH:	/* SPI */
 		return 4;
+	case IPPROTO_IPV6:
+		/* third byte of ipv6 destination address */
+		return 36;
 	default:
 		return -EINVAL;
 	}
diff -ruw linux-6.4/include/linux/miscdevice.h linux-6.4-fbx/include/linux/miscdevice.h
--- linux-6.4/include/linux/miscdevice.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/miscdevice.h	2023-11-29 17:07:13.534994595 +0100
@@ -21,6 +21,7 @@
 #define APOLLO_MOUSE_MINOR	7	/* unused */
 #define PC110PAD_MINOR		9	/* unused */
 /*#define ADB_MOUSE_MINOR	10	FIXME OBSOLETE */
+#define TALDEV_MINOR		74	/* Marvell TAL device */
 #define WATCHDOG_MINOR		130	/* Watchdog timer     */
 #define TEMP_MINOR		131	/* Temperature Sensor */
 #define APM_MINOR_DEV		134
diff -ruw linux-6.4/include/linux/mm_types.h linux-6.4-fbx/include/linux/mm_types.h
--- linux-6.4/include/linux/mm_types.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/mm_types.h	2024-02-21 16:43:28.699803832 +0100
@@ -123,7 +123,7 @@
 			 */
 			unsigned long pp_magic;
 			struct page_pool *pp;
-			unsigned long _pp_mapping_pad;
+			unsigned long pp_recycle_flag;
 			unsigned long dma_addr;
 			union {
 				/**
@@ -398,8 +398,8 @@
  */
 #define STRUCT_PAGE_MAX_SHIFT	(order_base_2(sizeof(struct page)))
 
-#define PAGE_FRAG_CACHE_MAX_SIZE	__ALIGN_MASK(32768, ~PAGE_MASK)
-#define PAGE_FRAG_CACHE_MAX_ORDER	get_order(PAGE_FRAG_CACHE_MAX_SIZE)
+#define PAGE_FRAG_CACHE_MAX_ORDER	CONFIG_PAGE_FRAG_CACHE_ORDER
+#define PAGE_FRAG_CACHE_MAX_SIZE	(4096 << PAGE_FRAG_CACHE_MAX_ORDER)
 
 /*
  * page_private can be used on tail pages.  However, PagePrivate is only
@@ -432,6 +432,7 @@
 	 */
 	unsigned int		pagecnt_bias;
 	bool pfmemalloc;
+	atomic_t pages_allocated;
 };
 
 typedef unsigned long vm_flags_t;
diff -ruw linux-6.4/include/linux/mtd/mtd.h linux-6.4-fbx/include/linux/mtd/mtd.h
--- linux-6.4/include/linux/mtd/mtd.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/mtd/mtd.h	2023-11-29 17:07:13.544994611 +0100
@@ -287,6 +287,13 @@
 	 */
 	unsigned int bitflip_threshold;
 
+	/* NAND related attributes */
+	const char *nand_type;
+	const char *nand_manufacturer;
+	const char *onfi_model;
+	uint8_t onfi_ecc_bits;
+	uint8_t nand_ids[8];
+
 	/* Kernel-only stuff starts here. */
 	const char *name;
 	int index;
diff -ruw linux-6.4/include/linux/mtd/rawnand.h linux-6.4-fbx/include/linux/mtd/rawnand.h
--- linux-6.4/include/linux/mtd/rawnand.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/mtd/rawnand.h	2023-11-29 17:07:13.544994611 +0100
@@ -212,6 +212,9 @@
  */
 #define NAND_NO_BBM_QUIRK	BIT(27)
 
+/* NAND controller does not want RNDOUT commands, even in NAND_ECC_SOFT */
+#define NAND_NO_RNDOUT		BIT(28)
+
 /* Cell info constants */
 #define NAND_CI_CHIPNR_MSK	0x03
 #define NAND_CI_CELLTYPE_MSK	0x0C
diff -ruw linux-6.4/include/linux/netdevice.h linux-6.4-fbx/include/linux/netdevice.h
--- linux-6.4/include/linux/netdevice.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/netdevice.h	2023-11-29 17:07:13.548327949 +0100
@@ -78,6 +78,20 @@
 struct xdp_buff;
 struct xdp_md;
 
+#ifdef CONFIG_NETRXTHREAD
+
+#define RXTHREAD_MAX_PKTS       512
+struct krxd {
+	struct sk_buff_head	pkt_queue;
+	unsigned int		stats_pkts;
+	unsigned int		stats_dropped;
+	wait_queue_head_t	wq;
+	struct task_struct	*task;
+};
+
+extern struct krxd gkrxd[CONFIG_NETRXTHREAD_RX_QUEUE];
+#endif
+
 void synchronize_net(void);
 void netdev_set_default_ethtool_ops(struct net_device *dev,
 				    const struct ethtool_ops *ops);
@@ -1743,6 +1757,8 @@
 	IFF_NO_ADDRCONF			= BIT_ULL(30),
 	IFF_TX_SKB_NO_LINEAR		= BIT_ULL(31),
 	IFF_CHANGE_PROTO_DOWN		= BIT_ULL(32),
+	IFF_FBXBRIDGE			= BIT_ULL(33),
+	IFF_FBXBRIDGE_PORT		= BIT_ULL(34),
 };
 
 #define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
@@ -1776,6 +1792,8 @@
 #define IFF_FAILOVER_SLAVE		IFF_FAILOVER_SLAVE
 #define IFF_L3MDEV_RX_HANDLER		IFF_L3MDEV_RX_HANDLER
 #define IFF_TX_SKB_NO_LINEAR		IFF_TX_SKB_NO_LINEAR
+#define IFF_FBXBRIDGE			IFF_FBXBRIDGE
+#define IFF_FBXBRIDGE_PORT		IFF_FBXBRIDGE_PORT
 
 /* Specifies the type of the struct net_device::ml_priv pointer */
 enum netdev_ml_priv_type {
@@ -4827,13 +4845,6 @@
 int skb_csum_hwoffload_help(struct sk_buff *skb,
 			    const netdev_features_t features);
 
-struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
-				  netdev_features_t features, bool tx_path);
-struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features, __be16 type);
-struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features);
-
 struct netdev_bonding_info {
 	ifslave	slave;
 	ifbond	master;
@@ -4856,11 +4867,6 @@
 }
 #endif
 
-static inline
-struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
-{
-	return __skb_gso_segment(skb, features, true);
-}
 __be16 skb_network_protocol(struct sk_buff *skb, int *depth);
 
 static inline bool can_checksum_protocol(netdev_features_t features,
@@ -4987,6 +4993,7 @@
 					  struct net_device *dev,
 					  netdev_features_t features);
 netdev_features_t netif_skb_features(struct sk_buff *skb);
+void skb_warn_bad_offload(const struct sk_buff *skb);
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
@@ -5035,19 +5042,6 @@
 void netif_inherit_tso_max(struct net_device *to,
 			   const struct net_device *from);
 
-static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
-					int pulled_hlen, u16 mac_offset,
-					int mac_len)
-{
-	skb->protocol = protocol;
-	skb->encapsulation = 1;
-	skb_push(skb, pulled_hlen);
-	skb_reset_transport_header(skb);
-	skb->mac_header = mac_offset;
-	skb->network_header = skb->mac_header + mac_len;
-	skb->mac_len = mac_len;
-}
-
 static inline bool netif_is_macsec(const struct net_device *dev)
 {
 	return dev->priv_flags & IFF_MACSEC;
@@ -5103,6 +5097,16 @@
 	return dev->priv_flags & IFF_BRIDGE_PORT;
 }
 
+static inline bool netif_is_fbxbridge_master(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_FBXBRIDGE;
+}
+
+static inline bool netif_is_fbxbridge_port(const struct net_device *dev)
+{
+	return dev->priv_flags & IFF_FBXBRIDGE_PORT;
+}
+
 static inline bool netif_is_ovs_master(const struct net_device *dev)
 {
 	return dev->priv_flags & IFF_OPENVSWITCH;
diff -ruw linux-6.4/include/linux/netfilter/nf_conntrack_tcp.h linux-6.4-fbx/include/linux/netfilter/nf_conntrack_tcp.h
--- linux-6.4/include/linux/netfilter/nf_conntrack_tcp.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/netfilter/nf_conntrack_tcp.h	2020-02-08 00:30:24.356529751 +0100
@@ -28,6 +28,7 @@
 	/* For SYN packets while we may be out-of-sync */
 	u_int8_t	last_wscale;	/* Last window scaling factor seen */
 	u_int8_t	last_flags;	/* Last flags set */
+	u_int32_t	no_window_track;
 };
 
 #endif /* _NF_CONNTRACK_TCP_H */
diff -ruw linux-6.4/include/linux/of_fdt.h linux-6.4-fbx/include/linux/of_fdt.h
--- linux-6.4/include/linux/of_fdt.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/of_fdt.h	2023-11-29 17:07:13.558327965 +0100
@@ -83,6 +83,7 @@
 extern void unflatten_and_copy_device_tree(void);
 extern void early_init_devtree(void *);
 extern void early_get_first_memblock_info(void *, phys_addr_t *);
+const void *of_fdt_find_compatible_dtb(const char *name);
 #else /* CONFIG_OF_EARLY_FLATTREE */
 static inline void early_init_dt_check_for_usable_mem_range(void) {}
 static inline int early_init_dt_scan_chosen_stdout(void) { return -ENODEV; }
diff -ruw linux-6.4/include/linux/page_owner.h linux-6.4-fbx/include/linux/page_owner.h
--- linux-6.4/include/linux/page_owner.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/page_owner.h	2023-11-29 17:07:13.558327965 +0100
@@ -12,6 +12,9 @@
 extern void __set_page_owner(struct page *page,
 			unsigned short order, gfp_t gfp_mask);
 extern void __split_page_owner(struct page *page, unsigned int nr);
+extern void __set_page_owner_frag_cache(struct page *page,
+					unsigned int order,
+					struct page_frag_cache *nc);
 extern void __folio_copy_owner(struct folio *newfolio, struct folio *old);
 extern void __set_page_owner_migrate_reason(struct page *page, int reason);
 extern void __dump_page_owner(const struct page *page);
@@ -36,6 +39,13 @@
 	if (static_branch_unlikely(&page_owner_inited))
 		__split_page_owner(page, nr);
 }
+static inline void set_page_owner_frag_cache(struct page *page,
+					     unsigned int order,
+					     struct page_frag_cache *nc)
+{
+	if (static_branch_unlikely(&page_owner_inited))
+		__set_page_owner_frag_cache(page, order, nc);
+}
 static inline void folio_copy_owner(struct folio *newfolio, struct folio *old)
 {
 	if (static_branch_unlikely(&page_owner_inited))
@@ -59,6 +69,11 @@
 			unsigned int order, gfp_t gfp_mask)
 {
 }
+static inline void set_page_owner_frag_cache(struct page *page,
+					     unsigned int order,
+					     struct page_frag_cache *nc)
+{
+}
 static inline void split_page_owner(struct page *page,
 			unsigned short order)
 {
diff -ruw linux-6.4/include/linux/part_stat.h linux-6.4-fbx/include/linux/part_stat.h
--- linux-6.4/include/linux/part_stat.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/part_stat.h	2023-11-29 17:07:13.561661303 +0100
@@ -12,6 +12,7 @@
 	unsigned long merges[NR_STAT_GROUPS];
 	unsigned long io_ticks;
 	local_t in_flight[2];
+	unsigned long io_errors[2];
 };
 
 /*
diff -ruw linux-6.4/include/linux/pci.h linux-6.4-fbx/include/linux/pci.h
--- linux-6.4/include/linux/pci.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/pci.h	2023-11-29 17:07:13.561661303 +0100
@@ -464,12 +464,14 @@
 	unsigned int	no_vf_scan:1;		/* Don't scan for VFs after IOV enablement */
 	unsigned int	no_command_memory:1;	/* No PCI_COMMAND_MEMORY */
 	unsigned int	rom_bar_overlap:1;	/* ROM BAR disable broken */
+	unsigned int	sysfs_init_done:1;	/* res_attr has been created */
 	pci_dev_flags_t dev_flags;
 	atomic_t	enable_cnt;	/* pci_enable_device has been called */
 
 	u32		saved_config_space[16]; /* Config space saved at suspend time */
 	struct hlist_head saved_cap_space;
 	int		rom_attr_enabled;	/* Display of ROM attribute enabled? */
+	struct mutex	sysfs_init_lock;	/* res_attr has been created */
 	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
 	struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
 
diff -ruw linux-6.4/include/linux/pci_ids.h linux-6.4-fbx/include/linux/pci_ids.h
--- linux-6.4/include/linux/pci_ids.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/pci_ids.h	2023-11-29 17:07:13.561661303 +0100
@@ -1828,6 +1828,7 @@
 #define PCI_DEVICE_ID_PERICOM_PI7C9X7952	0x7952
 #define PCI_DEVICE_ID_PERICOM_PI7C9X7954	0x7954
 #define PCI_DEVICE_ID_PERICOM_PI7C9X7958	0x7958
+#define PCI_DEVICE_ID_PI7C9X20303SL		0xa303
 
 #define PCI_SUBVENDOR_ID_CHASE_PCIFAST		0x12E0
 #define PCI_SUBDEVICE_ID_CHASE_PCIFAST4		0x0031
diff -ruw linux-6.4/include/linux/phy.h linux-6.4-fbx/include/linux/phy.h
--- linux-6.4/include/linux/phy.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/phy.h	2023-11-29 17:07:13.568327980 +0100
@@ -110,6 +110,7 @@
  * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface
  * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax
  * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII
+ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII
  * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII
  * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX
  * @PHY_INTERFACE_MODE_1000BASEX: 1000 BaseX
@@ -123,6 +124,7 @@
  * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN
  * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII
  * @PHY_INTERFACE_MODE_1000BASEKX: 1000Base-KX - with Clause 73 AN
+ * @PHY_INTERFACE_MODE_10G_QXGMII: USXGMII-M 10G / 4 ports
  * @PHY_INTERFACE_MODE_MAX: Book keeping
  *
  * Describes the interface between the MAC and PHY.
@@ -147,6 +149,7 @@
 	PHY_INTERFACE_MODE_XLGMII,
 	PHY_INTERFACE_MODE_MOCA,
 	PHY_INTERFACE_MODE_QSGMII,
+	PHY_INTERFACE_MODE_PSGMII,
 	PHY_INTERFACE_MODE_TRGMII,
 	PHY_INTERFACE_MODE_100BASEX,
 	PHY_INTERFACE_MODE_1000BASEX,
@@ -162,6 +165,15 @@
 	PHY_INTERFACE_MODE_10GKR,
 	PHY_INTERFACE_MODE_QUSGMII,
 	PHY_INTERFACE_MODE_1000BASEKX,
+	PHY_INTERFACE_MODE_10G_QXGMII,
+
+	PHY_INTERFACE_MODE_1000BASEPX_D,
+	PHY_INTERFACE_MODE_1000BASEPX_U,
+	PHY_INTERFACE_MODE_10000BASEPR_D,
+	PHY_INTERFACE_MODE_10000BASEPR_U,
+	PHY_INTERFACE_MODE_10000_1000_BASEPRX_D,
+	PHY_INTERFACE_MODE_10000_1000_BASEPRX_U,
+
 	PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
@@ -255,6 +267,8 @@
 		return "moca";
 	case PHY_INTERFACE_MODE_QSGMII:
 		return "qsgmii";
+	case PHY_INTERFACE_MODE_PSGMII:
+		return "psgmii";
 	case PHY_INTERFACE_MODE_TRGMII:
 		return "trgmii";
 	case PHY_INTERFACE_MODE_1000BASEX:
@@ -281,6 +295,20 @@
 		return "100base-x";
 	case PHY_INTERFACE_MODE_QUSGMII:
 		return "qusgmii";
+	case PHY_INTERFACE_MODE_10G_QXGMII:
+		return "10g-qxgmii";
+	case PHY_INTERFACE_MODE_1000BASEPX_D:
+		return "1000base-px-d";
+	case PHY_INTERFACE_MODE_1000BASEPX_U:
+		return "1000base-px-u";
+	case PHY_INTERFACE_MODE_10000BASEPR_D:
+		return "10000base-pr-d";
+	case PHY_INTERFACE_MODE_10000BASEPR_U:
+		return "10000base-pr-u";
+	case PHY_INTERFACE_MODE_10000_1000_BASEPRX_D:
+		return "10000_1000base-prx-d";
+	case PHY_INTERFACE_MODE_10000_1000_BASEPRX_U:
+		return "10000_1000base-prx-u";
 	default:
 		return "unknown";
 	}
@@ -420,7 +448,11 @@
 	/** @reset_post_delay_us: GPIO reset deassert delay in microseconds */
 	int reset_post_delay_us;
 	/** @reset_gpiod: Reset GPIO descriptor pointer */
-	struct gpio_desc *reset_gpiod;
+	struct gpio_descs *reset_gpiod;
+
+	/* mark non-present phy as present but broken during
+	 * probing */
+	bool keep_broken_phy;
 
 	/** @shared_lock: protect access to the shared element */
 	struct mutex shared_lock;
@@ -1814,6 +1846,7 @@
 
 /* Generic C45 PHY driver */
 extern struct phy_driver genphy_c45_driver;
+extern struct phy_driver genphy_broken_c45_driver;
 
 /* The gen10g_* functions are the old Clause 45 stub */
 int gen10g_config_aneg(struct phy_device *phydev);
diff -ruw linux-6.4/include/linux/phylink.h linux-6.4-fbx/include/linux/phylink.h
--- linux-6.4/include/linux/phylink.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/phylink.h	2023-11-29 17:07:13.568327980 +0100
@@ -584,6 +584,7 @@
 void phylink_mac_change(struct phylink *, bool up);
 
 void phylink_start(struct phylink *);
+void phylink_start_silent(struct phylink *);
 void phylink_stop(struct phylink *);
 
 void phylink_suspend(struct phylink *pl, bool mac_wol);
@@ -660,4 +661,12 @@
 
 void phylink_decode_usxgmii_word(struct phylink_link_state *state,
 				 uint16_t lpa);
+int phylink_set_interface(struct phylink *pl,
+			  phy_interface_t interface,
+			  bool an_enabled);
+void phylink_get_interface(struct phylink *pl,
+			   phy_interface_t *interface,
+			   int *an_en,
+			   int *mode);
+
 #endif
diff -ruw linux-6.4/include/linux/ppp_channel.h linux-6.4-fbx/include/linux/ppp_channel.h
--- linux-6.4/include/linux/ppp_channel.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/ppp_channel.h	2023-11-29 17:07:13.578327996 +0100
@@ -50,6 +50,9 @@
 /* Called by the channel when it can send some more data. */
 extern void ppp_output_wakeup(struct ppp_channel *);
 
+/* Called by the channel when it want to prevent further transmit on it */
+extern void ppp_output_stop(struct ppp_channel *);
+
 /* Called by the channel to process a received PPP packet.
    The packet should have just the 2-byte PPP protocol header. */
 extern void ppp_input(struct ppp_channel *, struct sk_buff *);
diff -ruw linux-6.4/include/linux/pstore.h linux-6.4-fbx/include/linux/pstore.h
--- linux-6.4/include/linux/pstore.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/pstore.h	2023-11-29 17:07:13.581661334 +0100
@@ -67,6 +67,7 @@
  * @reason:	kdump reason for notification
  * @part:	position in a multipart record
  * @compressed:	whether the buffer is compressed
+ * @old:        reflects underlying prz old_zone.
  *
  */
 struct pstore_record {
@@ -83,6 +84,7 @@
 	enum kmsg_dump_reason	reason;
 	unsigned int		part;
 	bool			compressed;
+	bool			old;
 };
 
 /**
diff -ruw linux-6.4/include/linux/pstore_ram.h linux-6.4-fbx/include/linux/pstore_ram.h
--- linux-6.4/include/linux/pstore_ram.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/pstore_ram.h	2023-11-29 17:07:13.581661334 +0100
@@ -29,6 +29,7 @@
 struct ramoops_platform_data {
 	unsigned long	mem_size;
 	phys_addr_t	mem_address;
+	void		*mem_ptr;
 	unsigned int	mem_type;
 	unsigned long	record_size;
 	unsigned long	console_size;
diff -ruw linux-6.4/include/linux/regmap.h linux-6.4-fbx/include/linux/regmap.h
--- linux-6.4/include/linux/regmap.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/regmap.h	2023-11-29 17:07:13.588328011 +0100
@@ -1704,6 +1704,7 @@
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
 struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);
 
+void __iomem *regmap_get_mmio_base_address(struct regmap *map);
 #else
 
 /*
diff -ruw linux-6.4/include/linux/sched.h linux-6.4-fbx/include/linux/sched.h
--- linux-6.4/include/linux/sched.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/sched.h	2023-11-29 17:07:13.594994688 +0100
@@ -736,6 +736,12 @@
 #endif
 };
 
+enum task_exec_mode {
+	EXEC_MODE_DENIED,
+	EXEC_MODE_ONCE,
+	EXEC_MODE_UNLIMITED,
+};
+
 struct task_struct {
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 	/*
@@ -762,6 +768,7 @@
 	/* Per task flags (PF_*), defined further below: */
 	unsigned int			flags;
 	unsigned int			ptrace;
+	enum task_exec_mode		exec_mode;
 
 #ifdef CONFIG_SMP
 	int				on_cpu;
diff -ruw linux-6.4/include/linux/sfp.h linux-6.4-fbx/include/linux/sfp.h
--- linux-6.4/include/linux/sfp.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/sfp.h	2023-11-29 17:07:13.601661365 +0100
@@ -554,6 +554,7 @@
 int sfp_get_module_eeprom_by_page(struct sfp_bus *bus,
 				  const struct ethtool_module_eeprom *page,
 				  struct netlink_ext_ack *extack);
+int sfp_get_sfp_state(struct sfp_bus *bus, struct ethtool_sfp_state *st);
 void sfp_upstream_start(struct sfp_bus *bus);
 void sfp_upstream_stop(struct sfp_bus *bus);
 void sfp_bus_put(struct sfp_bus *bus);
@@ -606,6 +607,12 @@
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int sfp_get_sfp_state(struct sfp_bus *the_bus,
+				    struct ethtool_sfp_state *st)
+{
+	return -EOPNOTSUPP;
+}
 
 static inline void sfp_upstream_start(struct sfp_bus *bus)
 {
diff -ruw linux-6.4/include/linux/skbuff.h linux-6.4-fbx/include/linux/skbuff.h
--- linux-6.4/include/linux/skbuff.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/skbuff.h	2024-02-21 16:43:28.699803832 +0100
@@ -687,6 +687,13 @@
 typedef unsigned char *sk_buff_data_t;
 #endif
 
+enum {
+	FFN_STATE_INIT = 0,
+	FFN_STATE_FORWARDABLE,
+	FFN_STATE_FAST_FORWARDED,
+	FFN_STATE_INCOMPATIBLE,
+};
+
 /**
  * DOC: Basic sk_buff geometry
  *
@@ -893,11 +900,22 @@
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	unsigned long		 _nfct;
 #endif
+
+#if defined(CONFIG_IP_FFN) || defined(CONFIG_IPV6_FFN)
+	int			ffn_state;
+	int			ffn_orig_tos;
+	__u16			ffn_ff_done,
+				ffn_ff_dirty_len;
+#endif
 	unsigned int		len,
 				data_len;
 	__u16			mac_len,
 				hdr_len;
 
+#ifdef CONFIG_NETRXTHREAD
+	int			rxthread_prio;
+#endif
+
 	/* Following fields are _not_ copied in __copy_skb_header()
 	 * Note that queue_mapping is here mostly to fill a hole.
 	 */
@@ -3035,6 +3053,10 @@
  * get_rps_cpu() for example only access one 64 bytes aligned block :
  * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
  */
+#ifdef CONFIG_NETSKBPAD
+#define NET_SKB_PAD	CONFIG_NETSKBPAD
+#endif
+
 #ifndef NET_SKB_PAD
 #define NET_SKB_PAD	max(32, L1_CACHE_BYTES)
 #endif
@@ -3163,6 +3185,10 @@
 
 void *__netdev_alloc_frag_align(unsigned int fragsz, unsigned int align_mask);
 
+struct page_frag_cache *netdev_frag_cache_get(unsigned int cpu_id);
+struct page_frag_cache *napi_frag_cache_get(unsigned int cpu_id);
+
+
 /**
  * netdev_alloc_frag - allocate a page fragment
  * @fragsz: fragment size
@@ -3992,8 +4018,6 @@
 void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
 int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
-bool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu);
-bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len);
 struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);
 struct sk_buff *skb_segment_list(struct sk_buff *skb, netdev_features_t features,
 				 unsigned int offset);
@@ -4859,75 +4883,6 @@
 #endif
 }
 
-/* Keeps track of mac header offset relative to skb->head.
- * It is useful for TSO of Tunneling protocol. e.g. GRE.
- * For non-tunnel skb it points to skb_mac_header() and for
- * tunnel skb it points to outer mac header.
- * Keeps track of level of encapsulation of network headers.
- */
-struct skb_gso_cb {
-	union {
-		int	mac_offset;
-		int	data_offset;
-	};
-	int	encap_level;
-	__wsum	csum;
-	__u16	csum_start;
-};
-#define SKB_GSO_CB_OFFSET	32
-#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_GSO_CB_OFFSET))
-
-static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
-{
-	return (skb_mac_header(inner_skb) - inner_skb->head) -
-		SKB_GSO_CB(inner_skb)->mac_offset;
-}
-
-static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
-{
-	int new_headroom, headroom;
-	int ret;
-
-	headroom = skb_headroom(skb);
-	ret = pskb_expand_head(skb, extra, 0, GFP_ATOMIC);
-	if (ret)
-		return ret;
-
-	new_headroom = skb_headroom(skb);
-	SKB_GSO_CB(skb)->mac_offset += (new_headroom - headroom);
-	return 0;
-}
-
-static inline void gso_reset_checksum(struct sk_buff *skb, __wsum res)
-{
-	/* Do not update partial checksums if remote checksum is enabled. */
-	if (skb->remcsum_offload)
-		return;
-
-	SKB_GSO_CB(skb)->csum = res;
-	SKB_GSO_CB(skb)->csum_start = skb_checksum_start(skb) - skb->head;
-}
-
-/* Compute the checksum for a gso segment. First compute the checksum value
- * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and
- * then add in skb->csum (checksum from csum_start to end of packet).
- * skb->csum and csum_start are then updated to reflect the checksum of the
- * resultant packet starting from the transport header-- the resultant checksum
- * is in the res argument (i.e. normally zero or ~ of checksum of a pseudo
- * header.
- */
-static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res)
-{
-	unsigned char *csum_start = skb_transport_header(skb);
-	int plen = (skb->head + SKB_GSO_CB(skb)->csum_start) - csum_start;
-	__wsum partial = SKB_GSO_CB(skb)->csum;
-
-	SKB_GSO_CB(skb)->csum = res;
-	SKB_GSO_CB(skb)->csum_start = csum_start - skb->head;
-
-	return csum_fold(csum_partial(csum_start, plen, partial));
-}
-
 static inline bool skb_is_gso(const struct sk_buff *skb)
 {
 	return skb_shinfo(skb)->gso_size;
diff -ruw linux-6.4/include/linux/tcp.h linux-6.4-fbx/include/linux/tcp.h
--- linux-6.4/include/linux/tcp.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/tcp.h	2023-11-29 17:07:13.618328058 +0100
@@ -255,7 +255,8 @@
 	u8	compressed_ack;
 	u8	dup_ack_counter:2,
 		tlp_retrans:1,	/* TLP is a retransmission */
-		unused:5;
+		linear_rto:1,
+		unused:4;
 	u32	chrono_start;	/* Start time in jiffies of a TCP chrono */
 	u32	chrono_stat[3];	/* Time in jiffies for chrono_stat stats */
 	u8	chrono_type:2,	/* current chronograph type */
diff -ruw linux-6.4/include/linux/thermal.h linux-6.4-fbx/include/linux/thermal.h
--- linux-6.4/include/linux/thermal.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/thermal.h	2023-11-29 17:07:13.618328058 +0100
@@ -326,6 +326,9 @@
 
 struct thermal_cooling_device *thermal_cooling_device_register(const char *,
 		void *, const struct thermal_cooling_device_ops *);
+struct thermal_cooling_device *thermal_cooling_device_register_with_parent(
+		struct device *pdev, const char *, void *,
+		const struct thermal_cooling_device_ops *);
 struct thermal_cooling_device *
 thermal_of_cooling_device_register(struct device_node *np, const char *, void *,
 				   const struct thermal_cooling_device_ops *);
diff -ruw linux-6.4/include/linux/vmalloc.h linux-6.4-fbx/include/linux/vmalloc.h
--- linux-6.4/include/linux/vmalloc.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/linux/vmalloc.h	2023-11-29 17:07:13.634994750 +0100
@@ -145,6 +145,8 @@
 extern void *vmalloc_32(unsigned long size) __alloc_size(1);
 extern void *vmalloc_32_user(unsigned long size) __alloc_size(1);
 extern void *__vmalloc(unsigned long size, gfp_t gfp_mask) __alloc_size(1);
+extern void *__vmalloc_pgprot(unsigned long size, gfp_t gfp_mask,
+			      pgprot_t prot) __alloc_size(1);
 extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
 			unsigned long start, unsigned long end, gfp_t gfp_mask,
 			pgprot_t prot, unsigned long vm_flags, int node,
diff -ruw linux-6.4/include/media/dvb-usb-ids.h linux-6.4-fbx/include/media/dvb-usb-ids.h
--- linux-6.4/include/media/dvb-usb-ids.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/media/dvb-usb-ids.h	2023-11-29 17:07:13.641661428 +0100
@@ -167,6 +167,7 @@
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 		0x2131
 #define USB_PID_DIBCOM_HOOK_DEFAULT			0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM		0x0065
+#define USB_PID_DIBCOM_HOOK_DEFAULT_STK7770P		0x0066
 #define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
 #define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
 #define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
diff -ruw linux-6.4/include/net/cfg80211.h linux-6.4-fbx/include/net/cfg80211.h
--- linux-6.4/include/net/cfg80211.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/cfg80211.h	2024-02-21 16:43:28.703137206 +0100
@@ -7,7 +7,7 @@
  * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014 Intel Mobile Communications GmbH
  * Copyright 2015-2017	Intel Deutschland GmbH
- * Copyright (C) 2018-2021 Intel Corporation
+ * Copyright (C) 2018-2021, 2023 Intel Corporation
  */
 
 #include <linux/ethtool.h>
@@ -76,6 +76,8 @@
  * @IEEE80211_CHAN_DISABLED: This channel is disabled.
  * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes
  *	sending probe requests or beaconing.
+ * @IEEE80211_CHAN_PSD: Power spectral density (in dBm) is set for this
+ *	channel.
  * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
  * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
  *	is not permitted.
@@ -119,7 +121,7 @@
 enum ieee80211_channel_flags {
 	IEEE80211_CHAN_DISABLED		= 1<<0,
 	IEEE80211_CHAN_NO_IR		= 1<<1,
-	/* hole at 1<<2 */
+	IEEE80211_CHAN_PSD		= 1<<2,
 	IEEE80211_CHAN_RADAR		= 1<<3,
 	IEEE80211_CHAN_NO_HT40PLUS	= 1<<4,
 	IEEE80211_CHAN_NO_HT40MINUS	= 1<<5,
@@ -144,6 +146,7 @@
 	(IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
 
 #define IEEE80211_DFS_MIN_CAC_TIME_MS		60000
+#define IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS	600000
 #define IEEE80211_DFS_MIN_NOP_TIME_MS		(30 * 60 * 1000)
 
 /**
@@ -171,6 +174,7 @@
  *	on this channel.
  * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
  * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
+ * @psd: power spectral density (in dBm)
  */
 struct ieee80211_channel {
 	enum nl80211_band band;
@@ -187,6 +191,7 @@
 	enum nl80211_dfs_state dfs_state;
 	unsigned long dfs_state_entered;
 	unsigned int dfs_cac_ms;
+	s8 psd;
 };
 
 /**
@@ -263,7 +268,7 @@
  * are only for driver use when pointers to this structure are
  * passed around.
  *
- * @flags: rate-specific flags
+ * @flags: rate-specific flags from &enum ieee80211_rate_flags
  * @bitrate: bitrate in units of 100 Kbps
  * @hw_value: driver/hardware value for this rate
  * @hw_value_short: driver/hardware value for this rate when
@@ -309,6 +314,9 @@
 	u8 color;
 	bool enabled;
 	bool partial;
+
+	/* help compiling QCA code, no API to set it, value is always true */
+	bool collision_detection_enabled;
 };
 
 /**
@@ -562,6 +570,9 @@
 	if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
 		return NULL;
 
+	if (iftype == NL80211_IFTYPE_AP_VLAN)
+		iftype = NL80211_IFTYPE_AP;
+
 	for (i = 0; i < sband->n_iftype_data; i++)  {
 		const struct ieee80211_sband_iftype_data *data =
 			&sband->iftype_data[i];
@@ -752,6 +763,10 @@
 	u32 center_freq2;
 	struct ieee80211_edmg edmg;
 	u16 freq1_offset;
+
+	/*  help compiling QCA code, no API to set it, initialized to 0 */
+	u16 ru_punct_bitmap;
+	bool ru_punct_bitmap_supp_he;
 };
 
 /*
@@ -766,6 +781,13 @@
 		enum nl80211_txrate_gi gi;
 		enum nl80211_he_gi he_gi;
 		enum nl80211_he_ltf he_ltf;
+		/* help compiling QCA code, no API to set it, value is
+		 * always 0 */
+		u16 he_ul_mcs[NL80211_HE_NSS_MAX];
+
+		/* help compiling QCA code, no API to set it, initialized
+		 * according to station capabilities */
+		u16 eht_mcs[NL80211_EHT_NSS_MAX];
 	} control[NUM_NL80211_BANDS];
 };
 
@@ -808,7 +830,7 @@
 struct cfg80211_tid_config {
 	const u8 *peer;
 	u32 n_tid_conf;
-	struct cfg80211_tid_cfg tid_conf[];
+	struct cfg80211_tid_cfg tid_conf[] __counted_by(n_tid_conf);
 };
 
 /**
@@ -951,6 +973,30 @@
 				  enum nl80211_iftype iftype);
 
 /**
+ * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable and we
+ *				 can/need start CAC on such channel
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ *
+ * Return: true if all channels available and at least
+ *	   one channel requires CAC (NL80211_DFS_USABLE)
+ */
+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
+				 const struct cfg80211_chan_def *chandef);
+
+/**
+ * cfg80211_chandef_dfs_cac_time - get the DFS CAC time (in ms) for given
+ *				   channel definition
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ *
+ * Returns: DFS CAC time (in ms) which applies for this channel definition
+ */
+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+			      const struct cfg80211_chan_def *chandef);
+
+/**
  * nl80211_send_chandef - sends the channel definition.
  * @msg: the msg to send channel definition
  * @chandef: the channel definition to check
@@ -1184,7 +1230,7 @@
 	struct {
 		const u8 *data;
 		size_t len;
-	} elem[];
+	} elem[] __counted_by(cnt);
 };
 
 /**
@@ -1201,7 +1247,7 @@
 	struct {
 		const u8 *data;
 		size_t len;
-	} elem[];
+	} elem[] __counted_by(cnt);
 };
 
 /**
@@ -1279,13 +1325,14 @@
 	int n_acl_entries;
 
 	/* Keep it last */
-	struct mac_address mac_addrs[];
+	struct mac_address mac_addrs[] __counted_by(n_acl_entries);
 };
 
 /**
  * struct cfg80211_fils_discovery - FILS discovery parameters from
  * IEEE Std 802.11ai-2016, Annex C.3 MIB detail.
  *
+ * @update: Set to true if the feature configuration should be updated.
  * @min_interval: Minimum packet interval in TUs (0 - 10000)
  * @max_interval: Maximum packet interval in TUs (0 - 10000)
  * @tmpl_len: Template length
@@ -1293,6 +1340,7 @@
  *	frame headers.
  */
 struct cfg80211_fils_discovery {
+	bool update;
 	u32 min_interval;
 	u32 max_interval;
 	size_t tmpl_len;
@@ -1303,6 +1351,7 @@
  * struct cfg80211_unsol_bcast_probe_resp - Unsolicited broadcast probe
  *	response parameters in 6GHz.
  *
+ * @update: Set to true if the feature configuration should be updated.
  * @interval: Packet interval in TUs. Maximum allowed is 20 TU, as mentioned
  *	in IEEE P802.11ax/D6.0 26.17.2.3.2 - AP behavior for fast passive
  *	scanning
@@ -1310,6 +1359,7 @@
  * @tmpl: Template data for probe response
  */
 struct cfg80211_unsol_bcast_probe_resp {
+	bool update;
 	u32 interval;
 	size_t tmpl_len;
 	const u8 *tmpl;
@@ -1350,7 +1400,7 @@
  * @twt_responder: Enable Target Wait Time
  * @he_required: stations must support HE
  * @sae_h2e_required: stations must support direct H2E technique in SAE
- * @flags: flags, as defined in enum cfg80211_ap_settings_flags
+ * @flags: flags, as defined in &enum nl80211_ap_settings_flags
  * @he_obss_pd: OBSS Packet Detection settings
  * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
  * @fils_discovery: FILS discovery transmission parameters
@@ -1396,6 +1446,22 @@
 	u16 punct_bitmap;
 };
 
+
+/**
+ * struct cfg80211_ap_update - AP configuration update
+ *
+ * Subset of &struct cfg80211_ap_settings, for updating a running AP.
+ *
+ * @beacon: beacon data
+ * @fils_discovery: FILS discovery transmission parameters
+ * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
+ */
+struct cfg80211_ap_update {
+	struct cfg80211_beacon_data beacon;
+	struct cfg80211_fils_discovery fils_discovery;
+	struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
+};
+
 /**
  * struct cfg80211_csa_settings - channel switch settings
  *
@@ -1479,7 +1545,6 @@
  * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
  * @STATION_PARAM_APPLY_CAPABILITY: apply new capability
  * @STATION_PARAM_APPLY_PLINK_STATE: apply new plink state
- * @STATION_PARAM_APPLY_STA_TXPOWER: apply tx power for STA
  *
  * Not all station parameters have in-band "no change" signalling,
  * for those that don't these flags will are used.
@@ -1532,6 +1597,8 @@
  * @he_6ghz_capa: HE 6 GHz Band capabilities of station
  * @eht_capa: EHT capabilities of station
  * @eht_capa_len: the length of the EHT capabilities
+ * @tp_override: Throughput overide value
+ * @tp_overridden: Throughput has been overridden
  */
 struct link_station_parameters {
 	const u8 *mld_mac;
@@ -1550,6 +1617,8 @@
 	const struct ieee80211_he_6ghz_capa *he_6ghz_capa;
 	const struct ieee80211_eht_cap_elem *eht_capa;
 	u8 eht_capa_len;
+	u32 tp_override;
+	bool tp_overridden;
 };
 
 /**
@@ -1702,6 +1771,7 @@
  * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
  * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS
  * @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information
+ * @RATE_INFO_FLAGS_S1G_MCS: MCS field filled with S1G MCS
  */
 enum rate_info_flags {
 	RATE_INFO_FLAGS_MCS			= BIT(0),
@@ -1712,6 +1782,7 @@
 	RATE_INFO_FLAGS_EDMG			= BIT(5),
 	RATE_INFO_FLAGS_EXTENDED_SC_DMG		= BIT(6),
 	RATE_INFO_FLAGS_EHT_MCS			= BIT(7),
+	RATE_INFO_FLAGS_S1G_MCS			= BIT(8),
 };
 
 /**
@@ -1728,6 +1799,11 @@
  * @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
  * @RATE_INFO_BW_320: 320 MHz bandwidth
  * @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation
+ * @RATE_INFO_BW_1: 1 MHz bandwidth
+ * @RATE_INFO_BW_2: 2 MHz bandwidth
+ * @RATE_INFO_BW_4: 4 MHz bandwidth
+ * @RATE_INFO_BW_8: 8 MHz bandwidth
+ * @RATE_INFO_BW_16: 16 MHz bandwidth
  */
 enum rate_info_bw {
 	RATE_INFO_BW_20 = 0,
@@ -1739,6 +1815,11 @@
 	RATE_INFO_BW_HE_RU,
 	RATE_INFO_BW_320,
 	RATE_INFO_BW_EHT_RU,
+	RATE_INFO_BW_1,
+	RATE_INFO_BW_2,
+	RATE_INFO_BW_4,
+	RATE_INFO_BW_8,
+	RATE_INFO_BW_16,
 };
 
 /**
@@ -1747,8 +1828,8 @@
  * Information about a receiving or transmitting bitrate
  *
  * @flags: bitflag of flags from &enum rate_info_flags
- * @mcs: mcs index if struct describes an HT/VHT/HE rate
  * @legacy: bitrate in 100kbit/s for 802.11abg
+ * @mcs: mcs index if struct describes an HT/VHT/HE/EHT/S1G rate
  * @nss: number of streams (VHT & HE only)
  * @bw: bandwidth (from &enum rate_info_bw)
  * @he_gi: HE guard interval (from &enum nl80211_he_gi)
@@ -1761,9 +1842,9 @@
  *	only valid if bw is %RATE_INFO_BW_EHT_RU)
  */
 struct rate_info {
-	u8 flags;
-	u8 mcs;
+	u16 flags;
 	u16 legacy;
+	u8 mcs;
 	u8 nss;
 	u8 bw;
 	u8 he_gi;
@@ -2141,7 +2222,7 @@
  * @sn: target sequence number
  * @metric: metric (cost) of this mesh path
  * @exptime: expiration time for the mesh path from now, in msecs
- * @flags: mesh path flags
+ * @flags: mesh path flags from &enum mesh_path_flags
  * @discovery_timeout: total mesh path discovery timeout, in msecs
  * @discovery_retries: mesh path discovery retries
  * @generation: generation number for nl80211 dumps.
@@ -2166,6 +2247,15 @@
 	int generation;
 };
 
+#define MPLINK_DUMP_MAX_BLOCKED_ENTRIES	216 /* 216/6 = 36 entries */
+/**
+ * struct mplink_blocked_info - mesh peer link blocked info
+ */
+struct mplink_blocked_info {
+	u8 count;
+	u8 info[MPLINK_DUMP_MAX_BLOCKED_ENTRIES];
+};
+
 /**
  * struct bss_parameters - BSS parameters
  *
@@ -2332,7 +2422,7 @@
  * @user_mpm: userspace handles all MPM functions
  * @dtim_period: DTIM period to use
  * @beacon_interval: beacon interval to use
- * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
+ * @mcast_rate: multicast rate for Mesh Node [6Mbps is the default for 802.11a]
  * @basic_rates: basic rates to use when creating the mesh
  * @beacon_rate: bitrate to be used for beacons
  * @userspace_handles_dfs: whether user space controls DFS operation, i.e.
@@ -2366,6 +2456,17 @@
 };
 
 /**
+ * struct mesh_setup - 802.11s mesh setup configuration
+ * @ie: vendor information elements
+ * @ie_len: length of vendor information elements
+ * These parameters are updated peroidically after mesh creation.
+ */
+struct mesh_vendor_ie {
+	const u8 *ie;
+	u8 ie_len;
+};
+
+/**
  * struct ocb_setup - 802.11p OCB mode setup configuration
  * @chandef: defines the channel to use
  *
@@ -2454,6 +2555,7 @@
  * @short_ssid_valid: @short_ssid is valid and can be used
  * @psc_no_listen: when set, and the channel is a PSC channel, no need to wait
  *       20 TUs before starting to send probe requests.
+ * @psd_20: The AP's 20 MHz PSD value.
  */
 struct cfg80211_scan_6ghz_params {
 	u32 short_ssid;
@@ -2462,6 +2564,7 @@
 	bool unsolicited_probe;
 	bool short_ssid_valid;
 	bool psc_no_listen;
+	s8 psd_20;
 };
 
 /**
@@ -2471,7 +2574,6 @@
  * @n_ssids: number of SSIDs
  * @channels: channels to scan on.
  * @n_channels: total number of channels to scan
- * @scan_width: channel width for scanning
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
  * @duration: how long to listen on each channel, in TUs. If
@@ -2479,7 +2581,7 @@
  *	the actual dwell time may be shorter.
  * @duration_mandatory: if set, the scan duration must be as specified by the
  *	%duration field.
- * @flags: bit field of flags controlling operation
+ * @flags: control flags from &enum nl80211_scan_flags
  * @rates: bitmap of rates to advertise for each band
  * @wiphy: the wiphy this was for
  * @scan_start: time (in jiffies) when the scan started
@@ -2501,7 +2603,6 @@
 	struct cfg80211_ssid *ssids;
 	int n_ssids;
 	u32 n_channels;
-	enum nl80211_bss_scan_width scan_width;
 	const u8 *ie;
 	size_t ie_len;
 	u16 duration;
@@ -2527,7 +2628,7 @@
 	struct cfg80211_scan_6ghz_params *scan_6ghz_params;
 
 	/* keep last */
-	struct ieee80211_channel *channels[];
+	struct ieee80211_channel *channels[] __counted_by(n_channels);
 };
 
 static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask)
@@ -2550,7 +2651,7 @@
  *	or no match (RSSI only)
  * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
  * @per_band_rssi_thold: Minimum rssi threshold for each band to be applied
- *	for filtering out scan results received. Drivers advertize this support
+ *	for filtering out scan results received. Drivers advertise this support
  *	of band specific rssi based filtering through the feature capability
  *	%NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD. These band
  *	specific rssi thresholds take precedence over rssi_thold, if specified.
@@ -2596,14 +2697,13 @@
  * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
  * @n_ssids: number of SSIDs
  * @n_channels: total number of channels to scan
- * @scan_width: channel width for scanning
  * @ie: optional information element(s) to add into Probe Request or %NULL
  * @ie_len: length of ie in octets
- * @flags: bit field of flags controlling operation
+ * @flags: control flags from &enum nl80211_scan_flags
  * @match_sets: sets of parameters to be matched for a scan result
  *	entry to be considered valid and to be passed to the host
  *	(others are filtered out).
- *	If ommited, all results are passed.
+ *	If omitted, all results are passed.
  * @n_match_sets: number of match sets
  * @report_results: indicates that results were reported for this request
  * @wiphy: the wiphy this was for
@@ -2637,14 +2737,13 @@
  *	to the specified band while deciding whether a better BSS is reported
  *	using @relative_rssi. If delta is a negative number, the BSSs that
  *	belong to the specified band will be penalized by delta dB in relative
- *	comparisions.
+ *	comparisons.
  */
 struct cfg80211_sched_scan_request {
 	u64 reqid;
 	struct cfg80211_ssid *ssids;
 	int n_ssids;
 	u32 n_channels;
-	enum nl80211_bss_scan_width scan_width;
 	const u8 *ie;
 	size_t ie_len;
 	u32 flags;
@@ -2692,7 +2791,6 @@
 /**
  * struct cfg80211_inform_bss - BSS inform data
  * @chan: channel the frame was received on
- * @scan_width: scan width that was used
  * @signal: signal strength value, according to the wiphy's
  *	signal type
  * @boottime_ns: timestamp (CLOCK_BOOTTIME) when the information was
@@ -2708,16 +2806,18 @@
  *	the BSS that requested the scan in which the beacon/probe was received.
  * @chains: bitmask for filled values in @chain_signal.
  * @chain_signal: per-chain signal strength of last received BSS in dBm.
+ * @drv_data: Data to be passed through to @inform_bss
  */
 struct cfg80211_inform_bss {
 	struct ieee80211_channel *chan;
-	enum nl80211_bss_scan_width scan_width;
 	s32 signal;
 	u64 boottime_ns;
 	u64 parent_tsf;
 	u8 parent_bssid[ETH_ALEN] __aligned(2);
 	u8 chains;
 	s8 chain_signal[IEEE80211_MAX_CHAINS];
+
+	void *drv_data;
 };
 
 /**
@@ -2743,7 +2843,6 @@
  * for use in scan results and similar.
  *
  * @channel: channel this BSS is on
- * @scan_width: width of the control channel
  * @bssid: BSSID of the BSS
  * @beacon_interval: the beacon interval as from the frame
  * @capability: the capability field in host byte order
@@ -2773,7 +2872,6 @@
  */
 struct cfg80211_bss {
 	struct ieee80211_channel *channel;
-	enum nl80211_bss_scan_width scan_width;
 
 	const struct cfg80211_bss_ies __rcu *ies;
 	const struct cfg80211_bss_ies __rcu *beacon_ies;
@@ -2870,11 +2968,17 @@
  *	if this is %NULL for a link, that link is not requested
  * @elems: extra elements for the per-STA profile for this link
  * @elems_len: length of the elements
+ * @disabled: If set this link should be included during association etc. but it
+ *	should not be used until enabled by the AP MLD.
+ * @error: per-link error code, must be <= 0. If there is an error, then the
+ *	operation as a whole must fail.
  */
 struct cfg80211_assoc_link {
 	struct cfg80211_bss *bss;
 	const u8 *elems;
 	size_t elems_len;
+	bool disabled;
+	int error;
 };
 
 /**
@@ -3473,7 +3577,7 @@
  * This structure provides information needed to transmit a mgmt frame
  *
  * @chan: channel to use
- * @offchan: indicates wether off channel operation is required
+ * @offchan: indicates whether off channel operation is required
  * @wait: duration for ROC
  * @buf: buffer to transmit
  * @len: buffer length
@@ -3591,7 +3695,7 @@
  * @publish_bcast: if true, the solicited publish should be broadcasted
  * @subscribe_active: if true, the subscribe is active
  * @followup_id: the instance ID for follow up
- * @followup_reqid: the requestor instance ID for follow up
+ * @followup_reqid: the requester instance ID for follow up
  * @followup_dest: MAC address of the recipient of the follow up
  * @ttl: time to live counter in DW.
  * @serv_spec_info: Service Specific Info
@@ -3925,7 +4029,7 @@
 
 	struct list_head list;
 
-	struct cfg80211_pmsr_request_peer peers[];
+	struct cfg80211_pmsr_request_peer peers[] __counted_by(n_peers);
 };
 
 /**
@@ -4086,6 +4190,13 @@
  *
  * @change_bss: Modify parameters for a given BSS.
  *
+ * @inform_bss: Called by cfg80211 while being informed about new BSS data
+ *	for every BSS found within the reported data or frame. This is called
+ *	from within the cfg8011 inform_bss handlers while holding the bss_lock.
+ *	The data parameter is passed through from drv_data inside
+ *	struct cfg80211_inform_bss.
+ *	The new IE data for the BSS is explicitly passed.
+ *
  * @set_txq_params: Set TX queue parameters
  *
  * @libertas_set_mesh_channel: Only for backward compatibility for libertas,
@@ -4421,7 +4532,7 @@
 	int	(*start_ap)(struct wiphy *wiphy, struct net_device *dev,
 			    struct cfg80211_ap_settings *settings);
 	int	(*change_beacon)(struct wiphy *wiphy, struct net_device *dev,
-				 struct cfg80211_beacon_data *info);
+				 struct cfg80211_ap_update *info);
 	int	(*stop_ap)(struct wiphy *wiphy, struct net_device *dev,
 			   unsigned int link_id);
 
@@ -4473,6 +4584,9 @@
 	int	(*change_bss)(struct wiphy *wiphy, struct net_device *dev,
 			      struct bss_parameters *params);
 
+	void	(*inform_bss)(struct wiphy *wiphy, struct cfg80211_bss *bss,
+			      const struct cfg80211_bss_ies *ies, void *data);
+
 	int	(*set_txq_params)(struct wiphy *wiphy, struct net_device *dev,
 				  struct ieee80211_txq_params *params);
 
@@ -4592,9 +4706,10 @@
 				  struct cfg80211_gtk_rekey_data *data);
 
 	int	(*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
-			     const u8 *peer, u8 action_code,  u8 dialog_token,
-			     u16 status_code, u32 peer_capability,
-			     bool initiator, const u8 *buf, size_t len);
+			     const u8 *peer, int link_id,
+			     u8 action_code, u8 dialog_token, u16 status_code,
+			     u32 peer_capability, bool initiator,
+			     const u8 *buf, size_t len);
 	int	(*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
 			     const u8 *peer, enum nl80211_tdls_operation oper);
 
@@ -4783,6 +4898,8 @@
  * @WIPHY_FLAG_SUPPORTS_EXT_KCK_32: The device supports 32-byte KCK keys.
  * @WIPHY_FLAG_NOTIFY_REGDOM_BY_DRIVER: The device could handle reg notify for
  *	NL80211_REGDOM_SET_BY_DRIVER.
+ * @WIPHY_FLAG_CHANNEL_CHANGE_ON_BEACON: reg_call_notifier() is called if driver
+ *	set this flag to update channels on beacon hints.
  */
 enum wiphy_flags {
 	WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK		= BIT(0),
@@ -4809,6 +4926,7 @@
 	WIPHY_FLAG_SUPPORTS_5_10_MHZ		= BIT(22),
 	WIPHY_FLAG_HAS_CHANNEL_SWITCH		= BIT(23),
 	WIPHY_FLAG_NOTIFY_REGDOM_BY_DRIVER	= BIT(24),
+	WIPHY_FLAG_CHANNEL_CHANGE_ON_BEACON     = BIT(25),
 };
 
 /**
@@ -5410,6 +5528,8 @@
 	u8 perm_addr[ETH_ALEN];
 	u8 addr_mask[ETH_ALEN];
 
+	int dev_port;
+
 	struct mac_address *addresses;
 
 	const struct ieee80211_txrx_stypes *mgmt_stypes;
@@ -5724,12 +5844,17 @@
  * wiphy_lock - lock the wiphy
  * @wiphy: the wiphy to lock
  *
- * This is mostly exposed so it can be done around registering and
- * unregistering netdevs that aren't created through cfg80211 calls,
- * since that requires locking in cfg80211 when the notifiers is
- * called, but that cannot differentiate which way it's called.
+ * This is needed around registering and unregistering netdevs that
+ * aren't created through cfg80211 calls, since that requires locking
+ * in cfg80211 when the notifiers is called, but that cannot
+ * differentiate which way it's called.
+ *
+ * It can also be used by drivers for their own purposes.
  *
  * When cfg80211 ops are called, the wiphy is already locked.
+ *
+ * Note that this makes sure that no workers that have been queued
+ * with wiphy_queue_work() are running.
  */
 static inline void wiphy_lock(struct wiphy *wiphy)
 	__acquires(&wiphy->mtx)
@@ -5749,6 +5874,109 @@
 	mutex_unlock(&wiphy->mtx);
 }
 
+struct wiphy_work;
+typedef void (*wiphy_work_func_t)(struct wiphy *, struct wiphy_work *);
+
+struct wiphy_work {
+	struct list_head entry;
+	wiphy_work_func_t func;
+};
+
+static inline void wiphy_work_init(struct wiphy_work *work,
+				   wiphy_work_func_t func)
+{
+	INIT_LIST_HEAD(&work->entry);
+	work->func = func;
+}
+
+/**
+ * wiphy_work_queue - queue work for the wiphy
+ * @wiphy: the wiphy to queue for
+ * @work: the work item
+ *
+ * This is useful for work that must be done asynchronously, and work
+ * queued here has the special property that the wiphy mutex will be
+ * held as if wiphy_lock() was called, and that it cannot be running
+ * after wiphy_lock() was called. Therefore, wiphy_cancel_work() can
+ * use just cancel_work() instead of cancel_work_sync(), it requires
+ * being in a section protected by wiphy_lock().
+ */
+void wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *work);
+
+/**
+ * wiphy_work_cancel - cancel previously queued work
+ * @wiphy: the wiphy, for debug purposes
+ * @work: the work to cancel
+ *
+ * Cancel the work *without* waiting for it, this assumes being
+ * called under the wiphy mutex acquired by wiphy_lock().
+ */
+void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work);
+
+/**
+ * wiphy_work_flush - flush previously queued work
+ * @wiphy: the wiphy, for debug purposes
+ * @work: the work to flush, this can be %NULL to flush all work
+ *
+ * Flush the work (i.e. run it if pending). This must be called
+ * under the wiphy mutex acquired by wiphy_lock().
+ */
+void wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *work);
+
+struct wiphy_delayed_work {
+	struct wiphy_work work;
+	struct wiphy *wiphy;
+	struct timer_list timer;
+};
+
+void wiphy_delayed_work_timer(struct timer_list *t);
+
+static inline void wiphy_delayed_work_init(struct wiphy_delayed_work *dwork,
+					   wiphy_work_func_t func)
+{
+	timer_setup(&dwork->timer, wiphy_delayed_work_timer, 0);
+	wiphy_work_init(&dwork->work, func);
+}
+
+/**
+ * wiphy_delayed_work_queue - queue delayed work for the wiphy
+ * @wiphy: the wiphy to queue for
+ * @dwork: the delayable worker
+ * @delay: number of jiffies to wait before queueing
+ *
+ * This is useful for work that must be done asynchronously, and work
+ * queued here has the special property that the wiphy mutex will be
+ * held as if wiphy_lock() was called, and that it cannot be running
+ * after wiphy_lock() was called. Therefore, wiphy_cancel_work() can
+ * use just cancel_work() instead of cancel_work_sync(), it requires
+ * being in a section protected by wiphy_lock().
+ */
+void wiphy_delayed_work_queue(struct wiphy *wiphy,
+			      struct wiphy_delayed_work *dwork,
+			      unsigned long delay);
+
+/**
+ * wiphy_delayed_work_cancel - cancel previously queued delayed work
+ * @wiphy: the wiphy, for debug purposes
+ * @dwork: the delayed work to cancel
+ *
+ * Cancel the work *without* waiting for it, this assumes being
+ * called under the wiphy mutex acquired by wiphy_lock().
+ */
+void wiphy_delayed_work_cancel(struct wiphy *wiphy,
+			       struct wiphy_delayed_work *dwork);
+
+/**
+ * wiphy_delayed_work_flush - flush previously queued delayed work
+ * @wiphy: the wiphy, for debug purposes
+ * @dwork: the delayed work to flush
+ *
+ * Flush the work (i.e. run it if pending). This must be called
+ * under the wiphy mutex acquired by wiphy_lock().
+ */
+void wiphy_delayed_work_flush(struct wiphy *wiphy,
+			      struct wiphy_delayed_work *dwork);
+
 /**
  * struct wireless_dev - wireless device state
  *
@@ -5797,8 +6025,6 @@
  * @mgmt_registrations: list of registrations for management frames
  * @mgmt_registrations_need_update: mgmt registrations were updated,
  *	need to propagate the update to the driver
- * @mtx: mutex used to lock data in this struct, may be used by drivers
- *	and some API functions require it held
  * @beacon_interval: beacon interval used on this device for transmitting
  *	beacons, 0 when not valid
  * @address: The address for this device, valid only if @netdev is %NULL
@@ -5821,6 +6047,7 @@
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
  * @nl_owner_dead: (private) owner socket went away
+ * @cqm_rssi_work: (private) CQM RSSI reporting work
  * @cqm_config: (private) nl80211 RSSI monitor state
  * @pmsr_list: (private) peer measurement requests
  * @pmsr_lock: (private) peer measurements requests/results lock
@@ -5844,8 +6071,6 @@
 	struct list_head mgmt_registrations;
 	u8 mgmt_registrations_need_update:1;
 
-	struct mutex mtx;
-
 	bool use_4addr, is_running, registered, registering;
 
 	u8 address[ETH_ALEN] __aligned(sizeof(u16));
@@ -5893,7 +6118,8 @@
 	} wext;
 #endif
 
-	struct cfg80211_cqm_config *cqm_config;
+	struct wiphy_work cqm_rssi_work;
+	struct cfg80211_cqm_config __rcu *cqm_config;
 
 	struct list_head pmsr_list;
 	spinlock_t pmsr_lock;
@@ -6135,13 +6361,11 @@
 /**
  * ieee80211_mandatory_rates - get mandatory rates for a given band
  * @sband: the band to look for rates in
- * @scan_width: width of the control channel
  *
  * This function returns a bitmap of the mandatory rates for the given
  * band, bits are set according to the rate position in the bitrates array.
  */
-u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
-			      enum nl80211_bss_scan_width scan_width);
+u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband);
 
 /*
  * Radiotap parsing functions -- for controlled injection support
@@ -6482,7 +6706,7 @@
  * @ies: data consisting of IEs
  * @len: length of data
  *
- * Return: %NULL if the etended element could not be found or if
+ * Return: %NULL if the extended element could not be found or if
  * the element is invalid (claims to be longer than the given
  * data) or if the byte array doesn't match; otherwise return the
  * requested element struct.
@@ -6561,6 +6785,28 @@
 }
 
 /**
+ * cfg80211_defragment_element - Defrag the given element data into a buffer
+ *
+ * @elem: the element to defragment
+ * @ies: elements where @elem is contained
+ * @ieslen: length of @ies
+ * @data: buffer to store element data
+ * @data_len: length of @data
+ * @frag_id: the element ID of fragments
+ *
+ * Return: length of @data, or -EINVAL on error
+ *
+ * Copy out all data from an element that may be fragmented into @data, while
+ * skipping all headers.
+ *
+ * The function uses memmove() internally. It is acceptable to defragment an
+ * element in-place.
+ */
+ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies,
+				    size_t ieslen, u8 *data, size_t data_len,
+				    u8 frag_id);
+
+/**
  * cfg80211_send_layer2_update - send layer 2 update frame
  *
  * @dev: network device
@@ -6607,7 +6853,7 @@
 /**
  * regulatory_set_wiphy_regd - set regdom info for self managed drivers
  * @wiphy: the wireless device we want to process the regulatory domain on
- * @rd: the regulatory domain informatoin to use for this wiphy
+ * @rd: the regulatory domain information to use for this wiphy
  *
  * Set the regulatory domain information for self-managed wiphys, only they
  * may use this function. See %REGULATORY_WIPHY_SELF_MANAGED for more
@@ -6698,7 +6944,7 @@
  * Regulatory self-managed driver can use it to proactively
  *
  * @alpha2: the ISO/IEC 3166 alpha2 wmm rule to be queried.
- * @freq: the freqency(in MHz) to be queried.
+ * @freq: the frequency (in MHz) to be queried.
  * @rule: pointer to store the wmm rule from the regulatory db.
  *
  * Self-managed wireless drivers can use this function to  query
@@ -6781,22 +7027,6 @@
 			       gfp_t gfp);
 
 static inline struct cfg80211_bss * __must_check
-cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
-				struct ieee80211_channel *rx_channel,
-				enum nl80211_bss_scan_width scan_width,
-				struct ieee80211_mgmt *mgmt, size_t len,
-				s32 signal, gfp_t gfp)
-{
-	struct cfg80211_inform_bss data = {
-		.chan = rx_channel,
-		.scan_width = scan_width,
-		.signal = signal,
-	};
-
-	return cfg80211_inform_bss_frame_data(wiphy, &data, mgmt, len, gfp);
-}
-
-static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss_frame(struct wiphy *wiphy,
 			  struct ieee80211_channel *rx_channel,
 			  struct ieee80211_mgmt *mgmt, size_t len,
@@ -6804,7 +7034,6 @@
 {
 	struct cfg80211_inform_bss data = {
 		.chan = rx_channel,
-		.scan_width = NL80211_BSS_CHAN_WIDTH_20,
 		.signal = signal,
 	};
 
@@ -6907,26 +7136,6 @@
 			 gfp_t gfp);
 
 static inline struct cfg80211_bss * __must_check
-cfg80211_inform_bss_width(struct wiphy *wiphy,
-			  struct ieee80211_channel *rx_channel,
-			  enum nl80211_bss_scan_width scan_width,
-			  enum cfg80211_bss_frame_type ftype,
-			  const u8 *bssid, u64 tsf, u16 capability,
-			  u16 beacon_interval, const u8 *ie, size_t ielen,
-			  s32 signal, gfp_t gfp)
-{
-	struct cfg80211_inform_bss data = {
-		.chan = rx_channel,
-		.scan_width = scan_width,
-		.signal = signal,
-	};
-
-	return cfg80211_inform_bss_data(wiphy, &data, ftype, bssid, tsf,
-					capability, beacon_interval, ie, ielen,
-					gfp);
-}
-
-static inline struct cfg80211_bss * __must_check
 cfg80211_inform_bss(struct wiphy *wiphy,
 		    struct ieee80211_channel *rx_channel,
 		    enum cfg80211_bss_frame_type ftype,
@@ -6936,7 +7145,6 @@
 {
 	struct cfg80211_inform_bss data = {
 		.chan = rx_channel,
-		.scan_width = NL80211_BSS_CHAN_WIDTH_20,
 		.signal = signal,
 	};
 
@@ -7021,19 +7229,6 @@
 				    void *data),
 		       void *iter_data);
 
-static inline enum nl80211_bss_scan_width
-cfg80211_chandef_to_scan_width(const struct cfg80211_chan_def *chandef)
-{
-	switch (chandef->width) {
-	case NL80211_CHAN_WIDTH_5:
-		return NL80211_BSS_CHAN_WIDTH_5;
-	case NL80211_CHAN_WIDTH_10:
-		return NL80211_BSS_CHAN_WIDTH_10;
-	default:
-		return NL80211_BSS_CHAN_WIDTH_20;
-	}
-}
-
 /**
  * cfg80211_rx_mlme_mgmt - notification of processed MLME management frame
  * @dev: network device
@@ -7066,7 +7261,7 @@
 void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
 
 /**
- * struct cfg80211_rx_assoc_resp - association response data
+ * struct cfg80211_rx_assoc_resp_data - association response data
  * @bss: the BSS that association was requested with, ownership of the pointer
  *	moves to cfg80211 in the call to cfg80211_rx_assoc_resp()
  * @buf: (Re)Association Response frame (header + body)
@@ -7081,7 +7276,7 @@
  * @links.status: Set this (along with a BSS pointer) for links that
  *	were rejected by the AP.
  */
-struct cfg80211_rx_assoc_resp {
+struct cfg80211_rx_assoc_resp_data {
 	const u8 *buf;
 	size_t len;
 	const u8 *req_ies;
@@ -7089,7 +7284,7 @@
 	int uapsd_queues;
 	const u8 *ap_mld_addr;
 	struct {
-		const u8 *addr;
+		u8 addr[ETH_ALEN] __aligned(2);
 		struct cfg80211_bss *bss;
 		u16 status;
 	} links[IEEE80211_MLD_MAX_NUM_LINKS];
@@ -7098,7 +7293,7 @@
 /**
  * cfg80211_rx_assoc_resp - notification of processed association response
  * @dev: network device
- * @data: association response data, &struct cfg80211_rx_assoc_resp
+ * @data: association response data, &struct cfg80211_rx_assoc_resp_data
  *
  * After being asked to associate via cfg80211_ops::assoc() the driver must
  * call either this function or cfg80211_auth_timeout().
@@ -7106,7 +7301,7 @@
  * This function may sleep. The caller must hold the corresponding wdev's mutex.
  */
 void cfg80211_rx_assoc_resp(struct net_device *dev,
-			    struct cfg80211_rx_assoc_resp *data);
+			    struct cfg80211_rx_assoc_resp_data *data);
 
 /**
  * struct cfg80211_assoc_failure - association failure data
@@ -7825,7 +8020,8 @@
  * cfg80211_port_authorized - notify cfg80211 of successful security association
  *
  * @dev: network device
- * @bssid: the BSSID of the AP
+ * @peer_addr: BSSID of the AP/P2P GO in case of STA/GC or STA/GC MAC address
+ *	in case of AP/P2P GO
  * @td_bitmap: transition disable policy
  * @td_bitmap_len: Length of transition disable policy
  * @gfp: allocation flags
@@ -7836,8 +8032,11 @@
  * should be preceded with a call to cfg80211_connect_result(),
  * cfg80211_connect_done(), cfg80211_connect_bss() or cfg80211_roamed() to
  * indicate the 802.11 association.
+ * This function can also be called by AP/P2P GO driver that supports
+ * authentication offload. In this case the peer_mac passed is that of
+ * associated STA/GC.
  */
-void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid,
+void cfg80211_port_authorized(struct net_device *dev, const u8 *peer_addr,
 			      const u8* td_bitmap, u8 td_bitmap_len, gfp_t gfp);
 
 /**
@@ -7975,7 +8174,7 @@
  * @link_id: the ID of the link the frame was received	on
  * @buf: Management frame (header + body)
  * @len: length of the frame data
- * @flags: flags, as defined in enum nl80211_rxmgmt_flags
+ * @flags: flags, as defined in &enum nl80211_rxmgmt_flags
  * @rx_tstamp: Hardware timestamp of frame RX in nanoseconds
  * @ack_tstamp: Hardware timestamp of ack TX in nanoseconds
  */
@@ -8426,7 +8625,7 @@
  * @link_id: the link ID for MLO, must be 0 for non-MLO
  * @punct_bitmap: the new puncturing bitmap
  *
- * Caller must acquire wdev_lock, therefore must only be called from sleepable
+ * Caller must hold wiphy mutex, therefore must only be called from sleepable
  * driver context!
  */
 void cfg80211_ch_switch_notify(struct net_device *dev,
@@ -8666,6 +8865,18 @@
 }
 
 /**
+ * ieee80211_fragment_element - fragment the last element in skb
+ * @skb: The skbuf that the element was added to
+ * @len_pos: Pointer to length of the element to fragment
+ * @frag_id: The element ID to use for fragments
+ *
+ * This function fragments all data after @len_pos, adding fragmentation
+ * elements with the given ID as appropriate. The SKB will grow in size
+ * accordingly.
+ */
+void ieee80211_fragment_element(struct sk_buff *skb, u8 *len_pos, u8 frag_id);
+
+/**
  * cfg80211_report_wowlan_wakeup - report wakeup from WoWLAN
  * @wdev: the wireless device reporting the wakeup
  * @wakeup: the wakeup report
@@ -8914,9 +9125,9 @@
 
 /**
  * cfg80211_assoc_comeback - notification of association that was
- * temporarly rejected with a comeback
+ * temporarily rejected with a comeback
  * @netdev: network device
- * @ap_addr: AP (MLD) address that rejected the assocation
+ * @ap_addr: AP (MLD) address that rejected the association
  * @timeout: timeout interval value TUs.
  *
  * this function may sleep. the caller must hold the corresponding wdev's mutex.
@@ -9067,4 +9278,17 @@
 bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
 					      const struct cfg80211_chan_def *chandef);
 
+/**
+ * cfg80211_links_removed - Notify about removed STA MLD setup links.
+ * @dev: network device.
+ * @link_mask: BIT mask of removed STA MLD setup link IDs.
+ *
+ * Inform cfg80211 and the userspace about removed STA MLD setup links due to
+ * AP MLD removing the corresponding affiliated APs with Multi-Link
+ * reconfiguration. Note that it's not valid to remove all links, in this
+ * case disconnect instead.
+ * Also note that the wdev mutex must be held.
+ */
+void cfg80211_links_removed(struct net_device *dev, u16 link_mask);
+
 #endif /* __NET_CFG80211_H */
diff -ruw linux-6.4/include/net/dsa.h linux-6.4-fbx/include/net/dsa.h
--- linux-6.4/include/net/dsa.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/dsa.h	2023-11-29 17:07:13.658328120 +0100
@@ -56,6 +56,7 @@
 #define DSA_TAG_PROTO_RTL8_4T_VALUE		25
 #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE		26
 #define DSA_TAG_PROTO_LAN937X_VALUE		27
+#define DSA_TAG_PROTO_BRCM_FBX_VALUE		28
 
 enum dsa_tag_protocol {
 	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
@@ -86,6 +87,7 @@
 	DSA_TAG_PROTO_RTL8_4T		= DSA_TAG_PROTO_RTL8_4T_VALUE,
 	DSA_TAG_PROTO_RZN1_A5PSW	= DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
 	DSA_TAG_PROTO_LAN937X		= DSA_TAG_PROTO_LAN937X_VALUE,
+	DSA_TAG_PROTO_BRCM_FBX		= DSA_TAG_PROTO_BRCM_FBX_VALUE,
 };
 
 struct dsa_switch;
@@ -263,6 +265,8 @@
 		DSA_PORT_TYPE_DSA,
 		DSA_PORT_TYPE_USER,
 	} type;
+	bool			is_def_cpu_port;
+	struct device_node	*force_cpu_dn;
 
 	const char		*name;
 	struct dsa_port		*cpu_dp;
diff -ruw linux-6.4/include/net/gro.h linux-6.4-fbx/include/net/gro.h
--- linux-6.4/include/net/gro.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/gro.h	2023-11-29 17:07:13.661661459 +0100
@@ -446,5 +446,6 @@
 		gro_normal_list(napi);
 }
 
+extern struct list_head offload_base;
 
 #endif /* _NET_IPV6_GRO_H */
diff -ruw linux-6.4/include/net/ip.h linux-6.4-fbx/include/net/ip.h
--- linux-6.4/include/net/ip.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/ip.h	2023-11-29 17:07:13.664994797 +0100
@@ -705,6 +705,20 @@
 #endif
 
 /*
+ *     Functions provided by ip_ffn.c
+ */
+
+enum {
+	IP_FFN_FINISH_OUT,
+	IP_FFN_LOCAL_IN,
+};
+
+extern void ip_ffn_init(void);
+extern int ip_ffn_process(struct sk_buff *skb);
+extern void ip_ffn_add(struct sk_buff *skb, int when);
+extern void ip_ffn_flush_all(void);
+
+/*
  *	Functions provided by ip_forward.c
  */
 
diff -ruw linux-6.4/include/net/ip6_tunnel.h linux-6.4-fbx/include/net/ip6_tunnel.h
--- linux-6.4/include/net/ip6_tunnel.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/ip6_tunnel.h	2023-11-29 17:07:13.664994797 +0100
@@ -18,6 +18,18 @@
 /* determine capability on a per-packet basis */
 #define IP6_TNL_F_CAP_PER_PACKET 0x40000
 
+/* IPv6 tunnel FMR */
+struct __ip6_tnl_fmr {
+	struct __ip6_tnl_fmr *next; /* next fmr in list */
+	struct in6_addr ip6_prefix;
+	struct in_addr ip4_prefix;
+
+	__u8 ip6_prefix_len;
+	__u8 ip4_prefix_len;
+	__u8 ea_len;
+	__u8 offset;
+};
+
 struct __ip6_tnl_parm {
 	char name[IFNAMSIZ];	/* name of tunnel device */
 	int link;		/* ifindex of underlying L2 interface */
@@ -29,6 +41,7 @@
 	__u32 flags;		/* tunnel flags */
 	struct in6_addr laddr;	/* local tunnel end-point address */
 	struct in6_addr raddr;	/* remote tunnel end-point address */
+	struct __ip6_tnl_fmr *fmrs;	/* FMRs */
 
 	__be16			i_flags;
 	__be16			o_flags;
diff -ruw linux-6.4/include/net/ipv6.h linux-6.4-fbx/include/net/ipv6.h
--- linux-6.4/include/net/ipv6.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/ipv6.h	2023-11-29 17:07:13.668328136 +0100
@@ -1147,6 +1147,7 @@
 int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb);
 int ip6_forward(struct sk_buff *skb);
 int ip6_input(struct sk_buff *skb);
+int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
 int ip6_mc_input(struct sk_buff *skb);
 void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
 			      bool have_final);
@@ -1377,4 +1378,18 @@
 	release_sock(sk);
 }
 
+/*
+ *     Functions provided by ipv6_ffn.c
+ */
+
+enum {
+	IPV6_FFN_FINISH_OUT,
+	IPV6_FFN_LOCAL_IN,
+};
+
+extern void ipv6_ffn_init(void);
+extern int ipv6_ffn_process(struct sk_buff *skb);
+extern void ipv6_ffn_add(struct sk_buff *skb, int when);
+extern void ipv6_ffn_flush_all(void);
+
 #endif /* _NET_IPV6_H */
diff -ruw linux-6.4/include/net/netfilter/nf_conntrack.h linux-6.4-fbx/include/net/netfilter/nf_conntrack.h
--- linux-6.4/include/net/netfilter/nf_conntrack.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/netfilter/nf_conntrack.h	2023-11-29 17:07:13.671661474 +0100
@@ -53,6 +53,8 @@
 	/* only used when new connection is allocated: */
 	atomic_t count;
 	unsigned int expect_count;
+	u8 sysctl_auto_assign_helper;
+	bool auto_assign_helper_warned;
 
 	/* only used from work queues, configuration plane, and so on: */
 	unsigned int users4;
@@ -118,6 +120,9 @@
 	u_int32_t secmark;
 #endif
 
+	union nf_conntrack_man_proto	nat_src_proto_min;
+	union nf_conntrack_man_proto	nat_src_proto_max;
+
 	/* Extensions */
 	struct nf_ct_ext *ext;
 
diff -ruw linux-6.4/include/net/netfilter/nf_conntrack_expect.h linux-6.4-fbx/include/net/netfilter/nf_conntrack_expect.h
--- linux-6.4/include/net/netfilter/nf_conntrack_expect.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/netfilter/nf_conntrack_expect.h	2022-08-30 19:20:32.387649147 +0200
@@ -58,13 +58,24 @@
 #endif
 
 	struct rcu_head rcu;
+
+	/* private expect information. */
+	char data[32] __aligned(8);
 };
 
+#define NF_CT_EXPECT_BUILD_BUG_ON(structsize)				\
+	BUILD_BUG_ON((structsize) > sizeof_field(struct nf_conntrack_expect, data))
+
 static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
 {
 	return nf_ct_net(exp->master);
 }
 
+static inline void *nf_ct_exp_data(struct nf_conntrack_expect *exp)
+{
+	return (void *)exp->data;
+}
+
 #define NF_CT_EXP_POLICY_NAME_LEN	16
 
 struct nf_conntrack_expect_policy {
diff -ruw linux-6.4/include/net/netns/conntrack.h linux-6.4-fbx/include/net/netns/conntrack.h
--- linux-6.4/include/net/netns/conntrack.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/netns/conntrack.h	2023-11-29 17:07:13.678328151 +0100
@@ -100,6 +100,7 @@
 	u8			sysctl_log_invalid; /* Log invalid packets */
 	u8			sysctl_events;
 	u8			sysctl_acct;
+	u8			sysctl_auto_assign_helper;
 	u8			sysctl_tstamp;
 	u8			sysctl_checksum;
 
diff -ruw linux-6.4/include/net/page_pool.h linux-6.4-fbx/include/net/page_pool.h
--- linux-6.4/include/net/page_pool.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/page_pool.h	2024-02-21 16:43:28.709803957 +0100
@@ -377,6 +377,21 @@
 		page->dma_addr_upper = upper_32_bits(addr);
 }
 
+static inline void page_pool_clear_recycle_flag(struct page *page)
+{
+	page->pp_recycle_flag= 0;
+}
+
+static inline void page_pool_set_recycled_flag(struct page *page)
+{
+	page->pp_recycle_flag = 1;
+}
+
+static inline bool page_pool_is_recycled(struct page *page)
+{
+	return page->pp_recycle_flag & 1;
+}
+
 static inline bool is_page_pool_compiled_in(void)
 {
 #ifdef CONFIG_PAGE_POOL
diff -ruw linux-6.4/include/net/regulatory.h linux-6.4-fbx/include/net/regulatory.h
--- linux-6.4/include/net/regulatory.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/regulatory.h	2023-11-29 17:07:13.681661490 +0100
@@ -140,17 +140,6 @@
  *      otherwise initiating radiation is not allowed. This will enable the
  *      relaxations enabled under the CFG80211_REG_RELAX_NO_IR configuration
  *      option
- * @REGULATORY_IGNORE_STALE_KICKOFF: the regulatory core will _not_ make sure
- *	all interfaces on this wiphy reside on allowed channels. If this flag
- *	is not set, upon a regdomain change, the interfaces are given a grace
- *	period (currently 60 seconds) to disconnect or move to an allowed
- *	channel. Interfaces on forbidden channels are forcibly disconnected.
- *	Currently these types of interfaces are supported for enforcement:
- *	NL80211_IFTYPE_ADHOC, NL80211_IFTYPE_STATION, NL80211_IFTYPE_AP,
- *	NL80211_IFTYPE_AP_VLAN, NL80211_IFTYPE_MONITOR,
- *	NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO,
- *	NL80211_IFTYPE_P2P_DEVICE. The flag will be set by default if a device
- *	includes any modes unsupported for enforcement checking.
  * @REGULATORY_WIPHY_SELF_MANAGED: for devices that employ wiphy-specific
  *	regdom management. These devices will ignore all regdom changes not
  *	originating from their own wiphy.
@@ -177,7 +166,7 @@
 	REGULATORY_COUNTRY_IE_FOLLOW_POWER	= BIT(3),
 	REGULATORY_COUNTRY_IE_IGNORE		= BIT(4),
 	REGULATORY_ENABLE_RELAX_NO_IR           = BIT(5),
-	REGULATORY_IGNORE_STALE_KICKOFF         = BIT(6),
+	/* reuse bit 6 next time */
 	REGULATORY_WIPHY_SELF_MANAGED		= BIT(7),
 };
 
@@ -224,6 +213,7 @@
 	u32 flags;
 	u32 dfs_cac_ms;
 	bool has_wmm;
+	s8 psd;
 };
 
 struct ieee80211_regdomain {
diff -ruw linux-6.4/include/net/sock.h linux-6.4-fbx/include/net/sock.h
--- linux-6.4/include/net/sock.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/sock.h	2023-11-29 17:07:13.684994828 +0100
@@ -187,6 +187,7 @@
 	unsigned char		skc_reuseport:1;
 	unsigned char		skc_ipv6only:1;
 	unsigned char		skc_net_refcnt:1;
+	unsigned char		skc_reuse_conflict;
 	int			skc_bound_dev_if;
 	union {
 		struct hlist_node	skc_bind_node;
@@ -383,6 +384,7 @@
 #define sk_reuseport		__sk_common.skc_reuseport
 #define sk_ipv6only		__sk_common.skc_ipv6only
 #define sk_net_refcnt		__sk_common.skc_net_refcnt
+#define sk_reuse_conflict	__sk_common.skc_reuse_conflict
 #define sk_bound_dev_if		__sk_common.skc_bound_dev_if
 #define sk_bind_node		__sk_common.skc_bind_node
 #define sk_prot			__sk_common.skc_prot
@@ -959,6 +961,7 @@
 	SOCK_XDP, /* XDP is attached */
 	SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */
 	SOCK_RCVMARK, /* Receive SO_MARK  ancillary data with packet */
+	SOCK_UDP_DUP_UNICAST,
 };
 
 #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
diff -ruw linux-6.4/include/net/udp.h linux-6.4-fbx/include/net/udp.h
--- linux-6.4/include/net/udp.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/net/udp.h	2023-11-29 17:07:13.688328167 +0100
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/bug.h>
 #include <net/inet_sock.h>
+#include <net/gso.h>
 #include <net/sock.h>
 #include <net/snmp.h>
 #include <net/ip.h>
diff -ruw linux-6.4/include/uapi/asm-generic/socket.h linux-6.4-fbx/include/uapi/asm-generic/socket.h
--- linux-6.4/include/uapi/asm-generic/socket.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/asm-generic/socket.h	2023-11-29 17:07:13.728328229 +0100
@@ -30,9 +30,10 @@
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
 #define SO_SNDLOWAT	19
+#endif
+
 #define SO_RCVTIMEO_OLD	20
 #define SO_SNDTIMEO_OLD	21
-#endif
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		22
@@ -132,6 +133,8 @@
 
 #define SO_RCVMARK		75
 
+#define SO_UDP_DUP_UNICAST	100
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
diff -ruw linux-6.4/include/uapi/linux/batadv_packet.h linux-6.4-fbx/include/uapi/linux/batadv_packet.h
--- linux-6.4/include/uapi/linux/batadv_packet.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/batadv_packet.h	2024-01-12 13:49:05.006702363 +0100
@@ -44,6 +44,7 @@
 	BATADV_ELP		= 0x03,
 	BATADV_OGM2		= 0x04,
 	BATADV_MCAST            = 0x05,
+	BATADV_FBX		= 0x3f,
 	/* 0x40 - 0x7f: unicast */
 #define BATADV_UNICAST_MIN     0x40
 	BATADV_UNICAST          = 0x40,
@@ -87,6 +88,14 @@
 };
 
 /**
+ * enum batadv_v_flags - flags used in B.A.T.M.A.N. V OGM2 packets
+ * @BATADV_V_HALF_DUPLEX: Halfduplex penalty should be applied to throughput
+ */
+enum batadv_v_flags {
+	BATADV_V_HALF_DUPLEX   = 1UL << 7,
+};
+
+/**
  * enum batadv_icmp_packettype - ICMP message types
  * @BATADV_ECHO_REPLY: success reply to BATADV_ECHO_REQUEST
  * @BATADV_DESTINATION_UNREACHABLE: failure when route to destination not found
@@ -174,6 +183,7 @@
  * @BATADV_TVLV_TT: translation table tvlv
  * @BATADV_TVLV_ROAM: roaming advertisement tvlv
  * @BATADV_TVLV_MCAST: multicast capability tvlv
+ * @BATADV_TVLV_FBX: fbx specific tvlv
  */
 enum batadv_tvlv_type {
 	BATADV_TVLV_GW		= 0x01,
@@ -182,6 +192,7 @@
 	BATADV_TVLV_TT		= 0x04,
 	BATADV_TVLV_ROAM	= 0x05,
 	BATADV_TVLV_MCAST	= 0x06,
+	BATADV_TVLV_FBX		= 0xff,
 };
 
 #pragma pack(2)
@@ -628,6 +639,61 @@
 	__u8 reserved[3];
 };
 
+/**
+ * struct batadv_fbx_packet - FBX specific packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the general header
+ * @subtype: FBX packet subtype (see batadv_fbx_subtype)
+ * @rev: FBX specific version for compatibility
+ * @seqno: an alway increasing sequence number, not checked for now
+ */
+struct batadv_fbx_packet {
+	__u8   packet_type;
+	__u8   version;
+	__u8   subtype; /* see batadv_fbx_subtype detection message types */
+	__u8   rev;
+	__be32 seqno;
+};
+#define BATADV_FBX_HLEN sizeof(struct batadv_fbx_packet)
+
+/**
+ * enum batadv_fbx_subtype - FBX packet subtypes
+ * @BATADV_FBX_MTU_PROBE: Big message sent to a neigh to probe link MTU
+ * @BATADV_FBX_MTU_RESP: MTU acknowledgment from receiver to sender
+ */
+enum batadv_fbx_subtype {
+	BATADV_FBX_SUB_UNUSED = 0,
+	BATADV_FBX_SUB_MTU_PROBE,
+	BATADV_FBX_SUB_MTU_RESP,
+	BATADV_FBX_SUB_SLAP,
+	/* keep last */
+	BATADV_FBX_SUB_LAST,
+};
+
+/**
+ * struct batadv_fbx_mtu_packet - FBX MTU probing packet
+ * @hdr: Common FBX header
+ * @mtu: The mtu this probe / resp packet relates to
+ */
+struct batadv_fbx_mtu_packet {
+	struct batadv_fbx_packet hdr;
+	__be16 mtu;
+};
+
+#define BATADV_FBX_MTU_HLEN sizeof(struct batadv_fbx_mtu_packet)
+
+/**
+ * struct batadv_fbx_slap_packet - FBX SLAP ID packet
+ * @hdr: Common FBX header
+ * @prio: SLAP Prio of the originator node
+ */
+struct batadv_fbx_slap_packet {
+	struct batadv_fbx_packet hdr;
+	__be32 prio;
+};
+
+#define BATADV_FBX_SLAP_HLEN sizeof(struct batadv_fbx_slap_packet)
+
 #pragma pack()
 
 #endif /* _UAPI_LINUX_BATADV_PACKET_H_ */
diff -ruw linux-6.4/include/uapi/linux/batman_adv.h linux-6.4-fbx/include/uapi/linux/batman_adv.h
--- linux-6.4/include/uapi/linux/batman_adv.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/batman_adv.h	2024-01-12 13:49:05.006702363 +0100
@@ -11,6 +11,7 @@
 
 #define BATADV_NL_MCAST_GROUP_CONFIG	"config"
 #define BATADV_NL_MCAST_GROUP_TPMETER	"tpmeter"
+#define BATADV_NL_MCAST_GROUP_ROUTE	"route"
 
 /**
  * enum batadv_tt_client_flags - TT client specific flags
@@ -49,6 +50,12 @@
 	BATADV_TT_CLIENT_ISOLA	 = (1 << 5),
 
 	/**
+	 * @BATADV_TT_CLIENT_SEEN: this global client has been actually
+	 * detected to be part of the originator and has not yet expired
+	 */
+	BATADV_TT_CLIENT_SEEN = (1 << 6),
+
+	/**
 	 * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from
 	 * the table
 	 */
@@ -481,6 +488,11 @@
 	 */
 	BATADV_ATTR_MULTICAST_FANOUT,
 
+	/**
+	 * @BATADV_ATTF_FBX: defines FBX specific NL attributes
+	 */
+	BATADV_ATTR_FBX,
+
 	/* add attributes above here, update the policy in netlink.c */
 
 	/**
@@ -500,6 +512,52 @@
 };
 
 /**
+ * enum batadv_nl_fbx_attrs - batman-adv netlink attributes
+ */
+enum batadv_nl_fbx_attr {
+	/**
+	 * @BATADV_ATTR_FBX_MTU: defines the MTU this neighbor can safely use.
+	 */
+	BATADV_ATTR_FBX_MTU,
+
+	/**
+	 * @BATADV_ATTR_FBX_SLAP_MASTER_MAC: Show current SLAP master address
+	 */
+	BATADV_ATTR_FBX_SLAP_MASTER_ADDRESS,
+
+	/**
+	 * @BATADV_ATTR_FBX_SLAP_MASTER_PRIO: Show current SLAP master priority
+	 */
+	BATADV_ATTR_FBX_SLAP_MASTER_PRIO,
+
+	/**
+	 * @BATADV_ATTR_FBX_SLAP_IFINDEX: defines the currently selected SLAP
+	 * interface
+	 */
+	BATADV_ATTR_FBX_SLAP_IFINDEX,
+
+	/**
+	 * @BATADV_ATTR_FBX_SLAP_PRIO: defines the current SLAP priority
+	 */
+	BATADV_ATTR_FBX_SLAP_PRIO,
+
+	/**
+	 * @__BATADV_ATTR_FBX_AFTER_LAST: internal use
+	 */
+	__BATADV_ATTR_FBX_AFTER_LAST,
+
+	/**
+	 * @NUM_BATADV_FBX_ATTR: total number of batadv_nl_fbx_attrs available
+	 */
+	NUM_BATADV_ATTR_FBX = __BATADV_ATTR_FBX_AFTER_LAST,
+
+	/**
+	 * @BATADV_ATTR_FBX_MAX: highest attribute number currently defined
+	 */
+	BATADV_ATTR_FBX_MAX = __BATADV_ATTR_FBX_AFTER_LAST - 1
+};
+
+/**
  * enum batadv_nl_commands - supported batman-adv netlink commands
  */
 enum batadv_nl_commands {
@@ -613,6 +671,21 @@
 	 */
 	BATADV_CMD_SET_VLAN,
 
+	/**
+	 * @BATADV_CMD_ADD_ROUTE: Add new route to reach originator
+	 */
+	BATADV_CMD_ADD_ROUTE,
+
+	/**
+	 * @BATADV_CMD_DEL_ROUTE: Del route to originator
+	 */
+	BATADV_CMD_DEL_ROUTE,
+
+	/**
+	 * @BATADV_CMD_CHANGE_ROUTE: Modify an existing route to originator
+	 */
+	BATADV_CMD_CHANGE_ROUTE,
+
 	/* add new commands above here */
 
 	/**
diff -ruw linux-6.4/include/uapi/linux/ethtool.h linux-6.4-fbx/include/uapi/linux/ethtool.h
--- linux-6.4/include/uapi/linux/ethtool.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/ethtool.h	2023-11-29 17:07:13.744994921 +0100
@@ -294,6 +294,8 @@
 	ETHTOOL_PHY_DOWNSHIFT,
 	ETHTOOL_PHY_FAST_LINK_DOWN,
 	ETHTOOL_PHY_EDPD,
+	ETHTOOL_PHY_BROKEN,
+
 	/*
 	 * Add your fresh new phy tunable attribute above and remember to update
 	 * phy_tunable_strings[] in net/ethtool/common.c
@@ -681,6 +683,7 @@
  * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics
  * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics
  * @ETH_SS_STATS_RMON: names of RMON statistics
+ * @ETH_SS_PHYLINK_IFTYPES: names of phylink interface types
  *
  * @ETH_SS_COUNT: number of defined string sets
  */
@@ -706,6 +709,7 @@
 	ETH_SS_STATS_ETH_MAC,
 	ETH_SS_STATS_ETH_CTRL,
 	ETH_SS_STATS_RMON,
+	ETH_SS_PHYLINK_IFTYPES,
 
 	/* add new constants above here */
 	ETH_SS_COUNT
@@ -1576,6 +1580,91 @@
 #define ETHTOOL_FEC_BASER		(1 << ETHTOOL_FEC_BASER_BIT)
 #define ETHTOOL_FEC_LLRS		(1 << ETHTOOL_FEC_LLRS_BIT)
 
+/**
+ * struct ethtool_shaper_params
+ * @cmd: %ETHTOOL_GSHAPER_PARAMS / %ETHTOOL_SSHAPER_PARAMS
+ */
+struct ethtool_shaper_params {
+	__u32 cmd;
+
+	__u64 rate;
+	__u32 burst;
+	__u32 mtu;
+};
+
+/**
+ * struct ethtool_epon_param
+ * @cmd: Command number = %ETHTOOL_GEPON_PARAM or %ETHTOOL_SEPON_*
+ */
+struct ethtool_epon_param {
+	__u32   cmd;
+	__u8	discovery_rx;
+	__u8	registered;
+	__u16	llid;
+	__u32	burst_cap;
+	__u32	lasermon_event_count;
+	__u32	change_count;
+	__u32	keys_update_id;
+	__u8	key_sci[8];
+	__u8	down_key0[16];
+	__u8	down_key1[16];
+	__u32	down_encrypt;
+	__u32	down_last_rx_encrypted;
+	__u32	down_last_rx_key_id;
+	__u16	mcast_llid;
+	__u16	pad;
+};
+
+/*
+ * currently a 1:1 mapping for SFP SM in drivers/net/phy/sfp.c
+ */
+enum {
+	ETHTOOL_SFP_S_DOWN = 0,
+	ETHTOOL_SFP_S_FAIL,
+	ETHTOOL_SFP_S_WAIT,
+	ETHTOOL_SFP_S_INIT,
+	ETHTOOL_SFP_S_INIT_PHY,
+	ETHTOOL_SFP_S_INIT_TX_FAULT,
+	ETHTOOL_SFP_S_WAIT_LOS,
+	ETHTOOL_SFP_S_LINK_UP,
+	ETHTOOL_SFP_S_TX_FAULT,
+	ETHTOOL_SFP_S_REINIT,
+	ETHTOOL_SFP_S_TX_DISABLE,
+};
+
+/**
+ * struct ethtool_sfp_state
+ * @cmd: Command number = %ETHTOOL_GSFP_STATE
+ */
+struct ethtool_sfp_state {
+	__u32 cmd;
+
+	__u32 fsm_state;
+
+	__u8 o_pwren;
+	__u8 o_txdis;
+	__u8 i_presence;
+	__u8 i_rxlos;
+	__u8 i_txfault;
+};
+
+/**
+ * struct ethtool_phylink_if_mode
+ * @cmd: %ETHTOOL_GPHYLINK_IFTYPE / %ETHTOOL_SPHYLINK_IFTYPE
+ */
+struct ethtool_phylink_iftype {
+	__u32	cmd;
+
+	/* stringified phy_interface_t (enum is not part of UAPI and
+	 * is not stable), uses string from phy_modes()  */
+	char	iftype[ETH_GSTRING_LEN];
+
+	__u32	autoneg_en;
+
+	/* enum MLO_AN_xxx, read-only */
+	__u32	mode;
+};
+
 /* CMDs currently supported */
 #define ETHTOOL_GSET		0x00000001 /* DEPRECATED, Get settings.
 					    * Please use ETHTOOL_GLINKSETTINGS
@@ -1671,6 +1760,23 @@
 #define ETHTOOL_GFECPARAM	0x00000050 /* Get FEC settings */
 #define ETHTOOL_SFECPARAM	0x00000051 /* Set FEC settings */
 
+#define ETHTOOL_GEPON_PARAM	0x00000052 /* Get EPON params */
+#define ETHTOOL_SEPON_KEYS	0x00000053 /* Set EPON encryption keys */
+#define ETHTOOL_SEPON_ENCRYPT	0x00000054 /* Set EPON encryption keys */
+#define ETHTOOL_SEPON_RESTART	0x00000055 /* restart epon link */
+#define ETHTOOL_SEPON_BURST	0x00000056 /* update burst value */
+#define ETHTOOL_SEPON_ADD_MCLLID	0x00000057 /* add epon llid */
+#define ETHTOOL_SEPON_DEL_MCLLID	0x00000058 /* remove epon llid */
+#define ETHTOOL_SEPON_CLR_MCLLID	0x00000059 /* remove all epon llid */
+
+#define ETHTOOL_GSFP_STATE	0x00000060 /* get SFP state (IOs/FSM) */
+
+#define ETHTOOL_SSHAPER_PARAMS	0x00000061 /* set HW TX shaper params */
+#define ETHTOOL_GSHAPER_PARAMS	0x00000062 /* get HW TX shaper params */
+
+#define ETHTOOL_GPHYLINK_IFTYPE	0x00000063 /* get phylink interface type  */
+#define ETHTOOL_SPHYLINK_IFTYPE	0x00000064 /* set phylink interface type */
+
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
 #define SPARC_ETH_SSET		ETHTOOL_SSET
@@ -1787,6 +1893,12 @@
 	ETHTOOL_LINK_MODE_10baseT1S_Full_BIT		 = 99,
 	ETHTOOL_LINK_MODE_10baseT1S_Half_BIT		 = 100,
 	ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT	 = 101,
+	ETHTOOL_LINK_MODE_1000basePX_D_Full_BIT		 = 102,
+	ETHTOOL_LINK_MODE_1000basePX_U_Full_BIT		 = 103,
+	ETHTOOL_LINK_MODE_10000basePR_D_Full_BIT	 = 104,
+	ETHTOOL_LINK_MODE_10000basePR_U_Full_BIT	 = 105,
+	ETHTOOL_LINK_MODE_10000_1000basePRX_D_Full_BIT	 = 106,
+	ETHTOOL_LINK_MODE_10000_1000basePRX_U_Full_BIT	 = 107,
 
 	/* must be last entry */
 	__ETHTOOL_LINK_MODE_MASK_NBITS
diff -ruw linux-6.4/include/uapi/linux/if_ether.h linux-6.4-fbx/include/uapi/linux/if_ether.h
--- linux-6.4/include/uapi/linux/if_ether.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/if_ether.h	2024-02-21 16:43:28.709803957 +0100
@@ -55,6 +55,7 @@
 #define	ETH_P_BPQ	0x08FF		/* G8BPQ AX.25 Ethernet Packet	[ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IEEEPUP	0x0a00		/* Xerox IEEE802.3 PUP packet */
 #define ETH_P_IEEEPUPAT	0x0a01		/* Xerox IEEE802.3 PUP Addr Trans packet */
+#define ETH_P_FBXVLAN	0x1337		/* Freebox specific VLAN type [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_BATMAN	0x4305		/* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
 #define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
diff -ruw linux-6.4/include/uapi/linux/if_tun.h linux-6.4-fbx/include/uapi/linux/if_tun.h
--- linux-6.4/include/uapi/linux/if_tun.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/if_tun.h	2023-11-29 17:07:13.751661598 +0100
@@ -62,6 +62,32 @@
 #define TUNSETCARRIER _IOW('T', 226, int)
 #define TUNGETDEVNETNS _IO('T', 227)
 
+
+struct smalltun_rule {
+	__u8	proto;
+	__be16	src_port_start;
+	__be16	src_port_end;
+	__be16	dst_port_start;
+	__be16	dst_port_end;
+};
+
+struct smalltun_fp {
+	__be32	inner_src;
+	__be32	inner_dst;
+
+	__u32	af;
+	__u8	outer_src[16];
+	__u8	outer_dst[16];
+	__be16	outer_src_port;
+	__be16	outer_dst_port;
+
+	struct smalltun_rule rules[8];
+	__u32	rule_count;
+};
+
+#define TUNSMALLTUNSETFP _IOW('T', 228, struct smalltun_fp)
+#define TUNSMALLTUNDELFP _IOW('T', 229, struct smalltun_fp)
+
 /* TUNSETIFF ifr flags */
 #define IFF_TUN		0x0001
 #define IFF_TAP		0x0002
diff -ruw linux-6.4/include/uapi/linux/if_tunnel.h linux-6.4-fbx/include/uapi/linux/if_tunnel.h
--- linux-6.4/include/uapi/linux/if_tunnel.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/if_tunnel.h	2023-11-29 17:07:13.751661598 +0100
@@ -77,10 +77,23 @@
 	IFLA_IPTUN_ENCAP_DPORT,
 	IFLA_IPTUN_COLLECT_METADATA,
 	IFLA_IPTUN_FWMARK,
+	IFLA_IPTUN_FMRS,
 	__IFLA_IPTUN_MAX,
 };
 #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
 
+enum {
+	IFLA_IPTUN_FMR_UNSPEC,
+	IFLA_IPTUN_FMR_IP6_PREFIX,
+	IFLA_IPTUN_FMR_IP4_PREFIX,
+	IFLA_IPTUN_FMR_IP6_PREFIX_LEN,
+	IFLA_IPTUN_FMR_IP4_PREFIX_LEN,
+	IFLA_IPTUN_FMR_EA_LEN,
+	IFLA_IPTUN_FMR_OFFSET,
+	__IFLA_IPTUN_FMR_MAX,
+};
+#define IFLA_IPTUN_FMR_MAX (__IFLA_IPTUN_FMR_MAX - 1)
+
 enum tunnel_encap_types {
 	TUNNEL_ENCAP_NONE,
 	TUNNEL_ENCAP_FOU,
diff -ruw linux-6.4/include/uapi/linux/input-event-codes.h linux-6.4-fbx/include/uapi/linux/input-event-codes.h
--- linux-6.4/include/uapi/linux/input-event-codes.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/input-event-codes.h	2023-11-29 17:07:13.751661598 +0100
@@ -803,6 +803,18 @@
 #define BTN_TRIGGER_HAPPY39		0x2e6
 #define BTN_TRIGGER_HAPPY40		0x2e7
 
+#define KEY_APP_TV			0x2f1
+#define KEY_APP_REPLAY			0x2f2
+#define KEY_APP_VIDEOCLUB		0x2f3
+#define KEY_APP_WHATSON			0x2f4
+#define KEY_APP_RECORDS			0x2f5
+#define KEY_APP_MEDIA			0x2f6
+#define KEY_APP_YOUTUBE			0x2f7
+#define KEY_APP_RADIOS			0x2f8
+#define KEY_APP_CANALVOD		0x2f9
+#define KEY_APP_PIP			0x2fa
+#define KEY_APP_NETFLIX			0x2fb
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING	KEY_MUTE
 #define KEY_MAX			0x2ff
diff -ruw linux-6.4/include/uapi/linux/libc-compat.h linux-6.4-fbx/include/uapi/linux/libc-compat.h
--- linux-6.4/include/uapi/linux/libc-compat.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/libc-compat.h	2020-02-08 00:30:24.660532705 +0100
@@ -49,11 +49,11 @@
 #ifndef _UAPI_LIBC_COMPAT_H
 #define _UAPI_LIBC_COMPAT_H
 
-/* We have included glibc headers... */
-#if defined(__GLIBC__)
+/* We have included libc headers... */
+#if !defined(__KERNEL__)
 
-/* Coordinate with glibc net/if.h header. */
-#if defined(_NET_IF_H) && defined(__USE_MISC)
+/* Coordinate with libc net/if.h header. */
+#if defined(_NET_IF_H) && (!defined(__GLIBC__) || defined(__USE_MISC))
 
 /* GLIBC headers included first so don't define anything
  * that would already be defined. */
@@ -65,9 +65,11 @@
 /* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
 #define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
 /* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#ifndef IFF_ECHO
 #ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
 #define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
 #endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+#endif /* IFF_ECHO */
 
 #else /* _NET_IF_H */
 
@@ -170,7 +172,7 @@
  * or we are being included in the kernel, then define everything
  * that we need. Check for previous __UAPI_* definitions to give
  * unsupported C libraries a way to opt out of any kernel definition. */
-#else /* !defined(__GLIBC__) */
+#else /* !defined(__KERNEL__) */
 
 /* Definitions for if.h */
 #ifndef __UAPI_DEF_IF_IFCONF
@@ -262,6 +264,6 @@
 #define __UAPI_DEF_XATTR		1
 #endif
 
-#endif /* __GLIBC__ */
+#endif /* __KERNEL__ */
 
 #endif /* _UAPI_LIBC_COMPAT_H */
diff -ruw linux-6.4/include/uapi/linux/nl80211.h linux-6.4-fbx/include/uapi/linux/nl80211.h
--- linux-6.4/include/uapi/linux/nl80211.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/nl80211.h	2024-02-21 16:43:28.713137331 +0100
@@ -11,7 +11,7 @@
  * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
  * Copyright 2008 Colin McCabe <colin@cozybit.com>
  * Copyright 2015-2017	Intel Deutschland GmbH
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -167,7 +167,7 @@
  * following events occur.
  * a) Expiration of hardware timer whose expiration time is set to maximum
  * coalescing delay of matching coalesce rule.
- * b) Coalescing buffer in hardware reaches it's limit.
+ * b) Coalescing buffer in hardware reaches its limit.
  * c) Packet doesn't match any of the configured coalesce rules.
  *
  * User needs to configure following parameters for creating a coalesce
@@ -326,7 +326,7 @@
 /**
  * DOC: Multi-Link Operation
  *
- * In Multi-Link Operation, a connection between to MLDs utilizes multiple
+ * In Multi-Link Operation, a connection between two MLDs utilizes multiple
  * links. To use this in nl80211, various commands and responses now need
  * to or will include the new %NL80211_ATTR_MLO_LINKS attribute.
  * Additionally, various commands that need to operate on a specific link
@@ -335,6 +335,15 @@
  */
 
 /**
+ * DOC: OWE DH IE handling offload
+ *
+ * By setting @NL80211_EXT_FEATURE_OWE_OFFLOAD flag, drivers can indicate
+ * kernel/application space to avoid DH IE handling. When this flag is
+ * advertised, the driver/device will take care of DH IE inclusion and
+ * processing of peer DH IE to generate PMK.
+ */
+
+/**
  * enum nl80211_commands - supported nl80211 commands
  *
  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -1309,6 +1318,11 @@
  *	The number of peers that HW timestamping can be enabled for concurrently
  *	is indicated by %NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS.
  *
+ * @NL80211_CMD_LINKS_REMOVED: Notify userspace about the removal of STA MLD
+ *	setup links due to AP MLD removing the corresponding affiliated APs with
+ *	Multi-Link reconfiguration. %NL80211_ATTR_MLO_LINKS is used to provide
+ *	information about the removed STA MLD setup links.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1562,6 +1576,8 @@
 
 	NL80211_CMD_SET_HW_TIMESTAMP,
 
+	NL80211_CMD_LINKS_REMOVED,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -2683,11 +2699,13 @@
  *
  * @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS
  *	discovery. It is a nested attribute, see
- *	&enum nl80211_fils_discovery_attributes.
+ *	&enum nl80211_fils_discovery_attributes. Userspace should pass an empty
+ *	nested attribute to disable this feature and delete the templates.
  *
  * @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure
  *	unsolicited broadcast probe response. It is a nested attribute, see
- *	&enum nl80211_unsol_bcast_probe_resp_attributes.
+ *	&enum nl80211_unsol_bcast_probe_resp_attributes. Userspace should pass an empty
+ *	nested attribute to disable this feature and delete the templates.
  *
  * @NL80211_ATTR_S1G_CAPABILITY: S1G Capability information element (from
  *	association request when used with NL80211_CMD_NEW_STATION)
@@ -2805,6 +2823,9 @@
  *	index. If the userspace includes more RNR elements than number of
  *	MBSSID elements then these will be added in every EMA beacon.
  *
+ * @NL80211_ATTR_MLO_LINK_DISABLED: Flag attribute indicating that the link is
+ *	disabled.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3341,6 +3362,8 @@
 
 	NL80211_ATTR_EMA_RNR_ELEMS,
 
+	NL80211_ATTR_MLO_LINK_DISABLED,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3348,6 +3371,9 @@
 	NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
 };
 
+#define NL80211_QBC_UPDATE_NODE_METRICS_IE 1
+#define NL80211_QBC_UPDATE_PATH_METRICS_IE 2
+
 /* source-level API compatibility */
 #define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
 #define	NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
@@ -3667,6 +3693,13 @@
  *	(u8, see &enum nl80211_eht_gi)
  * @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then
  *	non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc)
+ * @NL80211_RATE_INFO_S1G_MCS: S1G MCS index (u8, 0-10)
+ * @NL80211_RATE_INFO_S1G_NSS: S1G NSS value (u8, 1-4)
+ * @NL80211_RATE_INFO_1_MHZ_WIDTH: 1 MHz S1G rate
+ * @NL80211_RATE_INFO_2_MHZ_WIDTH: 2 MHz S1G rate
+ * @NL80211_RATE_INFO_4_MHZ_WIDTH: 4 MHz S1G rate
+ * @NL80211_RATE_INFO_8_MHZ_WIDTH: 8 MHz S1G rate
+ * @NL80211_RATE_INFO_16_MHZ_WIDTH: 16 MHz S1G rate
  * @__NL80211_RATE_INFO_AFTER_LAST: internal use
  */
 enum nl80211_rate_info {
@@ -3693,6 +3726,13 @@
 	NL80211_RATE_INFO_EHT_NSS,
 	NL80211_RATE_INFO_EHT_GI,
 	NL80211_RATE_INFO_EHT_RU_ALLOC,
+	NL80211_RATE_INFO_S1G_MCS,
+	NL80211_RATE_INFO_S1G_NSS,
+	NL80211_RATE_INFO_1_MHZ_WIDTH,
+	NL80211_RATE_INFO_2_MHZ_WIDTH,
+	NL80211_RATE_INFO_4_MHZ_WIDTH,
+	NL80211_RATE_INFO_8_MHZ_WIDTH,
+	NL80211_RATE_INFO_16_MHZ_WIDTH,
 
 	/* keep last */
 	__NL80211_RATE_INFO_AFTER_LAST,
@@ -4187,6 +4227,8 @@
  *	as the primary or any of the secondary channels isn't possible
  * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel
  *	in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_PSD: Power spectral density (in dBm) that
+ *	is allowed on this channel in current regulatory domain.
  * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
  *	currently defined
  * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -4225,6 +4267,7 @@
 	NL80211_FREQUENCY_ATTR_16MHZ,
 	NL80211_FREQUENCY_ATTR_NO_320MHZ,
 	NL80211_FREQUENCY_ATTR_NO_EHT,
+	NL80211_FREQUENCY_ATTR_PSD,
 
 	/* keep last */
 	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -4325,6 +4368,8 @@
  * 	a given frequency range. The value is in mBm (100 * dBm).
  * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
  *	If not present or 0 default CAC time will be used.
+ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm).
+ *	This could be negative.
  * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
  *	currently defined
  * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -4342,6 +4387,8 @@
 
 	NL80211_ATTR_DFS_CAC_TIME,
 
+	NL80211_ATTR_POWER_RULE_PSD,
+
 	/* keep last */
 	__NL80211_REG_RULE_ATTR_AFTER_LAST,
 	NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
@@ -4424,6 +4471,8 @@
  * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
  * @NL80211_RRF_NO_HE: HE operation not allowed
  * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed
+ * @NL80211_RRF_NO_EHT: EHT operation not allowed
+ * @NL80211_RRF_PSD: Ruleset has power spectral density value
  */
 enum nl80211_reg_rule_flags {
 	NL80211_RRF_NO_OFDM		= 1<<0,
@@ -4443,6 +4492,8 @@
 	NL80211_RRF_NO_160MHZ		= 1<<16,
 	NL80211_RRF_NO_HE		= 1<<17,
 	NL80211_RRF_NO_320MHZ		= 1<<18,
+	NL80211_RRF_NO_EHT		= 1<<19,
+	NL80211_RRF_PSD			= 1<<20,
 };
 
 #define NL80211_RRF_PASSIVE_SCAN	NL80211_RRF_NO_IR
@@ -5010,7 +5061,7 @@
  *	elements from a Beacon frame (bin); not present if no Beacon frame has
  *	yet been received
  * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
- *	(u32, enum nl80211_bss_scan_width)
+ *	(u32, enum nl80211_bss_scan_width) - No longer used!
  * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
  *	(not present if no beacon frame has been received yet)
  * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
@@ -5255,6 +5306,7 @@
 };
 
 #define NL80211_HE_NSS_MAX		8
+#define NL80211_EHT_NSS_MAX             16
 /**
  * struct nl80211_txrate_he - HE MCS/NSS txrate bitmap
  * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
@@ -6372,6 +6424,12 @@
  *	in authentication and deauthentication frames sent to unassociated peer
  *	using @NL80211_CMD_FRAME.
  *
+ * @NL80211_EXT_FEATURE_OWE_OFFLOAD: Driver/Device wants to do OWE DH IE
+ *	handling in station mode.
+ *
+ * @NL80211_EXT_FEATURE_OWE_OFFLOAD_AP: Driver/Device wants to do OWE DH IE
+ *	handling in AP mode.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -6443,6 +6501,8 @@
 	NL80211_EXT_FEATURE_PUNCT,
 	NL80211_EXT_FEATURE_SECURE_NAN,
 	NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA,
+	NL80211_EXT_FEATURE_OWE_OFFLOAD,
+	NL80211_EXT_FEATURE_OWE_OFFLOAD_AP,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
@@ -6567,6 +6627,7 @@
  *	these channels would passively be scanned. Also note that when the flag
  *	is set, in addition to the colocated APs, PSC channels would also be
  *	scanned if the user space has asked for it.
+ * @NL80211_SCAN_FLAG_UPDATE_DFS: scan results will update DFS state
  */
 enum nl80211_scan_flags {
 	NL80211_SCAN_FLAG_LOW_PRIORITY				= 1<<0,
@@ -6584,6 +6645,7 @@
 	NL80211_SCAN_FLAG_MIN_PREQ_CONTENT			= 1<<12,
 	NL80211_SCAN_FLAG_FREQ_KHZ				= 1<<13,
 	NL80211_SCAN_FLAG_COLOCATED_6GHZ			= 1<<14,
+	NL80211_SCAN_FLAG_UPDATE_DFS				= 1<<15,
 };
 
 /**
@@ -7578,7 +7640,7 @@
  * @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU).
  *	Allowed range: 0..10000 (TU = Time Unit)
  * @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU).
- *	Allowed range: 0..10000 (TU = Time Unit)
+ *	Allowed range: 0..10000 (TU = Time Unit). If set to 0, the feature is disabled.
  * @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action
  *	frame including the headers.
  *
@@ -7611,7 +7673,8 @@
  *
  * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU).
  *	Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0
- *	26.17.2.3.2 (AP behavior for fast passive scanning).
+ *	26.17.2.3.2 (AP behavior for fast passive scanning). If set to 0, the feature is
+ *	disabled.
  * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response
  *	frame template (binary).
  *
diff -ruw linux-6.4/include/uapi/linux/serial_core.h linux-6.4-fbx/include/uapi/linux/serial_core.h
--- linux-6.4/include/uapi/linux/serial_core.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/serial_core.h	2023-11-29 17:07:13.771661630 +0100
@@ -279,4 +279,7 @@
 /* Sunplus UART */
 #define PORT_SUNPLUS	123
 
+/* BCM63xx HS */
+#define PORT_BCM63XX_HS	123
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
diff -ruw linux-6.4/include/uapi/linux/sockios.h linux-6.4-fbx/include/uapi/linux/sockios.h
--- linux-6.4/include/uapi/linux/sockios.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/sockios.h	2020-02-08 00:30:24.696533055 +0100
@@ -153,6 +153,14 @@
 #define SIOCSHWTSTAMP	0x89b0		/* set and get config		*/
 #define SIOCGHWTSTAMP	0x89b1		/* get config			*/
 
+/* fbxbridge call */
+#define SIOCGFBXBRIDGE	0x89c0		/* fbxbridge support          */
+#define SIOCSFBXBRIDGE	0x89c1		/* Set fbxbridge options      */
+
+/* fbxdiverter call */
+#define SIOCGFBXDIVERT  0x89d0		/* fbxdiverter support          */
+#define SIOCSFBXDIVERT  0x89d1		/* Set fbxdiverter options      */
+
 /* Device private ioctl calls */
 
 /*
diff -ruw linux-6.4/include/uapi/linux/stddef.h linux-6.4-fbx/include/uapi/linux/stddef.h
--- linux-6.4/include/uapi/linux/stddef.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/stddef.h	2023-11-29 17:07:13.774994968 +0100
@@ -45,3 +45,7 @@
 		TYPE NAME[]; \
 	}
 #endif
+
+#ifndef __counted_by
+#define __counted_by(m)
+#endif
diff -ruw linux-6.4/include/uapi/linux/tcp.h linux-6.4-fbx/include/uapi/linux/tcp.h
--- linux-6.4/include/uapi/linux/tcp.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/tcp.h	2023-11-29 17:07:13.774994968 +0100
@@ -134,6 +134,8 @@
 #define TCP_REPAIR_OFF		0
 #define TCP_REPAIR_OFF_NO_WP	-1	/* Turn off without window probes */
 
+#define TCP_LINEAR_RTO		128	/* force use of linear timeouts */
+
 struct tcp_repair_opt {
 	__u32	opt_code;
 	__u32	opt_val;
diff -ruw linux-6.4/include/uapi/linux/tty.h linux-6.4-fbx/include/uapi/linux/tty.h
--- linux-6.4/include/uapi/linux/tty.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/include/uapi/linux/tty.h	2023-11-29 17:07:13.774994968 +0100
@@ -39,8 +39,9 @@
 #define N_MCTP		28	/* MCTP-over-serial */
 #define N_DEVELOPMENT	29	/* Manual out-of-tree testing */
 #define N_CAN327	30	/* ELM327 based OBD-II interfaces */
+#define N_REMOTI	31	/* RemoTI over UART */
 
 /* Always the newest line discipline + 1 */
-#define NR_LDISCS	31
+#define NR_LDISCS	32
 
 #endif /* _UAPI_LINUX_TTY_H */
diff -ruw linux-6.4/init/Kconfig linux-6.4-fbx/init/Kconfig
--- linux-6.4/init/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/init/Kconfig	2023-11-29 17:07:13.801661676 +0100
@@ -139,6 +139,15 @@
 	  Maximum of each of the number of arguments and environment
 	  variables passed to init from the kernel command line.
 
+
+config CROSS_COMPILE
+	string "Cross-compiler tool prefix"
+	help
+	  Same as running 'make CROSS_COMPILE=prefix-' but stored for
+	  default make runs in this kernel build directory.  You don't
+	  need to set this unless you want the configured kernel build
+	  directory to select the cross-compiler automatically.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on HAS_IOMEM
@@ -779,6 +788,44 @@
 
 	  There is no additional runtime cost to printk with this enabled.
 
+config FBX_DECRYPT_INITRD
+	bool "Decrypt initrd at boot"
+	depends on BLK_DEV_RAM
+	default n
+
+choice
+	prompt "initrd decryption encryption flavor"
+	default FBX_DECRYPT_INITRD_RC4
+
+config FBX_DECRYPT_INITRD_RC4
+	depends on FBX_DECRYPT_INITRD
+	bool "RC4"
+
+config FBX_DECRYPT_INITRD_CHACHA20
+	depends on FBX_DECRYPT_INITRD
+	bool "CHACHA20"
+	select CRYPTO_CHACHA20
+
+endchoice
+
+config FBX_DECRYPT_INITRD_KEY
+	string "Decryption key"
+	depends on FBX_DECRYPT_INITRD
+
+config FBX_DECRYPT_INITRD_NONCE
+	string "Decryption nonce/IV"
+	depends on FBX_DECRYPT_INITRD_CHACHA20
+
+config FBX_VERIFY_INITRD
+	bool "Verify initrd at boot"
+	depends on FBX_DECRYPT_INITRD
+	select CRYPTO_RSA
+	select CRYPTO_SHA256
+
+config FBX_VERIFY_INITRD_PUBKEY
+	string "Public key path for initrd verify"
+	depends on FBX_VERIFY_INITRD
+
 #
 # Architectures with an unreliable sched_clock() should select this:
 #
diff -ruw linux-6.4/init/Makefile linux-6.4-fbx/init/Makefile
--- linux-6.4/init/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/init/Makefile	2023-11-29 17:07:13.801661676 +0100
@@ -15,6 +15,14 @@
 
 obj-y                          += init_task.o
 
+obj-$(CONFIG_FBX_DECRYPT_INITRD)+= fbx_decrypt_initrd.o
+obj-$(CONFIG_FBX_DECRYPT_INITRD_RC4) += rc4.o
+obj-$(CONFIG_FBX_VERIFY_INITRD) += fbx_initrd_pub_key.o
+
+PUB_KEY_PATH_UNQUOTED = $(patsubst "%",%,$(CONFIG_FBX_VERIFY_INITRD_PUBKEY))
+
+init/fbx_initrd_pub_key.o: $(PUB_KEY_PATH_UNQUOTED)
+
 mounts-y			:= do_mounts.o
 mounts-$(CONFIG_BLK_DEV_RAM)	+= do_mounts_rd.o
 mounts-$(CONFIG_BLK_DEV_INITRD)	+= do_mounts_initrd.o
diff -ruw linux-6.4/init/init_task.c linux-6.4-fbx/init/init_task.c
--- linux-6.4/init/init_task.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/init/init_task.c	2023-11-29 17:07:13.804995015 +0100
@@ -75,6 +75,7 @@
 	.stack		= init_stack,
 	.usage		= REFCOUNT_INIT(2),
 	.flags		= PF_KTHREAD,
+	.exec_mode	= EXEC_MODE_UNLIMITED,
 	.prio		= MAX_PRIO - 20,
 	.static_prio	= MAX_PRIO - 20,
 	.normal_prio	= MAX_PRIO - 20,
diff -ruw linux-6.4/init/initramfs.c linux-6.4-fbx/init/initramfs.c
--- linux-6.4/init/initramfs.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/init/initramfs.c	2023-11-29 17:07:13.804995015 +0100
@@ -18,6 +18,7 @@
 #include <linux/init_syscalls.h>
 #include <linux/task_work.h>
 #include <linux/umh.h>
+#include <linux/printk.h>
 
 static __initdata bool csum_present;
 static __initdata u32 io_csum;
@@ -668,6 +669,10 @@
 	ssize_t written;
 	struct file *file;
 	loff_t pos = 0;
+#ifdef CONFIG_FBX_DECRYPT_INITRD
+	int ret;
+	extern int fbx_decrypt_initrd(char *start, u32 size);
+#endif
 
 	unpack_to_rootfs(__initramfs_start, __initramfs_size);
 
@@ -677,6 +682,15 @@
 	if (IS_ERR(file))
 		return;
 
+#ifdef CONFIG_FBX_DECRYPT_INITRD
+	ret = fbx_decrypt_initrd((char*)initrd_start,
+				 initrd_end - initrd_start);
+	if (ret) {
+		printk(KERN_ERR "Decrypt failed: %i\n", ret);
+		return;
+	}
+#endif
+
 	written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start,
 			&pos);
 	if (written != initrd_end - initrd_start)
diff -ruw linux-6.4/kernel/fork.c linux-6.4-fbx/kernel/fork.c
--- linux-6.4/kernel/fork.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/kernel/fork.c	2023-11-29 17:07:13.848328415 +0100
@@ -1195,6 +1195,11 @@
 	tsk->mm_cid_active = 0;
 	tsk->migrate_from_cpu = -1;
 #endif
+	/*
+	 * inherit parent exec_mode.
+	 */
+	tsk->exec_mode = orig->exec_mode;
+
 	return tsk;
 
 free_stack:
diff -ruw linux-6.4/kernel/module/Kconfig linux-6.4-fbx/kernel/module/Kconfig
--- linux-6.4/kernel/module/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/kernel/module/Kconfig	2023-11-29 17:07:13.868328446 +0100
@@ -385,6 +385,10 @@
 	  one per line. The path can be absolute, or relative to the kernel
 	  source tree.
 
+config UNUSED_KSYMS_WHITELIST_SYMS
+	string "Whitelist of symbols name to keep in ksymtab"
+	depends on TRIM_UNUSED_KSYMS
+
 config MODULES_TREE_LOOKUP
 	def_bool y
 	depends on PERF_EVENTS || TRACING || CFI_CLANG
diff -ruw linux-6.4/kernel/sys.c linux-6.4-fbx/kernel/sys.c
--- linux-6.4/kernel/sys.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/kernel/sys.c	2023-11-29 17:07:13.904995170 +0100
@@ -12,6 +12,7 @@
 #include <linux/mman.h>
 #include <linux/reboot.h>
 #include <linux/prctl.h>
+#include <linux/prctl-private.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
 #include <linux/kmod.h>
@@ -2708,6 +2709,18 @@
 		error = !!test_bit(MMF_VM_MERGE_ANY, &me->mm->flags);
 		break;
 #endif
+	case PR_SET_EXEC_MODE:
+		if (arg2 != EXEC_MODE_UNLIMITED &&
+		    arg2 != EXEC_MODE_ONCE &&
+		    arg2 != EXEC_MODE_DENIED)
+			return -EINVAL;
+
+		if (arg2 > current->exec_mode)
+			return -EPERM;
+		current->exec_mode = arg2;
+		return 0;
+	case PR_GET_EXEC_MODE:
+		return current->exec_mode;
 	default:
 		error = -EINVAL;
 		break;
diff -ruw linux-6.4/lib/Kconfig linux-6.4-fbx/lib/Kconfig
--- linux-6.4/lib/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/lib/Kconfig	2023-11-29 17:07:13.938328555 +0100
@@ -728,6 +728,13 @@
 config OBJAGG
 	tristate "objagg" if COMPILE_TEST
 
+config ARCH_HAS_FBXSERIAL
+	bool
+
+config FBXSERIAL
+	bool "fbxserial"
+	select CRC32
+
 endmenu
 
 config GENERIC_IOREMAP
diff -ruw linux-6.4/lib/Makefile linux-6.4-fbx/lib/Makefile
--- linux-6.4/lib/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/lib/Makefile	2023-11-29 17:07:13.941661894 +0100
@@ -430,3 +430,4 @@
 ifeq ($(CONFIG_FORTIFY_SOURCE),y)
 $(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG)
 endif
+obj-$(CONFIG_FBXSERIAL) += fbxserial.o
diff -ruw linux-6.4/mm/Kconfig linux-6.4-fbx/mm/Kconfig
--- linux-6.4/mm/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/mm/Kconfig	2023-11-29 17:07:13.991661971 +0100
@@ -709,6 +709,13 @@
 config ARCH_SUPPORTS_MEMORY_FAILURE
 	bool
 
+config PAGE_FRAG_CACHE_ORDER
+	int "page order size of page fragment allocator"
+	default 3
+	help
+	  This allocator is used by networking only for skb->head allocation.
+	  A large value speeds up allocation but causes memory fragmentation.
+
 config MEMORY_FAILURE
 	depends on MMU
 	depends on ARCH_SUPPORTS_MEMORY_FAILURE
diff -ruw linux-6.4/mm/memtest.c linux-6.4-fbx/mm/memtest.c
--- linux-6.4/mm/memtest.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/mm/memtest.c	2023-11-29 17:07:14.014995341 +0100
@@ -28,6 +28,7 @@
 	0x7a6c7258554e494cULL, /* yeah ;-) */
 };
 
+#ifndef CONFIG_X86 // original code
 static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad)
 {
 	pr_info("  %016llx bad mem addr %pa - %pa reserved\n",
@@ -68,19 +69,83 @@
 
 	early_memtest_done = true;
 }
+#else // fbx6hd
+/*
+ * Count memory errors in segment [a,b]
+ * If an error is detected, remove segment from memory pool.
+ */
+static void __init test_segment(unsigned long a, unsigned long b, u64 pat)
+{
+	int err_count = 0;
+	u64 *p;
+
+	/*
+	 * If an exception, such as page fault, is required to prefetch the data,
+	 * then the software prefetch instruction retires without prefetching data.
+	 */
+	for (p = __va(a); p != __va(b); p += 4) {
+		__builtin_prefetch(p+64);
+		if (p[0] != pat || p[1] != pat || p[2] != pat || p[3] != pat)
+			++err_count;
+	}
+
+	if (err_count) {
+		pr_warn("BAD+RAM: %lx-%lx: N=%d", a, b, err_count);
+		memblock_reserve(a, b-a);
+	}
+}
+
+typedef u64 u128 __attribute__ ((__vector_size__ (16)));
+
+static void __init write_pattern(unsigned long a, unsigned long b, u64 pat)
+{
+	u128 val = (u128){ pat, pat };
+	u128 *p = __va(a), *q = __va(b);
+	kernel_fpu_begin();
+	asm("movdqa %0, %%xmm0" : : "m" (val));
+	for (/**/; p != q; ++p)
+		asm("movntdq %%xmm0, %0" : "=m" (*p));
+	kernel_fpu_end();
+}
+
+#define SEGMENT_SIZE (1 << 16) // 64K
+
+static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size)
+{
+	/* On fbx6hd, ulong is wide enough to store physical addresses */
+	unsigned long curr = start_phys;
+	unsigned long next = ALIGN(curr + 1, SEGMENT_SIZE);
+	unsigned long end = start_phys + size;
+
+	// Check alignment for correct loop unrolling
+	if (curr & 0x1f || end & 0x1f) {
+		pr_warn("BAD+RAM: %lx-%lx: misaligned", curr, end);
+		return;
+	}
+
+	write_pattern(curr, end, pattern);
+
+	while (curr < end) {
+		if (next > end)
+			next = end;
+		test_segment(curr, next, pattern);
+		curr = next;
+		next += SEGMENT_SIZE;
+	}
+}
+#endif
 
 static void __init do_one_pass(u64 pattern, phys_addr_t start, phys_addr_t end)
 {
 	u64 i;
 	phys_addr_t this_start, this_end;
 
+	pr_info("pattern %016llx\n", cpu_to_be64(pattern));
 	for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &this_start,
 				&this_end, NULL) {
 		this_start = clamp(this_start, start, end);
 		this_end = clamp(this_end, start, end);
 		if (this_start < this_end) {
-			pr_info("  %pa - %pa pattern %016llx\n",
-				&this_start, &this_end, cpu_to_be64(pattern));
 			memtest(pattern, this_start, this_end - this_start);
 		}
 	}
diff -ruw linux-6.4/mm/page_alloc.c linux-6.4-fbx/mm/page_alloc.c
--- linux-6.4/mm/page_alloc.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/mm/page_alloc.c	2023-11-29 17:07:14.024995357 +0100
@@ -4887,18 +4887,24 @@
 {
 	struct page *page = NULL;
 	gfp_t gfp = gfp_mask;
+	unsigned int order;
 
 #if (PAGE_SIZE < PAGE_FRAG_CACHE_MAX_SIZE)
 	gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY |
 		    __GFP_NOMEMALLOC;
 	page = alloc_pages_node(NUMA_NO_NODE, gfp_mask,
 				PAGE_FRAG_CACHE_MAX_ORDER);
+	order = PAGE_FRAG_CACHE_MAX_ORDER;
 	nc->size = page ? PAGE_FRAG_CACHE_MAX_SIZE : PAGE_SIZE;
 #endif
-	if (unlikely(!page))
+	if (unlikely(!page)) {
 		page = alloc_pages_node(NUMA_NO_NODE, gfp, 0);
+		order = 0;
+	}
 
 	nc->va = page ? page_address(page) : NULL;
+	if (page)
+		set_page_owner_frag_cache(page, order, nc);
 
 	return page;
 }
diff -ruw linux-6.4/mm/vmalloc.c linux-6.4-fbx/mm/vmalloc.c
--- linux-6.4/mm/vmalloc.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/mm/vmalloc.c	2023-11-29 17:07:14.034995372 +0100
@@ -3340,6 +3340,19 @@
 EXPORT_SYMBOL_GPL(__vmalloc_node);
 #endif
 
+/*
+ * __vmalloc_pgprot(): same as __vmalloc, but with a pgprot_t parameter.
+ *
+ * required for IntelCE drivers.
+ */
+void *__vmalloc_pgprot(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+{
+	return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
+				    gfp_mask, prot, 0, NUMA_NO_NODE,
+				    __builtin_return_address(0));
+}
+EXPORT_SYMBOL(__vmalloc_pgprot);
+
 void *__vmalloc(unsigned long size, gfp_t gfp_mask)
 {
 	return __vmalloc_node(size, 1, gfp_mask, NUMA_NO_NODE,
diff -ruw linux-6.4/net/8021q/Kconfig linux-6.4-fbx/net/8021q/Kconfig
--- linux-6.4/net/8021q/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/8021q/Kconfig	2024-02-21 16:43:28.713137331 +0100
@@ -39,3 +39,12 @@
 	  supersedes GVRP and is not backwards-compatible.
 
 	  If unsure, say N.
+
+config VLAN_FBX
+	bool "Freebox specific VLAN ethertype to bypass dump switches"
+	depends on VLAN_8021Q
+	help
+	  Select this to enable FBX VLAN specific ethertype to bypass
+	  switches that drops 802.1q packets
+
+	  If unsure, say N.
diff -ruw linux-6.4/net/8021q/vlan.c linux-6.4-fbx/net/8021q/vlan.c
--- linux-6.4/net/8021q/vlan.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/8021q/vlan.c	2023-11-29 17:07:14.044995388 +0100
@@ -211,7 +211,7 @@
 /*  Attach a VLAN device to a mac address (ie Ethernet Card).
  *  Returns 0 if the device was created or a negative error code otherwise.
  */
-static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
+int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
 {
 	struct net_device *new_dev;
 	struct vlan_dev_priv *vlan;
diff -ruw linux-6.4/net/8021q/vlan.h linux-6.4-fbx/net/8021q/vlan.h
--- linux-6.4/net/8021q/vlan.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/8021q/vlan.h	2024-02-21 16:43:28.713137331 +0100
@@ -16,6 +16,9 @@
 enum vlan_protos {
 	VLAN_PROTO_8021Q	= 0,
 	VLAN_PROTO_8021AD,
+#ifdef CONFIG_VLAN_FBX
+	VLAN_PROTO_FBX,
+#endif
 	VLAN_PROTO_NUM,
 };
 
@@ -43,6 +46,10 @@
 		return VLAN_PROTO_8021Q;
 	case htons(ETH_P_8021AD):
 		return VLAN_PROTO_8021AD;
+#ifdef CONFIG_VLAN_FBX
+	case htons(ETH_P_FBXVLAN):
+		return VLAN_PROTO_FBX;
+#endif
 	default:
 		WARN(1, "invalid VLAN protocol: 0x%04x\n", ntohs(proto));
 		return -EINVAL;
diff -ruw linux-6.4/net/8021q/vlan_core.c linux-6.4-fbx/net/8021q/vlan_core.c
--- linux-6.4/net/8021q/vlan_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/8021q/vlan_core.c	2023-11-29 17:07:14.044995388 +0100
@@ -99,6 +99,12 @@
 }
 EXPORT_SYMBOL(__vlan_find_dev_deep_rcu);
 
+struct net_device *vlan_dev_upper_dev(const struct net_device *dev)
+{
+	return vlan_dev_priv(dev)->real_dev;
+}
+EXPORT_SYMBOL(vlan_dev_upper_dev);
+
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
 	struct net_device *ret = vlan_dev_priv(dev)->real_dev;
diff -ruw linux-6.4/net/8021q/vlan_netlink.c linux-6.4-fbx/net/8021q/vlan_netlink.c
--- linux-6.4/net/8021q/vlan_netlink.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/8021q/vlan_netlink.c	2024-02-21 16:43:28.713137331 +0100
@@ -63,6 +63,9 @@
 		switch (nla_get_be16(data[IFLA_VLAN_PROTOCOL])) {
 		case htons(ETH_P_8021Q):
 		case htons(ETH_P_8021AD):
+#ifdef CONFIG_VLAN_FBX
+		case htons(ETH_P_FBXVLAN):
+#endif
 			break;
 		default:
 			NL_SET_ERR_MSG_MOD(extack, "Invalid VLAN protocol");
diff -ruw linux-6.4/net/Kconfig linux-6.4-fbx/net/Kconfig
--- linux-6.4/net/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/Kconfig	2024-01-12 13:49:05.006702363 +0100
@@ -32,6 +32,10 @@
 	  This option can be selected by other options that need compat
 	  netlink messages.
 
+config NET_PROMISC_MESSAGES
+	bool "show promisc/allmulti status change in kernel log"
+	default y
+
 config COMPAT_NETLINK_MESSAGES
 	def_bool y
 	depends on COMPAT
@@ -60,6 +64,19 @@
 
 menu "Networking options"
 
+config NETSKBPAD
+	int "Size reserved by dev_alloc_skb"
+	default 32
+
+config NETRXTHREAD
+	bool "Do rx network processing in kernel thread"
+	depends on BROKEN_ON_SMP
+
+config NETRXTHREAD_RX_QUEUE
+	int "Number of rx queues"
+	default 1
+	depends on NETRXTHREAD
+
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
 source "net/tls/Kconfig"
@@ -236,6 +253,8 @@
 source "net/tipc/Kconfig"
 source "net/atm/Kconfig"
 source "net/l2tp/Kconfig"
+source "net/fbxatm/Kconfig"
+source "net/fbxbridge/Kconfig"
 source "net/802/Kconfig"
 source "net/bridge/Kconfig"
 source "net/dsa/Kconfig"
diff -ruw linux-6.4/net/Makefile linux-6.4-fbx/net/Makefile
--- linux-6.4/net/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/Makefile	2024-01-12 13:49:05.006702363 +0100
@@ -39,6 +39,12 @@
 obj-$(CONFIG_STREAM_PARSER)	+= strparser/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_L2TP)		+= l2tp/
+ifneq ($(CONFIG_FBXATM),)
+obj-y				+= fbxatm/
+endif
+ifneq ($(CONFIG_FBXBRIDGE),)
+obj-y				+= fbxbridge/
+endif
 obj-$(CONFIG_PHONET)		+= phonet/
 ifneq ($(CONFIG_VLAN_8021Q),)
 obj-y				+= 8021q/
diff -ruw linux-6.4/net/batman-adv/Kconfig linux-6.4-fbx/net/batman-adv/Kconfig
--- linux-6.4/net/batman-adv/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/batman-adv/Kconfig	2024-01-12 13:49:05.006702363 +0100
@@ -94,3 +94,31 @@
 	  messages using the generic tracing infrastructure of the kernel.
 	  BATMAN_ADV_DEBUG must also be selected to get trace events for
 	  batadv_dbg.
+
+config BATMAN_ADV_FBX
+	bool "B.A.T.M.A.N. FBX specific features"
+	depends on BATMAN_ADV
+	help
+	  This enables FBX specific options to be selected (e.g. MTU
+	  discovery, SLAP protocol).
+
+config BATMAN_ADV_FBX_MTU
+	bool "B.A.T.M.A.N. FBX path max MTU discovery feature"
+	depends on BATMAN_ADV_FBX
+	help
+	  This enables FBX path max MTU discovery protocol.
+
+config BATMAN_ADV_FBX_SLAP
+	bool "B.A.T.M.A.N. FBX SLAP"
+	depends on BATMAN_ADV_FBX
+	help
+	  This enables FBX SLAP (simple loop avoidance protocol) to handle
+	  blend of LAN and B.A.T.M.A.N traffic on ethernet port correctly
+	  in Freebox configuration
+
+config BATMAN_ADV_FBX_PERIF_ROUTER
+	bool "B.A.T.M.A.N. FBX perif router"
+	depends on BATMAN_ADV_FBX && BATMAN_ADV_BATMAN_V
+	help
+	  Keep track of per interface best router to reach a specific
+	  originator.
diff -ruw linux-6.4/net/batman-adv/Makefile linux-6.4-fbx/net/batman-adv/Makefile
--- linux-6.4/net/batman-adv/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/batman-adv/Makefile	2024-01-12 13:49:05.006702363 +0100
@@ -4,6 +4,7 @@
 # Marek Lindner, Simon Wunderlich
 
 obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
+
 batman-adv-y += bat_algo.o
 batman-adv-y += bat_iv_ogm.o
 batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v.o
@@ -30,5 +31,9 @@
 batman-adv-y += tp_meter.o
 batman-adv-y += translation-table.o
 batman-adv-y += tvlv.o
+batman-adv-$(CONFIG_BATMAN_ADV_FBX) += fbx/fbx.o
+batman-adv-$(CONFIG_BATMAN_ADV_FBX_MTU) += fbx/mtu.o
+batman-adv-$(CONFIG_BATMAN_ADV_FBX_SLAP) += fbx/slap.o
+batman-adv-$(CONFIG_BATMAN_ADV_FBX_PERIF_ROUTER) += fbx/router.o
 
 CFLAGS_trace.o := -I$(src)
diff -ruw linux-6.4/net/bridge/Kconfig linux-6.4-fbx/net/bridge/Kconfig
--- linux-6.4/net/bridge/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/bridge/Kconfig	2023-11-29 17:07:14.074995434 +0100
@@ -34,6 +34,11 @@
 
 	  If unsure, say N.
 
+config BRIDGE_STATE_MESSAGES
+	bool "show port status change in kernel log"
+	depends on BRIDGE
+	default y
+
 config BRIDGE_IGMP_SNOOPING
 	bool "IGMP/MLD snooping"
 	depends on BRIDGE
diff -ruw linux-6.4/net/bridge/br_private.h linux-6.4-fbx/net/bridge/br_private.h
--- linux-6.4/net/bridge/br_private.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/bridge/br_private.h	2024-01-12 13:49:05.010035721 +0100
@@ -569,6 +569,7 @@
 #if IS_ENABLED(CONFIG_BRIDGE_CFM)
 	struct hlist_head		mep_list;
 #endif
+	unsigned int			forced_mtu;
 };
 
 struct br_input_skb_cb {
@@ -623,8 +624,14 @@
 	br_printk(KERN_WARNING, __br, format, ##args)
 #define br_notice(__br, format, args...)		\
 	br_printk(KERN_NOTICE, __br, format, ##args)
+
+#ifdef CONFIG_BRIDGE_STATE_MESSAGES
 #define br_info(__br, format, args...)			\
 	br_printk(KERN_INFO, __br, format, ##args)
+#else
+#define br_info(__br, format, args...)			\
+	pr_debug("%s: " format,  (__br)->dev->name, ##args)
+#endif
 
 #define br_debug(br, format, args...)			\
 	pr_debug("%s: " format,  (br)->dev->name, ##args)
@@ -811,6 +818,9 @@
 		   unsigned long off);
 int br_fdb_add_local(struct net_bridge *br, struct net_bridge_port *source,
 		     const unsigned char *addr, u16 vid);
+bool br_fdb_update_only(struct net_bridge *br,
+			struct net_bridge_port *source,
+			const unsigned char *addr);
 void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 		   const unsigned char *addr, u16 vid, unsigned long flags);
 
diff -ruw linux-6.4/net/core/Makefile linux-6.4-fbx/net/core/Makefile
--- linux-6.4/net/core/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/Makefile	2023-11-29 17:07:14.091662127 +0100
@@ -13,7 +13,7 @@
 			neighbour.o rtnetlink.o utils.o link_watch.o filter.o \
 			sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
 			fib_notifier.o xdp.o flow_offload.o gro.o \
-			netdev-genl.o netdev-genl-gen.o
+			netdev-genl.o netdev-genl-gen.o gso.o
 
 obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
 
diff -ruw linux-6.4/net/core/dev.c linux-6.4-fbx/net/core/dev.c
--- linux-6.4/net/core/dev.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/dev.c	2024-01-12 13:49:05.013369080 +0100
@@ -150,6 +150,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/prandom.h>
 #include <linux/once_lite.h>
+#include <linux/kthread.h>
 
 #include "dev.h"
 #include "net-sysfs.h"
@@ -165,6 +166,10 @@
 					   struct netlink_ext_ack *extack);
 static struct napi_struct *napi_by_id(unsigned int napi_id);
 
+#ifdef CONFIG_NETRXTHREAD
+struct krxd gkrxd[CONFIG_NETRXTHREAD_RX_QUEUE];
+#endif
+
 /*
  * The @dev_base_head list is protected by @dev_base_lock and the rtnl
  * semaphore.
@@ -3209,7 +3214,7 @@
 	return (u16) reciprocal_scale(skb_get_hash(skb), qcount) + qoffset;
 }
 
-static void skb_warn_bad_offload(const struct sk_buff *skb)
+void skb_warn_bad_offload(const struct sk_buff *skb)
 {
 	static const netdev_features_t null_features;
 	struct net_device *dev = skb->dev;
@@ -3338,74 +3343,6 @@
 	return vlan_get_protocol_and_depth(skb, type, depth);
 }
 
-/* openvswitch calls this on rx path, so we need a different check.
- */
-static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
-{
-	if (tx_path)
-		return skb->ip_summed != CHECKSUM_PARTIAL &&
-		       skb->ip_summed != CHECKSUM_UNNECESSARY;
-
-	return skb->ip_summed == CHECKSUM_NONE;
-}
-
-/**
- *	__skb_gso_segment - Perform segmentation on skb.
- *	@skb: buffer to segment
- *	@features: features for the output path (see dev->features)
- *	@tx_path: whether it is called in TX path
- *
- *	This function segments the given skb and returns a list of segments.
- *
- *	It may return NULL if the skb requires no segmentation.  This is
- *	only possible when GSO is used for verifying header integrity.
- *
- *	Segmentation preserves SKB_GSO_CB_OFFSET bytes of previous skb cb.
- */
-struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
-				  netdev_features_t features, bool tx_path)
-{
-	struct sk_buff *segs;
-
-	if (unlikely(skb_needs_check(skb, tx_path))) {
-		int err;
-
-		/* We're going to init ->check field in TCP or UDP header */
-		err = skb_cow_head(skb, 0);
-		if (err < 0)
-			return ERR_PTR(err);
-	}
-
-	/* Only report GSO partial support if it will enable us to
-	 * support segmentation on this frame without needing additional
-	 * work.
-	 */
-	if (features & NETIF_F_GSO_PARTIAL) {
-		netdev_features_t partial_features = NETIF_F_GSO_ROBUST;
-		struct net_device *dev = skb->dev;
-
-		partial_features |= dev->features & dev->gso_partial_features;
-		if (!skb_gso_ok(skb, features | partial_features))
-			features &= ~NETIF_F_GSO_PARTIAL;
-	}
-
-	BUILD_BUG_ON(SKB_GSO_CB_OFFSET +
-		     sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb));
-
-	SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb);
-	SKB_GSO_CB(skb)->encap_level = 0;
-
-	skb_reset_mac_header(skb);
-	skb_reset_mac_len(skb);
-
-	segs = skb_mac_gso_segment(skb, features);
-
-	if (segs != skb && unlikely(skb_needs_check(skb, tx_path) && !IS_ERR(segs)))
-		skb_warn_bad_offload(skb);
-
-	return segs;
-}
-EXPORT_SYMBOL(__skb_gso_segment);
 
 /* Take action when hardware reception checksum errors are detected. */
 #ifdef CONFIG_BUG
@@ -4959,6 +4896,23 @@
 	return ret;
 }
 
+/* Start Freebox added code */
+#if defined(CONFIG_FREEBOX_DIVERTER) || defined(CONFIG_FREEBOX_DIVERTER_MODULE)
+int (*fbxdiverter_hook)(struct sk_buff *);
+
+static int handle_fbxdiverter(struct sk_buff *skb)
+{
+	/* try_module_get is missing here, so there is a race on
+	 * fbxdiverter module deletion */
+	if (!fbxdiverter_hook)
+		return 0;
+	return fbxdiverter_hook(skb);
+}
+
+EXPORT_SYMBOL(fbxdiverter_hook);
+#endif
+
+
 /**
  *	__netif_rx	-	Slightly optimized version of netif_rx
  *	@skb: buffer to post
@@ -5278,28 +5232,116 @@
 	return 0;
 }
 
+static int __netif_receive_skb_core_end(struct sk_buff **pskb, bool pfmemalloc,
+					struct packet_type **ppt_prev);
+
 static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
 				    struct packet_type **ppt_prev)
 {
-	struct packet_type *ptype, *pt_prev;
-	rx_handler_func_t *rx_handler;
 	struct sk_buff *skb = *pskb;
-	struct net_device *orig_dev;
-	bool deliver_exact = false;
-	int ret = NET_RX_DROP;
-	__be16 type;
+#ifdef CONFIG_NETRXTHREAD
+	unsigned int len;
+	struct krxd *krxd;
+#endif
 
 	net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb);
 
 	trace_netif_receive_skb(skb);
 
-	orig_dev = skb->dev;
-
 	skb_reset_network_header(skb);
 	if (!skb_transport_header_was_set(skb))
 		skb_reset_transport_header(skb);
 	skb_reset_mac_len(skb);
 
+#if defined(CONFIG_FREEBOX_DIVERTER) || defined(CONFIG_FREEBOX_DIVERTER_MODULE)
+	if (handle_fbxdiverter(skb))
+		return NET_RX_SUCCESS;
+#endif
+
+#ifndef CONFIG_NETRXTHREAD
+	return __netif_receive_skb_core_end(pskb, pfmemalloc, ppt_prev);
+#else
+	if (pfmemalloc)
+		return __netif_receive_skb_core_end(pskb, pfmemalloc, ppt_prev);
+
+	BUILD_BUG_ON(ARRAY_SIZE(gkrxd) < 2);
+	krxd = &gkrxd[skb->rxthread_prio & 1];
+
+        /* queue the packet to the rx thread */
+	local_bh_disable();
+	len = skb_queue_len(&krxd->pkt_queue);
+	if (len < RXTHREAD_MAX_PKTS) {
+		__skb_queue_tail(&krxd->pkt_queue, skb);
+		krxd->stats_pkts++;
+		if (!len)
+			wake_up(&krxd->wq);
+	} else {
+		krxd->stats_dropped++;
+		dev_kfree_skb(skb);
+        }
+	local_bh_enable();
+	return NET_RX_SUCCESS;
+#endif
+}
+
+#ifdef CONFIG_NETRXTHREAD
+static int krxd_action(void *data)
+{
+	struct krxd *krxd = (struct krxd *)data;
+	unsigned int queue = krxd - gkrxd;
+	struct sk_buff *skb;
+
+	set_user_nice(current, queue > 0 ? -10 : -5);
+	current->flags |= PF_NOFREEZE;
+	__set_current_state(TASK_RUNNING);
+
+	local_bh_disable();
+	while (1) {
+		struct packet_type *pt_prev = NULL;
+		struct net_device *orig_dev;
+
+		skb = skb_dequeue(&krxd->pkt_queue);
+		if (!skb) {
+			local_bh_enable();
+			wait_event_interruptible(krxd->wq,
+						 skb_queue_len(&krxd->pkt_queue));
+			set_current_state(TASK_RUNNING);
+			local_bh_disable();
+			continue;
+		}
+
+		rcu_read_lock();
+		orig_dev = skb->dev;
+		__netif_receive_skb_core_end(&skb, false, &pt_prev);
+		if (pt_prev)
+			INDIRECT_CALL_INET(pt_prev->func,
+					   ipv6_rcv, ip_rcv, skb,
+					   skb->dev, pt_prev, orig_dev);
+		rcu_read_unlock();
+
+		/* only schedule when working on lowest prio queue */
+		if (queue == 0 && need_resched()) {
+			local_bh_enable();
+			schedule();
+			local_bh_disable();
+		}
+	}
+	return 0;
+}
+#endif
+
+static int __netif_receive_skb_core_end(struct sk_buff **pskb, bool pfmemalloc,
+					struct packet_type **ppt_prev)
+{
+	struct sk_buff *skb = *pskb;
+	struct packet_type *ptype, *pt_prev;
+	rx_handler_func_t *rx_handler;
+	struct net_device *orig_dev;
+	bool deliver_exact = false;
+	int ret = NET_RX_DROP;
+	__be16 type;
+
+	orig_dev = skb->dev;
 	pt_prev = NULL;
 
 another_round:
@@ -5457,7 +5499,9 @@
 	if (pt_prev) {
 		if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC)))
 			goto drop;
-		*ppt_prev = pt_prev;
+		else
+			ret = INDIRECT_CALL_INET(pt_prev->func, ipv6_rcv, ip_rcv, skb,
+						 skb->dev, pt_prev, orig_dev);
 	} else {
 drop:
 		if (!deliver_exact)
@@ -5488,10 +5532,16 @@
 	struct packet_type *pt_prev = NULL;
 	int ret;
 
+#ifdef CONFIG_NETRXTHREAD
+	(void)orig_dev;
+	ret = __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev);
+#else
 	ret = __netif_receive_skb_core(&skb, pfmemalloc, &pt_prev);
 	if (pt_prev)
 		ret = INDIRECT_CALL_INET(pt_prev->func, ipv6_rcv, ip_rcv, skb,
 					 skb->dev, pt_prev, orig_dev);
+#endif
+
 	return ret;
 }
 
@@ -8356,8 +8406,10 @@
 		}
 	}
 	if (dev->flags != old_flags) {
+#ifdef CONFIG_NET_PROMISC_MESSAGES
 		netdev_info(dev, "%s promiscuous mode\n",
 			    dev->flags & IFF_PROMISC ? "entered" : "left");
+#endif
 		if (audit_enabled) {
 			current_uid_gid(&uid, &gid);
 			audit_log(audit_context(), GFP_ATOMIC,
@@ -8425,8 +8477,10 @@
 		}
 	}
 	if (dev->flags ^ old_flags) {
+#ifdef CONFIG_NET_PROMISC_MESSAGES
 		netdev_info(dev, "%s allmulticast mode\n",
 			    dev->flags & IFF_ALLMULTI ? "entered" : "left");
+#endif
 		dev_change_rx_flags(dev, IFF_ALLMULTI);
 		dev_set_rx_mode(dev);
 		if (notify)
@@ -11477,6 +11531,24 @@
 	open_softirq(NET_TX_SOFTIRQ, net_tx_action);
 	open_softirq(NET_RX_SOFTIRQ, net_rx_action);
 
+#ifdef CONFIG_NETRXTHREAD
+        for (i = 0; i < CONFIG_NETRXTHREAD_RX_QUEUE; i++) {
+		struct krxd *krxd = &gkrxd[i];
+		struct task_struct *task;
+
+		skb_queue_head_init(&krxd->pkt_queue);
+		init_waitqueue_head(&krxd->wq);
+		task = kthread_create(krxd_action, krxd, "krxthread_%u", i);
+		if (IS_ERR(task)) {
+			printk(KERN_ERR "unable to create krxd\n");
+			return -ENOMEM;
+		}
+		krxd->task = task;
+		wake_up_process(task);
+	}
+#endif
+
+
 	rc = cpuhp_setup_state_nocalls(CPUHP_NET_DEV_DEAD, "net/dev:dead",
 				       NULL, dev_cpu_dead);
 	WARN_ON(rc < 0);
diff -ruw linux-6.4/net/core/gro.c linux-6.4-fbx/net/core/gro.c
--- linux-6.4/net/core/gro.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/gro.c	2023-11-29 17:07:14.101662142 +0100
@@ -10,7 +10,7 @@
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
 
 static DEFINE_SPINLOCK(offload_lock);
-static struct list_head offload_base __read_mostly = LIST_HEAD_INIT(offload_base);
+struct list_head offload_base __read_mostly = LIST_HEAD_INIT(offload_base);
 /* Maximum number of GRO_NORMAL skbs to batch up for list-RX */
 int gro_normal_batch __read_mostly = 8;
 
@@ -92,63 +92,6 @@
 }
 EXPORT_SYMBOL(dev_remove_offload);
 
-/**
- *	skb_eth_gso_segment - segmentation handler for ethernet protocols.
- *	@skb: buffer to segment
- *	@features: features for the output path (see dev->features)
- *	@type: Ethernet Protocol ID
- */
-struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features, __be16 type)
-{
-	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
-	struct packet_offload *ptype;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(ptype, &offload_base, list) {
-		if (ptype->type == type && ptype->callbacks.gso_segment) {
-			segs = ptype->callbacks.gso_segment(skb, features);
-			break;
-		}
-	}
-	rcu_read_unlock();
-
-	return segs;
-}
-EXPORT_SYMBOL(skb_eth_gso_segment);
-
-/**
- *	skb_mac_gso_segment - mac layer segmentation handler.
- *	@skb: buffer to segment
- *	@features: features for the output path (see dev->features)
- */
-struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
-				    netdev_features_t features)
-{
-	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
-	struct packet_offload *ptype;
-	int vlan_depth = skb->mac_len;
-	__be16 type = skb_network_protocol(skb, &vlan_depth);
-
-	if (unlikely(!type))
-		return ERR_PTR(-EINVAL);
-
-	__skb_pull(skb, vlan_depth);
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(ptype, &offload_base, list) {
-		if (ptype->type == type && ptype->callbacks.gso_segment) {
-			segs = ptype->callbacks.gso_segment(skb, features);
-			break;
-		}
-	}
-	rcu_read_unlock();
-
-	__skb_push(skb, skb->data - skb_mac_header(skb));
-
-	return segs;
-}
-EXPORT_SYMBOL(skb_mac_gso_segment);
 
 int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
 {
diff -ruw linux-6.4/net/core/net-procfs.c linux-6.4-fbx/net/core/net-procfs.c
--- linux-6.4/net/core/net-procfs.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/net-procfs.c	2023-11-29 17:07:14.104995481 +0100
@@ -200,6 +200,89 @@
 	.show  = softnet_seq_show,
 };
 
+static struct page_frag_cache *frag_alloc_netdev_get_online(loff_t *pos)
+{
+	struct page_frag_cache *nc = NULL;
+
+	while (*pos < nr_cpu_ids)
+		if (cpu_online(*pos)) {
+			nc = netdev_frag_cache_get(*pos);
+			break;
+		} else
+			++*pos;
+	return nc;
+}
+
+static struct page_frag_cache *frag_alloc_napi_get_online(loff_t *pos)
+{
+	struct page_frag_cache *nc = NULL;
+
+	while (*pos < nr_cpu_ids)
+		if (cpu_online(*pos)) {
+			nc = napi_frag_cache_get(*pos);
+			break;
+		} else
+			++*pos;
+	return nc;
+}
+
+static void *frag_alloc_netdev_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return frag_alloc_netdev_get_online(pos);
+}
+
+static void *frag_alloc_netdev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return frag_alloc_netdev_get_online(pos);
+}
+
+static void *frag_alloc_napi_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return frag_alloc_napi_get_online(pos);
+}
+
+static void *frag_alloc_napi_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return frag_alloc_napi_get_online(pos);
+}
+
+static void frag_alloc_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int frag_alloc_seq_show(struct seq_file *seq, void *v)
+{
+#ifdef CONFIG_PAGE_OWNER
+	struct page_frag_cache *nc = v;
+	unsigned int pages = atomic_read(&nc->pages_allocated);
+
+	seq_printf(seq,
+		   "cpu[%d]: pages:%u (%lu kB)\n",
+		   (int)seq->index, pages, (pages * PAGE_SIZE) / 1024);
+#else
+	seq_printf(seq,
+		   "cpu[%d]: CONFIG_PAGE_OWNER missing\n",
+		   (int)seq->index);
+#endif
+	return 0;
+}
+
+static const struct seq_operations frag_alloc_netdev_seq_ops = {
+	.start = frag_alloc_netdev_seq_start,
+	.next  = frag_alloc_netdev_seq_next,
+	.stop  = frag_alloc_seq_stop,
+	.show  = frag_alloc_seq_show,
+};
+
+static const struct seq_operations frag_alloc_napi_seq_ops = {
+	.start = frag_alloc_napi_seq_start,
+	.next  = frag_alloc_napi_seq_next,
+	.stop  = frag_alloc_seq_stop,
+	.show  = frag_alloc_seq_show,
+};
+
 static void *ptype_get_idx(struct seq_file *seq, loff_t pos)
 {
 	struct list_head *ptype_list = NULL;
@@ -320,6 +403,85 @@
 	.show  = ptype_seq_show,
 };
 
+#ifdef CONFIG_NETRXTHREAD
+/*
+ *	This is invoked by the /proc filesystem handler to display a device
+ *	in detail.
+ */
+static void *krxthread_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	int *queue;
+
+	if (*pos > CONFIG_NETRXTHREAD_RX_QUEUE)
+		return NULL;
+
+	queue = kmalloc(sizeof(*queue), GFP_KERNEL);
+	if (!queue)
+		return NULL;
+	*queue = ((int)*pos - 1);
+
+	return queue;
+}
+
+static void *krxthread_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	int *queue = v;
+
+	if (*pos == CONFIG_NETRXTHREAD_RX_QUEUE) {
+		++*pos;
+		return NULL;
+	}
+
+	++*queue;
+	*pos = *queue + 1;
+	return queue;
+}
+
+static void krxthread_seq_stop(struct seq_file *seq, void *v)
+{
+	kfree(v);
+}
+
+static void krxthread_seq_printf_stats(struct seq_file *seq, int queue)
+{
+	seq_printf(seq, "%8u %12u %12u\n",
+		   queue,
+		   gkrxd[queue].stats_pkts,
+		   gkrxd[queue].stats_dropped);
+}
+
+static int krxthread_seq_show(struct seq_file *seq, void *v)
+{
+	int *queue = v;
+
+	if (*queue == -1)
+		seq_printf(seq, "%8s %12s %12s\n",
+			   "queue", "packets", "drops");
+	else
+		krxthread_seq_printf_stats(seq, *queue);
+	return 0;
+}
+
+static const struct seq_operations krxthread_seq_ops = {
+	.start = krxthread_seq_start,
+	.next  = krxthread_seq_next,
+	.stop  = krxthread_seq_stop,
+	.show  = krxthread_seq_show,
+};
+
+static int krxthread_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &krxthread_seq_ops);
+}
+
+static const struct proc_ops krxthread_seq_fops = {
+	.proc_open	= krxthread_seq_open,
+	.proc_read	= seq_read,
+	.proc_lseek	= seq_lseek,
+	.proc_release	= seq_release,
+};
+#endif /* KRXTHREAD */
+
 static int __net_init dev_proc_net_init(struct net *net)
 {
 	int rc = -ENOMEM;
@@ -333,9 +495,20 @@
 	if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops,
 			sizeof(struct seq_net_private)))
 		goto out_softnet;
+	if (!proc_create_seq("frag_alloc_netdev", 0444, net->proc_net,
+			     &frag_alloc_netdev_seq_ops))
+		goto out_softnet;
+	if (!proc_create_seq("frag_alloc_napi", 0444, net->proc_net,
+			     &frag_alloc_napi_seq_ops))
+		goto out_softnet;
 
 	if (wext_proc_init(net))
 		goto out_ptype;
+#ifdef CONFIG_NETRXTHREAD
+	if (!proc_create("krxthread", S_IRUGO, net->proc_net,
+			 &krxthread_seq_fops))
+		goto out_ptype;
+#endif
 	rc = 0;
 out:
 	return rc;
diff -ruw linux-6.4/net/core/net-sysfs.c linux-6.4-fbx/net/core/net-sysfs.c
--- linux-6.4/net/core/net-sysfs.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/net-sysfs.c	2023-11-29 17:07:14.104995481 +0100
@@ -15,6 +15,7 @@
 #include <linux/nsproxy.h>
 #include <net/sock.h>
 #include <net/net_namespace.h>
+#include <net/cfg80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
@@ -747,7 +748,28 @@
 	.attrs  = netstat_attrs,
 };
 
+#if IS_ENABLED(CONFIG_CFG80211)
+static ssize_t show_nl80211_iftype(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	const struct net_device *netdev = to_net_dev(dev);
+	ssize_t ret = 0;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+	if (netdev->ieee80211_ptr)
+		ret = sprintf(buf, "%d\n", netdev->ieee80211_ptr->iftype);
+	rtnl_unlock();
+
+	return ret;
+}
+static DEVICE_ATTR(nl80211_iftype, S_IRUGO, show_nl80211_iftype, NULL);
+#endif
+
 static struct attribute *wireless_attrs[] = {
+#if IS_ENABLED(CONFIG_CFG80211)
+	&dev_attr_nl80211_iftype.attr,
+#endif
 	NULL
 };
 
diff -ruw linux-6.4/net/core/of_net.c linux-6.4-fbx/net/core/of_net.c
--- linux-6.4/net/core/of_net.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/of_net.c	2023-11-29 17:07:14.108328819 +0100
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/device.h>
 #include <linux/nvmem-consumer.h>
+#include <linux/fbxserial.h>
 
 /**
  * of_get_phy_mode - Get phy mode for given device_node
@@ -96,6 +97,23 @@
 }
 EXPORT_SYMBOL(of_get_mac_address_nvmem);
 
+static int of_get_mac_addr_from_fbxserial(struct device_node *np, u8 *addr)
+{
+#ifdef CONFIG_FBXSERIAL
+	struct property *pp;
+
+	pp = of_find_property(np, "fbxserial-mac-address", NULL);
+	if (!pp || pp->length != 4)
+		return -ENODEV;
+
+	memcpy(addr, fbxserialinfo_get_mac_addr(be32_to_cpu(*(u32*)pp->value)),
+	       ETH_ALEN);
+	return 0;
+#else
+	return -ENOSYS;
+#endif
+}
+
 /**
  * of_get_mac_address()
  * @np:		Caller's Device Node
@@ -129,6 +147,10 @@
 	if (!np)
 		return -ENODEV;
 
+	ret = of_get_mac_addr_from_fbxserial(np, addr);
+	if (!ret)
+		return 0;
+
 	ret = of_get_mac_addr(np, "mac-address", addr);
 	if (!ret)
 		return 0;
diff -ruw linux-6.4/net/core/skbuff.c linux-6.4-fbx/net/core/skbuff.c
--- linux-6.4/net/core/skbuff.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/skbuff.c	2024-02-21 16:43:28.716470707 +0100
@@ -67,6 +67,7 @@
 #include <net/dst.h>
 #include <net/sock.h>
 #include <net/checksum.h>
+#include <net/gso.h>
 #include <net/ip6_checksum.h>
 #include <net/xfrm.h>
 #include <net/mpls.h>
@@ -281,6 +282,17 @@
 static DEFINE_PER_CPU(struct page_frag_cache, netdev_alloc_cache);
 static DEFINE_PER_CPU(struct napi_alloc_cache, napi_alloc_cache);
 
+struct page_frag_cache *netdev_frag_cache_get(unsigned int cpu_id)
+{
+	return per_cpu_ptr(&netdev_alloc_cache, cpu_id);
+}
+
+struct page_frag_cache *napi_frag_cache_get(unsigned int cpu_id)
+{
+	struct napi_alloc_cache *nc = per_cpu_ptr(&napi_alloc_cache, cpu_id);
+	return &nc->page;
+}
+
 /* Double check that napi_get_frags() allocates skbs with
  * skb->head being backed by slab, not a page fragment.
  * This is to make sure bug fixed in 3226b158e67c
@@ -893,6 +905,11 @@
 {
 	if (!IS_ENABLED(CONFIG_PAGE_POOL) || !skb->pp_recycle)
 		return false;
+
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_ff_done & BIT(1))
+		page_pool_set_recycled_flag(virt_to_page(data));
+#endif
 	return page_pool_return_skb_page(virt_to_page(data), napi_safe);
 }
 
@@ -1345,6 +1362,11 @@
 	new->queue_mapping = old->queue_mapping;
 
 	memcpy(&new->headers, &old->headers, sizeof(new->headers));
+
+#ifdef CONFIG_IP_FFN
+	new->ffn_state		= FFN_STATE_INIT;
+	new->ffn_ff_done	= 0;
+#endif
 	CHECK_SKB_FIELD(protocol);
 	CHECK_SKB_FIELD(csum);
 	CHECK_SKB_FIELD(hash);
@@ -5774,157 +5796,20 @@
 	skb->offload_fwd_mark = 0;
 	skb->offload_l3_fwd_mark = 0;
 #endif
+	skb->mark = 0;
 
+#ifdef CONFIG_IP_FFN
+	skb->ffn_state = FFN_STATE_INIT;
+	skb->ffn_ff_done = 0;
+#endif
 	if (!xnet)
 		return;
 
 	ipvs_reset(skb);
-	skb->mark = 0;
 	skb_clear_tstamp(skb);
 }
 EXPORT_SYMBOL_GPL(skb_scrub_packet);
 
-/**
- * skb_gso_transport_seglen - Return length of individual segments of a gso packet
- *
- * @skb: GSO skb
- *
- * skb_gso_transport_seglen is used to determine the real size of the
- * individual segments, including Layer4 headers (TCP/UDP).
- *
- * The MAC/L2 or network (IP, IPv6) headers are not accounted for.
- */
-static unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
-{
-	const struct skb_shared_info *shinfo = skb_shinfo(skb);
-	unsigned int thlen = 0;
-
-	if (skb->encapsulation) {
-		thlen = skb_inner_transport_header(skb) -
-			skb_transport_header(skb);
-
-		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-			thlen += inner_tcp_hdrlen(skb);
-	} else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
-		thlen = tcp_hdrlen(skb);
-	} else if (unlikely(skb_is_gso_sctp(skb))) {
-		thlen = sizeof(struct sctphdr);
-	} else if (shinfo->gso_type & SKB_GSO_UDP_L4) {
-		thlen = sizeof(struct udphdr);
-	}
-	/* UFO sets gso_size to the size of the fragmentation
-	 * payload, i.e. the size of the L4 (UDP) header is already
-	 * accounted for.
-	 */
-	return thlen + shinfo->gso_size;
-}
-
-/**
- * skb_gso_network_seglen - Return length of individual segments of a gso packet
- *
- * @skb: GSO skb
- *
- * skb_gso_network_seglen is used to determine the real size of the
- * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
- *
- * The MAC/L2 header is not accounted for.
- */
-static unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
-{
-	unsigned int hdr_len = skb_transport_header(skb) -
-			       skb_network_header(skb);
-
-	return hdr_len + skb_gso_transport_seglen(skb);
-}
-
-/**
- * skb_gso_mac_seglen - Return length of individual segments of a gso packet
- *
- * @skb: GSO skb
- *
- * skb_gso_mac_seglen is used to determine the real size of the
- * individual segments, including MAC/L2, Layer3 (IP, IPv6) and L4
- * headers (TCP/UDP).
- */
-static unsigned int skb_gso_mac_seglen(const struct sk_buff *skb)
-{
-	unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
-
-	return hdr_len + skb_gso_transport_seglen(skb);
-}
-
-/**
- * skb_gso_size_check - check the skb size, considering GSO_BY_FRAGS
- *
- * There are a couple of instances where we have a GSO skb, and we
- * want to determine what size it would be after it is segmented.
- *
- * We might want to check:
- * -    L3+L4+payload size (e.g. IP forwarding)
- * - L2+L3+L4+payload size (e.g. sanity check before passing to driver)
- *
- * This is a helper to do that correctly considering GSO_BY_FRAGS.
- *
- * @skb: GSO skb
- *
- * @seg_len: The segmented length (from skb_gso_*_seglen). In the
- *           GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS].
- *
- * @max_len: The maximum permissible length.
- *
- * Returns true if the segmented length <= max length.
- */
-static inline bool skb_gso_size_check(const struct sk_buff *skb,
-				      unsigned int seg_len,
-				      unsigned int max_len) {
-	const struct skb_shared_info *shinfo = skb_shinfo(skb);
-	const struct sk_buff *iter;
-
-	if (shinfo->gso_size != GSO_BY_FRAGS)
-		return seg_len <= max_len;
-
-	/* Undo this so we can re-use header sizes */
-	seg_len -= GSO_BY_FRAGS;
-
-	skb_walk_frags(skb, iter) {
-		if (seg_len + skb_headlen(iter) > max_len)
-			return false;
-	}
-
-	return true;
-}
-
-/**
- * skb_gso_validate_network_len - Will a split GSO skb fit into a given MTU?
- *
- * @skb: GSO skb
- * @mtu: MTU to validate against
- *
- * skb_gso_validate_network_len validates if a given skb will fit a
- * wanted MTU once split. It considers L3 headers, L4 headers, and the
- * payload.
- */
-bool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu)
-{
-	return skb_gso_size_check(skb, skb_gso_network_seglen(skb), mtu);
-}
-EXPORT_SYMBOL_GPL(skb_gso_validate_network_len);
-
-/**
- * skb_gso_validate_mac_len - Will a split GSO skb fit in a given length?
- *
- * @skb: GSO skb
- * @len: length to validate against
- *
- * skb_gso_validate_mac_len validates if a given skb will fit a wanted
- * length once split, including L2, L3 and L4 headers and the payload.
- */
-bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len)
-{
-	return skb_gso_size_check(skb, skb_gso_mac_seglen(skb), len);
-}
-EXPORT_SYMBOL_GPL(skb_gso_validate_mac_len);
-
 static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
 {
 	int mac_len, meta_len;
diff -ruw linux-6.4/net/core/sock.c linux-6.4-fbx/net/core/sock.c
--- linux-6.4/net/core/sock.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/core/sock.c	2023-11-29 17:07:14.111662158 +0100
@@ -1526,6 +1526,10 @@
 		WRITE_ONCE(sk->sk_txrehash, (u8)val);
 		break;
 
+	case SO_UDP_DUP_UNICAST:
+		sock_valbool_flag(sk, SOCK_UDP_DUP_UNICAST, valbool);
+		break;
+
 	default:
 		ret = -ENOPROTOOPT;
 		break;
@@ -1896,6 +1900,10 @@
 		v.val64 = sock_gen_cookie(sk);
 		break;
 
+	case SO_UDP_DUP_UNICAST:
+		v.val = sock_flag(sk, SOCK_UDP_DUP_UNICAST);
+		break;
+
 	case SO_ZEROCOPY:
 		v.val = sock_flag(sk, SOCK_ZEROCOPY);
 		break;
diff -ruw linux-6.4/net/dsa/Kconfig linux-6.4-fbx/net/dsa/Kconfig
--- linux-6.4/net/dsa/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/dsa/Kconfig	2023-11-29 17:07:14.121662173 +0100
@@ -63,6 +63,10 @@
 	  Say Y or M if you want to enable support for tagging frames
 	  for the Hirschmann Hellcreek TSN switches.
 
+config NET_DSA_TAG_BRCM_FBX
+	tristate "Tag driver for Broadcom switches using in-frame headers"
+	select NET_DSA_TAG_BRCM_COMMON
+
 config NET_DSA_TAG_GSWIP
 	tristate "Tag driver for Lantiq / Intel GSWIP switches"
 	help
diff -ruw linux-6.4/net/ethernet/eth.c linux-6.4-fbx/net/ethernet/eth.c
--- linux-6.4/net/ethernet/eth.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ethernet/eth.c	2023-11-29 17:07:14.128328850 +0100
@@ -62,6 +62,7 @@
 #include <net/gro.h>
 #include <linux/uaccess.h>
 #include <net/pkt_sched.h>
+#include <linux/fbxserial.h>
 
 /**
  * eth_header - create the Ethernet header
@@ -609,6 +610,21 @@
  */
 int fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr)
 {
+#ifdef CONFIG_FBXSERIAL
+	u32 index;
+	int ret;
+
+	ret = fwnode_property_read_u32(fwnode, "fbxserial-mac-address",
+				       &index);
+	if (ret == 0) {
+		const void *res = fbxserialinfo_get_mac_addr(index);
+		if (res) {
+			memcpy(addr, res, ETH_ALEN);
+			return 0;
+		}
+	}
+#endif
+
 	if (!fwnode_get_mac_addr(fwnode, "mac-address", addr) ||
 	    !fwnode_get_mac_addr(fwnode, "local-mac-address", addr) ||
 	    !fwnode_get_mac_addr(fwnode, "address", addr))
diff -ruw linux-6.4/net/ethtool/common.c linux-6.4-fbx/net/ethtool/common.c
--- linux-6.4/net/ethtool/common.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ethtool/common.c	2023-11-29 17:07:14.128328850 +0100
@@ -211,6 +211,12 @@
 	__DEFINE_LINK_MODE_NAME(10, T1S, Full),
 	__DEFINE_LINK_MODE_NAME(10, T1S, Half),
 	__DEFINE_LINK_MODE_NAME(10, T1S_P2MP, Half),
+	__DEFINE_LINK_MODE_NAME(1000, PX_D, Full),
+	__DEFINE_LINK_MODE_NAME(1000, PX_U, Full),
+	__DEFINE_LINK_MODE_NAME(10000, PR_D, Full),
+	__DEFINE_LINK_MODE_NAME(10000, PR_U, Full),
+	__DEFINE_LINK_MODE_NAME(10000_1000, PRX_D, Full),
+	__DEFINE_LINK_MODE_NAME(10000_1000, PRX_U, Full),
 };
 static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);
 
@@ -251,6 +257,10 @@
 #define __LINK_MODE_LANES_T1S_P2MP	1
 #define __LINK_MODE_LANES_VR8		8
 #define __LINK_MODE_LANES_DR8_2		8
+#define __LINK_MODE_LANES_PX_D		1
+#define __LINK_MODE_LANES_PX_U		1
+#define __LINK_MODE_LANES_PR_U		1
+#define __LINK_MODE_LANES_PR_D		1
 
 #define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex)	\
 	[ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = {		\
@@ -374,6 +384,18 @@
 	__DEFINE_LINK_MODE_PARAMS(10, T1S, Full),
 	__DEFINE_LINK_MODE_PARAMS(10, T1S, Half),
 	__DEFINE_LINK_MODE_PARAMS(10, T1S_P2MP, Half),
+	__DEFINE_LINK_MODE_PARAMS(1000, PX_D, Full),
+	__DEFINE_LINK_MODE_PARAMS(1000, PX_U, Full),
+	__DEFINE_LINK_MODE_PARAMS(10000, PR_D, Full),
+	__DEFINE_LINK_MODE_PARAMS(10000, PR_U, Full),
+	[ETHTOOL_LINK_MODE_10000_1000basePRX_D_Full_BIT] = {
+		.speed  = SPEED_10000,
+		.duplex = DUPLEX_FULL,
+	},
+	[ETHTOOL_LINK_MODE_10000_1000basePRX_U_Full_BIT] = {
+		.speed  = SPEED_10000,
+		.duplex = DUPLEX_FULL,
+	},
 };
 static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS);
 
diff -ruw linux-6.4/net/ethtool/ioctl.c linux-6.4-fbx/net/ethtool/ioctl.c
--- linux-6.4/net/ethtool/ioctl.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ethtool/ioctl.c	2023-11-29 17:07:14.128328850 +0100
@@ -17,6 +17,7 @@
 #include <linux/netdevice.h>
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
+#include <linux/phylink.h>
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
@@ -179,6 +180,9 @@
 	if (sset == ETH_SS_LINK_MODES)
 		return __ETHTOOL_LINK_MODE_MASK_NBITS;
 
+	if (sset == ETH_SS_PHYLINK_IFTYPES)
+		return PHY_INTERFACE_MODE_MAX - 1;
+
 	if (ops->get_sset_count && ops->get_strings)
 		return ops->get_sset_count(dev, sset);
 	else
@@ -208,7 +212,16 @@
 	else if (stringset == ETH_SS_LINK_MODES)
 		memcpy(data, link_mode_names,
 		       __ETHTOOL_LINK_MODE_MASK_NBITS * ETH_GSTRING_LEN);
-	else
+	else if (stringset == ETH_SS_PHYLINK_IFTYPES) {
+		int i;
+
+		for (i = PHY_INTERFACE_MODE_NA + 1;
+		     i < PHY_INTERFACE_MODE_MAX; i++) {
+			strlcpy(data + (i - 1) * ETH_GSTRING_LEN,
+				phy_modes(i),
+				ETH_GSTRING_LEN);
+		}
+	} else
 		/* ops->get_strings is valid because checked earlier */
 		ops->get_strings(dev, stringset, data);
 }
@@ -2624,6 +2637,7 @@
 	switch (tuna->id) {
 	case ETHTOOL_PHY_DOWNSHIFT:
 	case ETHTOOL_PHY_FAST_LINK_DOWN:
+	case ETHTOOL_PHY_BROKEN:
 		if (tuna->len != sizeof(u8) ||
 		    tuna->type_id != ETHTOOL_TUNABLE_U8)
 			return -EINVAL;
@@ -2750,6 +2764,156 @@
 	return dev->ethtool_ops->set_fecparam(dev, &fecparam);
 }
 
+static int ethtool_get_sfp_state(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_sfp_state sfp_state;
+	int rc;
+
+	if (!dev->sfp_bus) {
+		printk("no SFP bus ya twat.\n");
+		return -ENODEV;
+	}
+
+	rc = sfp_get_sfp_state(dev->sfp_bus, &sfp_state);
+	if (rc)
+		return rc;
+
+	if (copy_to_user(useraddr, &sfp_state, sizeof (sfp_state)))
+		return -EFAULT;
+	return 0;
+}
+
+static int ethtool_get_shaper_params(struct net_device *dev, void __user *uaddr)
+{
+	struct ethtool_shaper_params sp;
+	int rc;
+
+	if (!dev->ethtool_ops->get_shaper_param)
+		return -EOPNOTSUPP;
+
+	memset(&sp, 0, sizeof (sp));
+	rc = dev->ethtool_ops->get_shaper_param(dev, &sp);
+	if (rc)
+		return rc;
+
+	if (copy_to_user(uaddr, &sp, sizeof (sp)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int ethtool_set_shaper_params(struct net_device *dev, void __user *uaddr)
+{
+	struct ethtool_shaper_params sp;
+
+	if (!dev->ethtool_ops->set_shaper_param)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&sp, uaddr, sizeof (sp)))
+		return -EFAULT;
+
+	return dev->ethtool_ops->set_shaper_param(dev, &sp);
+}
+
+static int ethtool_get_eponparam(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_epon_param eponparam = { .cmd = ETHTOOL_GEPON_PARAM };
+	int rc;
+
+	if (!dev->ethtool_ops->get_epon_param)
+		return -EOPNOTSUPP;
+
+	rc = dev->ethtool_ops->get_epon_param(dev, &eponparam);
+	if (rc)
+		return rc;
+
+	if (copy_to_user(useraddr, &eponparam, sizeof(eponparam)))
+		return -EFAULT;
+	return 0;
+}
+
+static int ethtool_set_eponparam(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_epon_param eponparam;
+
+	if (!dev->ethtool_ops->set_epon_param)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&eponparam, useraddr, sizeof(eponparam)))
+		return -EFAULT;
+
+	return dev->ethtool_ops->set_epon_param(dev, &eponparam);
+}
+
+#ifdef CONFIG_PHYLINK
+static int ethtool_get_phylink_iftype(struct net_device *dev, void __user *uaddr)
+{
+	struct ethtool_phylink_iftype sp;
+	phy_interface_t interface;
+	struct phylink *pl;
+	int mode, an_enable;
+
+	if (!dev->ethtool_ops->get_phylink)
+		return -EOPNOTSUPP;
+
+	pl = dev->ethtool_ops->get_phylink(dev);
+	if (!pl)
+		return -EIO;
+
+	memset(&sp, 0, sizeof (sp));
+	phylink_get_interface(pl, &interface, &an_enable, &mode);
+	strlcpy(sp.iftype, phy_modes(interface), sizeof (sp.iftype));
+	sp.autoneg_en = an_enable;
+	sp.mode = mode;
+
+	if (copy_to_user(uaddr, &sp, sizeof (sp)))
+		return -EFAULT;
+
+	return 0;
+}
+#else
+static inline int ethtool_get_phylink_iftype(struct net_device *dev, void __user *uaddr)
+{
+	return -ENOTSUPP;
+}
+#endif
+
+#ifdef CONFIG_PHYLINK
+static int ethtool_set_phylink_iftype(struct net_device *dev, void __user *uaddr)
+{
+	struct ethtool_phylink_iftype sp;
+	phy_interface_t i;
+	struct phylink *pl;
+
+	if (copy_from_user(&sp, uaddr, sizeof (sp)))
+		return -EFAULT;
+
+	if (!dev->ethtool_ops->get_phylink)
+		return -EOPNOTSUPP;
+
+	pl = dev->ethtool_ops->get_phylink(dev);
+	if (!pl)
+		return -EIO;
+
+	sp.iftype[sizeof (sp.iftype) - 1] = 0;
+
+	for (i = PHY_INTERFACE_MODE_NA; i < PHY_INTERFACE_MODE_MAX; i++) {
+		if (!strcmp(phy_modes(i), sp.iftype))
+			break;
+	}
+
+	if (i == PHY_INTERFACE_MODE_MAX)
+		return -EINVAL;
+
+	return phylink_set_interface(pl, i, sp.autoneg_en ? 1 : 0);
+}
+#else
+static inline int ethtool_set_phylink_iftype(struct net_device *dev, void __user *uaddr)
+{
+	return -ENOTSUPP;
+}
+#endif
+
 /* The main entry point in this file.  Called from net/core/dev_ioctl.c */
 
 static int
@@ -3036,6 +3200,33 @@
 	case ETHTOOL_SFECPARAM:
 		rc = ethtool_set_fecparam(dev, useraddr);
 		break;
+	case ETHTOOL_SSHAPER_PARAMS:
+		rc = ethtool_set_shaper_params(dev, useraddr);
+		break;
+	case ETHTOOL_GSHAPER_PARAMS:
+		rc = ethtool_get_shaper_params(dev, useraddr);
+		break;
+	case ETHTOOL_GEPON_PARAM:
+		rc = ethtool_get_eponparam(dev, useraddr);
+		break;
+	case ETHTOOL_SEPON_KEYS:
+	case ETHTOOL_SEPON_ENCRYPT:
+	case ETHTOOL_SEPON_RESTART:
+	case ETHTOOL_SEPON_BURST:
+	case ETHTOOL_SEPON_ADD_MCLLID:
+	case ETHTOOL_SEPON_DEL_MCLLID:
+	case ETHTOOL_SEPON_CLR_MCLLID:
+		rc = ethtool_set_eponparam(dev, useraddr);
+		break;
+	case ETHTOOL_GSFP_STATE:
+		rc = ethtool_get_sfp_state(dev, useraddr);
+		break;
+	case ETHTOOL_GPHYLINK_IFTYPE:
+		rc = ethtool_get_phylink_iftype(dev, useraddr);
+		break;
+	case ETHTOOL_SPHYLINK_IFTYPE:
+		rc = ethtool_set_phylink_iftype(dev, useraddr);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}
diff -ruw linux-6.4/net/ethtool/strset.c linux-6.4-fbx/net/ethtool/strset.c
--- linux-6.4/net/ethtool/strset.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ethtool/strset.c	2023-11-29 17:07:14.131662189 +0100
@@ -105,6 +105,12 @@
 		.count		= __ETHTOOL_A_STATS_RMON_CNT,
 		.strings	= stats_rmon_names,
 	},
+	[ETH_SS_PHYLINK_IFTYPES] = {
+		/* not implemented in netlink codepath */
+		.per_dev	= false,
+		.count		= 0,
+		.strings	= NULL,
+	},
 };
 
 struct strset_req_info {
diff -ruw linux-6.4/net/ipv4/Makefile linux-6.4-fbx/net/ipv4/Makefile
--- linux-6.4/net/ipv4/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/Makefile	2023-11-29 17:07:14.138328866 +0100
@@ -20,6 +20,8 @@
 
 obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o
 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
+
+obj-$(CONFIG_IP_FFN) += ip_ffn.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
diff -ruw linux-6.4/net/ipv4/af_inet.c linux-6.4-fbx/net/ipv4/af_inet.c
--- linux-6.4/net/ipv4/af_inet.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/af_inet.c	2023-11-29 17:07:14.138328866 +0100
@@ -100,6 +100,7 @@
 #include <net/ip_fib.h>
 #include <net/inet_connection_sock.h>
 #include <net/gro.h>
+#include <net/gso.h>
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/udplite.h>
diff -ruw linux-6.4/net/ipv4/gre_offload.c linux-6.4-fbx/net/ipv4/gre_offload.c
--- linux-6.4/net/ipv4/gre_offload.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/gre_offload.c	2023-11-29 17:07:14.141662205 +0100
@@ -11,6 +11,7 @@
 #include <net/protocol.h>
 #include <net/gre.h>
 #include <net/gro.h>
+#include <net/gso.h>
 
 static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 				       netdev_features_t features)
diff -ruw linux-6.4/net/ipv4/ip_input.c linux-6.4-fbx/net/ipv4/ip_input.c
--- linux-6.4/net/ipv4/ip_input.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/ip_input.c	2023-11-29 17:07:14.148328882 +0100
@@ -224,8 +224,12 @@
 	}
 }
 
-static int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
+int ip_local_deliver_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FORWARDABLE)
+		ip_ffn_add(skb, IP_FFN_LOCAL_IN);
+#endif
 	skb_clear_delivery_time(skb);
 	__skb_pull(skb, skb_network_header_len(skb));
 
@@ -566,6 +570,11 @@
 	if (skb == NULL)
 		return NET_RX_DROP;
 
+#ifdef CONFIG_IP_FFN
+	if (!ip_ffn_process(skb))
+		return NET_RX_SUCCESS;
+#endif
+
 	return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
 		       net, NULL, skb, dev, NULL,
 		       ip_rcv_finish);
diff -ruw linux-6.4/net/ipv4/ip_output.c linux-6.4-fbx/net/ipv4/ip_output.c
--- linux-6.4/net/ipv4/ip_output.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/ip_output.c	2023-11-29 17:07:14.148328882 +0100
@@ -73,6 +73,7 @@
 #include <net/arp.h>
 #include <net/icmp.h>
 #include <net/checksum.h>
+#include <net/gso.h>
 #include <net/inetpeer.h>
 #include <net/inet_ecn.h>
 #include <net/lwtunnel.h>
@@ -219,6 +220,11 @@
 			return res;
 	}
 
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FORWARDABLE)
+		ip_ffn_add(skb, IP_FFN_FINISH_OUT);
+#endif
+
 	rcu_read_lock();
 	neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
 	if (!IS_ERR(neigh)) {
@@ -428,6 +434,11 @@
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
 
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FAST_FORWARDED)
+		return ip_finish_output(net, sk, skb);
+#endif
+
 	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
 			    net, sk, skb, indev, dev,
 			    ip_finish_output,
@@ -1769,4 +1780,7 @@
 #if defined(CONFIG_IP_MULTICAST)
 	igmp_mc_init();
 #endif
+#ifdef CONFIG_IP_FFN
+	ip_ffn_init();
+#endif
 }
diff -ruw linux-6.4/net/ipv4/ip_tunnel_core.c linux-6.4-fbx/net/ipv4/ip_tunnel_core.c
--- linux-6.4/net/ipv4/ip_tunnel_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/ip_tunnel_core.c	2023-11-29 17:07:14.148328882 +0100
@@ -38,6 +38,9 @@
 #include <net/geneve.h>
 #include <net/vxlan.h>
 #include <net/erspan.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack.h>
+#endif
 
 const struct ip_tunnel_encap_ops __rcu *
 		iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
@@ -60,6 +63,11 @@
 	skb_scrub_packet(skb, xnet);
 
 	skb_clear_hash_if_not_l4(skb);
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+	if (proto == IPPROTO_IPV6)
+		nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+#endif
+
 	skb_dst_set(skb, &rt->dst);
 	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
diff -ruw linux-6.4/net/ipv4/ipconfig.c linux-6.4-fbx/net/ipv4/ipconfig.c
--- linux-6.4/net/ipv4/ipconfig.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/ipconfig.c	2023-11-29 17:07:14.148328882 +0100
@@ -197,16 +197,62 @@
 static struct ic_device *ic_first_dev __initdata;	/* List of open device */
 static struct ic_device *ic_dev __initdata;		/* Selected device */
 
-static bool __init ic_is_init_dev(struct net_device *dev)
+static bool __init ic_is_init_dev(struct net_device *dev, bool partial)
 {
+	char *p = NULL;
+	bool ret;
+
 	if (dev->flags & IFF_LOOPBACK)
 		return false;
-	return user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
+
+	if (partial) {
+		p = strchr(user_dev_name, '.');
+		if (p)
+			*p = 0;
+	}
+
+	ret = false;
+	if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
 	    (!(dev->flags & IFF_LOOPBACK) &&
 	     (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
-	     strncmp(dev->name, "dummy", 5));
+	     strncmp(dev->name, "dummy", 5)))
+		ret = true;
+	if (p)
+		*p = '.';
+	return ret;
 }
 
+#ifdef CONFIG_VLAN_8021Q
+int register_vlan_device(struct net_device *real_dev, u16 vlan_id);
+
+static void __init prepare_vlan(void)
+{
+	unsigned short oflags;
+	struct net_device *dev;
+	char *p;
+	u16 vid;
+
+	if (!strchr(user_dev_name, '.'))
+		return;
+
+	p = strchr(user_dev_name, '.');
+	*p = 0;
+	vid = simple_strtoul(p + 1, NULL, 10);
+	dev = __dev_get_by_name(&init_net, user_dev_name);
+	if (!dev)
+		goto fail;
+
+	oflags = dev->flags;
+	if (dev_change_flags(dev, oflags | IFF_UP, NULL) < 0)
+		goto fail;
+
+	register_vlan_device(dev, vid);
+
+fail:
+	*p = '.';
+}
+#endif
+
 static int __init ic_open_devs(void)
 {
 	struct ic_device *d, **last;
@@ -225,8 +271,13 @@
 			pr_err("IP-Config: Failed to open %s\n", dev->name);
 	}
 
+#ifdef CONFIG_VLAN_8021Q
+	/* register vlan device if needed */
+	prepare_vlan();
+#endif
+
 	for_each_netdev(&init_net, dev) {
-		if (ic_is_init_dev(dev)) {
+		if (ic_is_init_dev(dev, false)) {
 			int able = 0;
 			if (dev->mtu >= 364)
 				able |= IC_BOOTP;
@@ -281,7 +332,7 @@
 
 		rtnl_lock();
 		for_each_netdev(&init_net, dev)
-			if (ic_is_init_dev(dev) && netif_carrier_ok(dev)) {
+			if (ic_is_init_dev(dev, false) && netif_carrier_ok(dev)) {
 				rtnl_unlock();
 				goto have_carrier;
 			}
@@ -729,8 +780,10 @@
 			e += len;
 		}
 		if (*vendor_class_identifier) {
+#ifdef IPCONFIG_DEBUG
 			pr_info("DHCP: sending class identifier \"%s\"\n",
 				vendor_class_identifier);
+#endif
 			*e++ = 60;	/* Class-identifier */
 			len = strlen(vendor_class_identifier);
 			*e++ = len;
@@ -1445,7 +1498,7 @@
 
 		rtnl_lock();
 		for_each_netdev(&init_net, dev) {
-			if (ic_is_init_dev(dev)) {
+			if (ic_is_init_dev(dev, true)) {
 				found = 1;
 				break;
 			}
diff -ruw linux-6.4/net/ipv4/netfilter/Kconfig linux-6.4-fbx/net/ipv4/netfilter/Kconfig
--- linux-6.4/net/ipv4/netfilter/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/netfilter/Kconfig	2023-11-29 17:07:14.151662220 +0100
@@ -6,6 +6,13 @@
 menu "IP: Netfilter Configuration"
 	depends on INET && NETFILTER
 
+config IP_FFN
+	bool "IP: Fast forwarding and NAT"
+
+config IP_FFN_PROCFS
+	bool "IP: Fast forwarding and NAT /proc/net entries"
+	depends on IP_FFN
+
 config NF_DEFRAG_IPV4
 	tristate
 	default n
diff -ruw linux-6.4/net/ipv4/netfilter/ip_tables.c linux-6.4-fbx/net/ipv4/netfilter/ip_tables.c
--- linux-6.4/net/ipv4/netfilter/ip_tables.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/netfilter/ip_tables.c	2023-11-29 17:07:14.151662220 +0100
@@ -1099,6 +1099,8 @@
 	return ret;
 }
 
+extern void fbxbr_flush_cache(void);
+
 static int
 do_replace(struct net *net, sockptr_t arg, unsigned int len)
 {
@@ -1138,6 +1140,14 @@
 			   tmp.num_counters, tmp.counters);
 	if (ret)
 		goto free_newinfo_untrans;
+
+#ifdef CONFIG_FBXBRIDGE
+	fbxbr_flush_cache();
+#endif
+
+#ifdef CONFIG_IP_FFN
+	ip_ffn_flush_all();
+#endif
 	return 0;
 
  free_newinfo_untrans:
diff -ruw linux-6.4/net/ipv4/tcp.c linux-6.4-fbx/net/ipv4/tcp.c
--- linux-6.4/net/ipv4/tcp.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/tcp.c	2023-11-29 17:07:14.158328897 +0100
@@ -3599,6 +3599,13 @@
 			err = -EINVAL;
 		break;
 
+	case TCP_LINEAR_RTO:
+		if (val < 0 || val > 1)
+			err = -EINVAL;
+		else
+			tp->linear_rto = val;
+		break;
+
 	case TCP_REPAIR:
 		if (!tcp_can_repair_sock(sk))
 			err = -EPERM;
@@ -4203,6 +4210,9 @@
 	case TCP_THIN_DUPACK:
 		val = 0;
 		break;
+	case TCP_LINEAR_RTO:
+		val = tp->linear_rto;
+		break;
 
 	case TCP_REPAIR:
 		val = tp->repair;
diff -ruw linux-6.4/net/ipv4/tcp_offload.c linux-6.4-fbx/net/ipv4/tcp_offload.c
--- linux-6.4/net/ipv4/tcp_offload.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/tcp_offload.c	2023-11-29 17:07:14.164995574 +0100
@@ -9,6 +9,7 @@
 #include <linux/indirect_call_wrapper.h>
 #include <linux/skbuff.h>
 #include <net/gro.h>
+#include <net/gso.h>
 #include <net/tcp.h>
 #include <net/protocol.h>
 
diff -ruw linux-6.4/net/ipv4/tcp_timer.c linux-6.4-fbx/net/ipv4/tcp_timer.c
--- linux-6.4/net/ipv4/tcp_timer.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/tcp_timer.c	2023-11-29 17:07:14.168328913 +0100
@@ -587,6 +587,10 @@
 	    icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) {
 		icsk->icsk_backoff = 0;
 		icsk->icsk_rto = min(__tcp_set_rto(tp), TCP_RTO_MAX);
+
+	} else if (sk->sk_state == TCP_ESTABLISHED && tp->linear_rto) {
+		icsk->icsk_backoff = 0;
+		icsk->icsk_rto = min(__tcp_set_rto(tp), TCP_RTO_MAX);
 	} else {
 		/* Use normal (exponential) backoff */
 		icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
diff -ruw linux-6.4/net/ipv4/udp.c linux-6.4-fbx/net/ipv4/udp.c
--- linux-6.4/net/ipv4/udp.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/udp.c	2023-11-29 17:07:14.168328913 +0100
@@ -103,6 +103,7 @@
 #include <net/ip_tunnels.h>
 #include <net/route.h>
 #include <net/checksum.h>
+#include <net/gso.h>
 #include <net/xfrm.h>
 #include <trace/events/udp.h>
 #include <linux/static_key.h>
@@ -315,6 +316,49 @@
 	inet_sk(sk)->inet_num = snum;
 	udp_sk(sk)->udp_port_hash = snum;
 	udp_sk(sk)->udp_portaddr_hash ^= snum;
+
+	/* resolve udp reuse conflict */
+	if (sk->sk_reuse) {
+		struct sock *sk2;
+		bool found;
+
+		found = false;
+		sk_for_each(sk2, &hslot->head) {
+			if (!net_eq(sock_net(sk2), net) ||
+			    sk2 == sk ||
+			    (udp_sk(sk2)->udp_port_hash != snum))
+				continue;
+
+			if (sk2->sk_bound_dev_if &&
+			    sk->sk_bound_dev_if &&
+			    sk2->sk_bound_dev_if != sk->sk_bound_dev_if)
+				continue;
+
+			if (!inet_rcv_saddr_equal(sk, sk2, true))
+				continue;
+
+			found = true;
+			break;
+		}
+
+		sk_for_each(sk2, &hslot->head) {
+			if (!net_eq(sock_net(sk2), net) ||
+			    sk2 == sk ||
+			    (udp_sk(sk2)->udp_port_hash != snum))
+				continue;
+
+			if (sk2->sk_bound_dev_if &&
+			    sk->sk_bound_dev_if &&
+			    sk2->sk_bound_dev_if != sk->sk_bound_dev_if)
+				continue;
+
+			if (!inet_rcv_saddr_equal(sk, sk2, true))
+				continue;
+
+			sk->sk_reuse_conflict = found;
+		}
+	}
+
 	if (sk_unhashed(sk)) {
 		if (sk->sk_reuseport &&
 		    udp_reuseport_add_sock(sk, hslot)) {
@@ -2342,6 +2386,90 @@
 	return 0;
 }
 
+/*
+ *	Unicast goes to one listener and all sockets with dup flag
+ *
+ *	Note: called only from the BH handler context.
+ *
+ *	Note2: it is okay to use the udp_table.hash table only here
+ *	and not udp_table.hash2 table as the sock is always hashed in
+ *	both udp_table.hash and udp_table.hash2. This might impact
+ *	performance if the sock hash bucket hosts more than 10 socks
+ *	but has the benefit of keeping the code simplier.
+ *
+ *	Note3: __udp_is_mcast_sock() does not have really anything to
+ *	do with multicast, it used there to deliver the packet only to
+ *	the sockets that are bound to the ip:port/interface the skbuff
+ *	is targeted to.
+ */
+static int __udp4_lib_uc_conflict_deliver(struct net *net, struct sk_buff *skb,
+					  struct udphdr  *uh,
+					  __be32 saddr, __be32 daddr,
+					  struct udp_table *udptable,
+					  int proto)
+{
+	struct sock *sk, *first = NULL;
+	unsigned short hnum = ntohs(uh->dest);
+	struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
+	int dif = skb->dev->ifindex;
+	unsigned int offset = offsetof(typeof(*sk), sk_node);
+	struct hlist_node *node;
+	struct sk_buff *nskb;
+	int sdif = inet_sdif(skb);
+	bool found_non_dup;
+
+	found_non_dup = false;
+	sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) {
+		bool need_deliver;
+
+		if (!__udp_is_mcast_sock(net, sk, uh->dest, daddr,
+					 uh->source, saddr, dif, sdif, hnum))
+			continue;
+
+		if (sock_flag(sk, SOCK_UDP_DUP_UNICAST))
+			need_deliver = true;
+		else {
+			if (!found_non_dup)
+				need_deliver = true;
+			else
+				need_deliver = false;
+			found_non_dup = true;
+		}
+
+		if (!need_deliver)
+			continue;
+
+		if (!first) {
+			first = sk;
+			continue;
+		}
+		nskb = skb_clone(skb, GFP_ATOMIC);
+
+		if (unlikely(!nskb)) {
+			atomic_inc(&sk->sk_drops);
+			__UDP_INC_STATS(net, UDP_MIB_RCVBUFERRORS,
+					IS_UDPLITE(sk));
+			__UDP_INC_STATS(net, UDP_MIB_INERRORS,
+					IS_UDPLITE(sk));
+			continue;
+		}
+
+		if (udp_queue_rcv_skb(sk, nskb) > 0)
+			consume_skb(nskb);
+	}
+
+	if (first) {
+		if (udp_queue_rcv_skb(first, skb) > 0)
+			consume_skb(skb);
+	} else {
+		kfree_skb(skb);
+		__UDP_INC_STATS(net, UDP_MIB_IGNOREDMULTI,
+				proto == IPPROTO_UDPLITE);
+	}
+
+	return 0;
+}
+
 /* Initialize UDP checksum. If exited with zero value (success),
  * CHECKSUM_UNNECESSARY means, that no more checks are required.
  * Otherwise, csum completion requires checksumming packet body,
@@ -2471,9 +2599,15 @@
 						saddr, daddr, udptable, proto);
 
 	sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
-	if (sk)
-		return udp_unicast_rcv_skb(sk, skb, uh);
+	if (sk) {
+		if (sk->sk_reuse_conflict)
+			return __udp4_lib_uc_conflict_deliver(net,
+							      skb, uh,
+							      saddr, daddr,
+							      udptable, proto);
 
+		return udp_unicast_rcv_skb(sk, skb, uh);
+	}
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto drop;
 	nf_reset_ct(skb);
diff -ruw linux-6.4/net/ipv4/udp_offload.c linux-6.4-fbx/net/ipv4/udp_offload.c
--- linux-6.4/net/ipv4/udp_offload.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv4/udp_offload.c	2023-11-29 17:07:14.168328913 +0100
@@ -8,6 +8,7 @@
 
 #include <linux/skbuff.h>
 #include <net/gro.h>
+#include <net/gso.h>
 #include <net/udp.h>
 #include <net/protocol.h>
 #include <net/inet_common.h>
diff -ruw linux-6.4/net/ipv6/Makefile linux-6.4-fbx/net/ipv6/Makefile
--- linux-6.4/net/ipv6/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/Makefile	2023-11-29 17:07:14.168328913 +0100
@@ -13,6 +13,7 @@
 		udp_offload.o seg6.o fib6_notifier.o rpl.o ioam6.o
 
 ipv6-$(CONFIG_SYSCTL) += sysctl_net_ipv6.o
+ipv6-$(CONFIG_IPV6_FFN) += ip6_ffn.o
 ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
 
 ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
diff -ruw linux-6.4/net/ipv6/addrconf.c linux-6.4-fbx/net/ipv6/addrconf.c
--- linux-6.4/net/ipv6/addrconf.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/addrconf.c	2023-11-29 17:07:14.171662251 +0100
@@ -2310,12 +2310,27 @@
 	return 0;
 }
 
+static int addrconf_ifid_ppp(u8 *eui, struct net_device *dev)
+{
+	if (is_zero_ether_addr(dev->perm_addr))
+		return -1;
+
+	memcpy(eui, dev->perm_addr, 3);
+	memcpy(eui + 5, dev->perm_addr + 3, 3);
+	eui[3] = 0xFF;
+	eui[4] = 0xFE;
+	eui[0] ^= 2;
+	return 0;
+}
+
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
 	switch (dev->type) {
 	case ARPHRD_ETHER:
 	case ARPHRD_FDDI:
 		return addrconf_ifid_eui48(eui, dev);
+	case ARPHRD_PPP:
+		return addrconf_ifid_ppp(eui, dev);
 	case ARPHRD_ARCNET:
 		return addrconf_ifid_arcnet(eui, dev);
 	case ARPHRD_INFINIBAND:
@@ -3363,6 +3378,7 @@
 
 	if ((dev->type != ARPHRD_ETHER) &&
 	    (dev->type != ARPHRD_FDDI) &&
+	    (dev->type != ARPHRD_PPP) &&
 	    (dev->type != ARPHRD_ARCNET) &&
 	    (dev->type != ARPHRD_INFINIBAND) &&
 	    (dev->type != ARPHRD_IEEE1394) &&
diff -ruw linux-6.4/net/ipv6/af_inet6.c linux-6.4-fbx/net/ipv6/af_inet6.c
--- linux-6.4/net/ipv6/af_inet6.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/af_inet6.c	2023-11-29 17:07:14.171662251 +0100
@@ -1180,6 +1180,10 @@
 	if (err)
 		goto udpv6_fail;
 
+#ifdef CONFIG_IPV6_FFN
+	ipv6_ffn_init();
+#endif
+
 	err = udplitev6_init();
 	if (err)
 		goto udplitev6_fail;
diff -ruw linux-6.4/net/ipv6/ip6_input.c linux-6.4-fbx/net/ipv6/ip6_input.c
--- linux-6.4/net/ipv6/ip6_input.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/ip6_input.c	2023-11-29 17:07:14.178328928 +0100
@@ -306,6 +306,12 @@
 	skb = ip6_rcv_core(skb, dev, net);
 	if (skb == NULL)
 		return NET_RX_DROP;
+
+#ifdef CONFIG_IPV6_FFN
+	if (!ipv6_ffn_process(skb))
+		return NET_RX_SUCCESS;
+#endif
+
 	return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
 		       net, NULL, skb, dev, NULL,
 		       ip6_rcv_finish);
@@ -475,8 +481,13 @@
 	kfree_skb_reason(skb, reason);
 }
 
-static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
+int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+#ifdef CONFIG_IPV6_FFN
+	if (skb->ffn_state == FFN_STATE_FORWARDABLE)
+		ipv6_ffn_add(skb, IPV6_FFN_LOCAL_IN);
+#endif
+
 	skb_clear_delivery_time(skb);
 	rcu_read_lock();
 	ip6_protocol_deliver_rcu(net, skb, 0, false);
diff -ruw linux-6.4/net/ipv6/ip6_offload.c linux-6.4-fbx/net/ipv6/ip6_offload.c
--- linux-6.4/net/ipv6/ip6_offload.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/ip6_offload.c	2023-11-29 17:07:14.178328928 +0100
@@ -16,6 +16,7 @@
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/gro.h>
+#include <net/gso.h>
 
 #include "ip6_offload.h"
 
diff -ruw linux-6.4/net/ipv6/ip6_output.c linux-6.4-fbx/net/ipv6/ip6_output.c
--- linux-6.4/net/ipv6/ip6_output.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/ip6_output.c	2023-11-29 17:07:14.178328928 +0100
@@ -42,6 +42,7 @@
 #include <net/sock.h>
 #include <net/snmp.h>
 
+#include <net/gso.h>
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 #include <net/protocol.h>
@@ -51,6 +52,7 @@
 #include <net/icmp.h>
 #include <net/xfrm.h>
 #include <net/checksum.h>
+#include <net/dsfield.h>
 #include <linux/mroute6.h>
 #include <net/l3mdev.h>
 #include <net/lwtunnel.h>
@@ -116,6 +118,11 @@
 			return res;
 	}
 
+#ifdef CONFIG_IPV6_FFN
+	if (skb->ffn_state == FFN_STATE_FORWARDABLE)
+		ipv6_ffn_add(skb, IPV6_FFN_FINISH_OUT);
+#endif
+
 	rcu_read_lock();
 	nexthop = rt6_nexthop((struct rt6_info *)dst, daddr);
 	neigh = __ipv6_neigh_lookup_noref(dev, nexthop);
@@ -224,6 +231,11 @@
 		return 0;
 	}
 
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FAST_FORWARDED)
+		return ip6_finish_output(net, sk, skb);
+#endif
+
 	return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
 			    net, sk, skb, indev, dev,
 			    ip6_finish_output,
@@ -646,6 +658,8 @@
 
 	hdr->hop_limit--;
 
+	skb->priority = rt_tos2priority(ipv6_get_dsfield(hdr));
+
 	return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
 		       net, NULL, skb, skb->dev, dst->dev,
 		       ip6_forward_finish);
diff -ruw linux-6.4/net/ipv6/netfilter/Kconfig linux-6.4-fbx/net/ipv6/netfilter/Kconfig
--- linux-6.4/net/ipv6/netfilter/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/netfilter/Kconfig	2023-11-29 17:07:14.181662267 +0100
@@ -6,6 +6,13 @@
 menu "IPv6: Netfilter Configuration"
 	depends on INET && IPV6 && NETFILTER
 
+config IPV6_FFN
+	bool "IPv6: Fast forwarding and NAT"
+
+config IPV6_FFN_PROCFS
+	bool "IPv6: Fast forwarding and NAT /proc/net entries"
+	depends on IPV6_FFN
+
 config NF_SOCKET_IPV6
 	tristate "IPv6 socket lookup support"
 	help
diff -ruw linux-6.4/net/ipv6/netfilter/ip6_tables.c linux-6.4-fbx/net/ipv6/netfilter/ip6_tables.c
--- linux-6.4/net/ipv6/netfilter/ip6_tables.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/netfilter/ip6_tables.c	2023-11-29 17:07:14.181662267 +0100
@@ -1155,6 +1155,10 @@
 			   tmp.num_counters, tmp.counters);
 	if (ret)
 		goto free_newinfo_untrans;
+
+#ifdef CONFIG_IPV6_FFN
+	ipv6_ffn_flush_all();
+#endif
 	return 0;
 
  free_newinfo_untrans:
diff -ruw linux-6.4/net/ipv6/udp.c linux-6.4-fbx/net/ipv6/udp.c
--- linux-6.4/net/ipv6/udp.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/udp.c	2023-11-29 17:07:14.188328944 +0100
@@ -844,6 +844,82 @@
  * Note: called only from the BH handler context,
  * so we don't need to lock the hashes.
  */
+static int __udp6_lib_uc_conflict_deliver(struct net *net, struct sk_buff *skb,
+		const struct in6_addr *saddr, const struct in6_addr *daddr,
+		struct udp_table *udptable, int proto)
+{
+	struct sock *sk, *first = NULL;
+	const struct udphdr *uh = udp_hdr(skb);
+	unsigned short hnum = ntohs(uh->dest);
+	struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
+	unsigned int offset = offsetof(typeof(*sk), sk_node);
+	int dif = inet6_iif(skb);
+	int sdif = inet6_sdif(skb);
+	struct hlist_node *node;
+	struct sk_buff *nskb;
+	bool found_non_dup;
+
+	found_non_dup = false;
+	sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) {
+		bool need_deliver;
+
+		if (!__udp_v6_is_mcast_sock(net, sk, uh->dest, daddr,
+					    uh->source, saddr, dif, sdif, hnum))
+
+			continue;
+
+		/* If zero checksum and no_check is not on for
+		 * the socket then skip it.
+		 */
+		if (!uh->check && !udp_sk(sk)->no_check6_rx)
+			continue;
+
+		if (sock_flag(sk, SOCK_UDP_DUP_UNICAST))
+			need_deliver = true;
+		else {
+			if (!found_non_dup)
+				need_deliver = true;
+			else
+				need_deliver = false;
+			found_non_dup = true;
+		}
+
+		if (!need_deliver)
+			continue;
+
+		if (!first) {
+			first = sk;
+			continue;
+		}
+		nskb = skb_clone(skb, GFP_ATOMIC);
+		if (unlikely(!nskb)) {
+			atomic_inc(&sk->sk_drops);
+			__UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS,
+					 IS_UDPLITE(sk));
+			__UDP6_INC_STATS(net, UDP_MIB_INERRORS,
+					 IS_UDPLITE(sk));
+			continue;
+		}
+
+		if (udpv6_queue_rcv_skb(sk, nskb) > 0)
+			consume_skb(nskb);
+	}
+
+	if (first) {
+		if (udpv6_queue_rcv_skb(first, skb) > 0)
+			consume_skb(skb);
+	} else {
+		kfree_skb(skb);
+		__UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI,
+				 proto == IPPROTO_UDPLITE);
+	}
+	return 0;
+}
+
+/*
+ * Note: called only from the BH handler context,
+ * so we don't need to lock the hashes.
+ */
 static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
 		const struct in6_addr *saddr, const struct in6_addr *daddr,
 		struct udp_table *udptable, int proto)
@@ -1018,6 +1094,12 @@
 	if (sk) {
 		if (!uh->check && !udp_sk(sk)->no_check6_rx)
 			goto report_csum_error;
+
+		if (sk->sk_reuse_conflict)
+			return __udp6_lib_uc_conflict_deliver(net, skb,
+						      saddr, daddr,
+						      udptable, proto);
+
 		return udp6_unicast_rcv_skb(sk, skb, uh);
 	}
 
diff -ruw linux-6.4/net/ipv6/udp_offload.c linux-6.4-fbx/net/ipv6/udp_offload.c
--- linux-6.4/net/ipv6/udp_offload.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/ipv6/udp_offload.c	2023-11-29 17:07:14.188328944 +0100
@@ -14,6 +14,7 @@
 #include <net/ip6_checksum.h>
 #include "ip6_offload.h"
 #include <net/gro.h>
+#include <net/gso.h>
 
 static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 					 netdev_features_t features)
diff -ruw linux-6.4/net/mac80211/Kconfig linux-6.4-fbx/net/mac80211/Kconfig
--- linux-6.4/net/mac80211/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/mac80211/Kconfig	2024-01-12 13:49:05.013369080 +0100
@@ -57,6 +57,17 @@
 comment "Some wireless drivers require a rate control algorithm"
 	depends on MAC80211 && MAC80211_HAS_RC=n
 
+config MAC80211_KUNIT_TEST
+	tristate "KUnit tests for mac80211" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	depends on MAC80211
+	default KUNIT_ALL_TESTS
+	depends on !KERNEL_6_2
+	help
+	  Enable this option to test mac80211 internals with kunit.
+
+	  If unsure, say N.
+
 config MAC80211_MESH
 	bool "Enable mac80211 mesh networking support"
 	depends on MAC80211
@@ -304,3 +315,9 @@
 	  connect more stations than the number selected here.)
 
 	  If unsure, leave the default of 0.
+
+config FBX80211_SCUM
+	bool "Same channel unassociated metrics"
+	depends on FBX80211
+	help
+	  Support for unassociated STA metrics
diff -ruw linux-6.4/net/mac80211/Makefile linux-6.4-fbx/net/mac80211/Makefile
--- linux-6.4/net/mac80211/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/mac80211/Makefile	2024-01-12 13:49:05.013369080 +0100
@@ -36,7 +36,8 @@
 	tdls.o \
 	ocb.o \
 	airtime.o \
-	eht.o
+	eht.o \
+	nmeshd_nl.o
 
 mac80211-$(CONFIG_MAC80211_LEDS) += led.o
 mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
@@ -54,6 +55,7 @@
 	mesh_ps.o
 
 mac80211-$(CONFIG_PM) += pm.o
+mac80211-$(CONFIG_FBX80211_SCUM) += fbx_scum.o
 
 CFLAGS_trace.o := -I$(src)
 
@@ -65,4 +67,6 @@
 
 mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
 
+obj-y += tests/
+
 ccflags-y += -DDEBUG
diff -ruw linux-6.4/net/netfilter/Kconfig linux-6.4-fbx/net/netfilter/Kconfig
--- linux-6.4/net/netfilter/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/Kconfig	2023-11-29 17:07:14.224995667 +0100
@@ -364,6 +364,7 @@
 config NF_CONNTRACK_SIP
 	tristate "SIP protocol support"
 	default m if NETFILTER_ADVANCED=n
+	select CRYPTO_LIB_SHA256
 	help
 	  SIP is an application-layer control protocol that can establish,
 	  modify, and terminate multimedia sessions (conferences) such as
diff -ruw linux-6.4/net/netfilter/nf_conntrack_core.c linux-6.4-fbx/net/netfilter/nf_conntrack_core.c
--- linux-6.4/net/netfilter/nf_conntrack_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_conntrack_core.c	2023-11-29 17:07:14.234995683 +0100
@@ -577,12 +577,29 @@
 #endif
 }
 
+#ifdef CONFIG_IP_FFN
+extern void ip_ffn_ct_destroy(struct nf_conn *ct);
+#endif
+
+#ifdef CONFIG_IPV6_FFN
+extern void ipv6_ffn_ct_destroy(struct nf_conn *ct);
+#endif
+
 void nf_ct_destroy(struct nf_conntrack *nfct)
 {
 	struct nf_conn *ct = (struct nf_conn *)nfct;
 
 	WARN_ON(refcount_read(&nfct->use) != 0);
 
+#ifdef CONFIG_IP_FFN
+	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == AF_INET)
+		ip_ffn_ct_destroy(ct);
+#endif
+#ifdef CONFIG_IPV6_FFN
+	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == AF_INET6)
+		ipv6_ffn_ct_destroy(ct);
+#endif
+
 	if (unlikely(nf_ct_is_template(ct))) {
 		nf_ct_tmpl_free(ct);
 		return;
@@ -1784,7 +1801,7 @@
 		}
 		spin_unlock_bh(&nf_conntrack_expect_lock);
 	}
-	if (!exp && tmpl)
+	if (!exp)
 		__nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC);
 
 	/* Other CPU might have obtained a pointer to this object before it was
@@ -2063,6 +2080,10 @@
 	ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
 	if (ct->master || (help && !hlist_empty(&help->expectations)))
 		return;
+
+	rcu_read_lock();
+	__nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
+	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
 
@@ -2804,6 +2825,7 @@
 	nf_conntrack_acct_pernet_init(net);
 	nf_conntrack_tstamp_pernet_init(net);
 	nf_conntrack_ecache_pernet_init(net);
+	nf_conntrack_helper_pernet_init(net);
 	nf_conntrack_proto_pernet_init(net);
 
 	return 0;
diff -ruw linux-6.4/net/netfilter/nf_conntrack_helper.c linux-6.4-fbx/net/netfilter/nf_conntrack_helper.c
--- linux-6.4/net/netfilter/nf_conntrack_helper.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_conntrack_helper.c	2023-11-29 17:07:14.238329021 +0100
@@ -37,6 +37,11 @@
 EXPORT_SYMBOL_GPL(nf_ct_helper_hsize);
 static unsigned int nf_ct_helper_count __read_mostly;
 
+static bool nf_ct_auto_assign_helper __read_mostly = true;
+module_param_named(nf_conntrack_helper, nf_ct_auto_assign_helper, bool, 0644);
+MODULE_PARM_DESC(nf_conntrack_helper,
+		 "Enable automatic conntrack helper assignment (default 0)");
+
 static DEFINE_MUTEX(nf_ct_nat_helpers_mutex);
 static struct list_head nf_ct_nat_helpers __read_mostly;
 
@@ -48,6 +53,24 @@
 		(__force __u16)tuple->src.u.all) % nf_ct_helper_hsize;
 }
 
+static struct nf_conntrack_helper *
+__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
+{
+	struct nf_conntrack_helper *helper;
+	struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
+	unsigned int h;
+
+	if (!nf_ct_helper_count)
+		return NULL;
+
+	h = helper_hash(tuple);
+	hlist_for_each_entry_rcu(helper, &nf_ct_helper_hash[h], hnode) {
+		if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask))
+			return helper;
+	}
+	return NULL;
+}
+
 struct nf_conntrack_helper *
 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
 {
@@ -188,11 +211,33 @@
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
 
+static struct nf_conntrack_helper *
+nf_ct_lookup_helper(struct nf_conn *ct, struct net *net)
+{
+	struct nf_conntrack_net *cnet = nf_ct_pernet(net);
+
+	if (!cnet->sysctl_auto_assign_helper) {
+		if (cnet->auto_assign_helper_warned)
+			return NULL;
+		if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple))
+			return NULL;
+		pr_info("nf_conntrack: default automatic helper assignment "
+			"has been turned off for security reasons and CT-based "
+			"firewall rule not found. Use the iptables CT target "
+			"to attach helpers instead.\n");
+		cnet->auto_assign_helper_warned = true;
+		return NULL;
+	}
+
+	return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+}
+
 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
 			      gfp_t flags)
 {
 	struct nf_conntrack_helper *helper = NULL;
 	struct nf_conn_help *help;
+	struct net *net = nf_ct_net(ct);
 
 	/* We already got a helper explicitly attached. The function
 	 * nf_conntrack_alter_reply - in case NAT is in use - asks for looking
@@ -203,22 +248,24 @@
 	if (test_bit(IPS_HELPER_BIT, &ct->status))
 		return 0;
 
-	if (WARN_ON_ONCE(!tmpl))
-		return 0;
-
+	if (tmpl != NULL) {
 	help = nfct_help(tmpl);
 	if (help != NULL) {
 		helper = rcu_dereference(help->helper);
 		set_bit(IPS_HELPER_BIT, &ct->status);
 	}
+	}
 
 	help = nfct_help(ct);
 
 	if (helper == NULL) {
+		helper = nf_ct_lookup_helper(ct, net);
+		if (helper == NULL) {
 		if (help)
 			RCU_INIT_POINTER(help->helper, NULL);
 		return 0;
 	}
+	}
 
 	if (help == NULL) {
 		help = nf_ct_helper_ext_add(ct, flags);
@@ -500,6 +547,19 @@
 }
 EXPORT_SYMBOL_GPL(nf_nat_helper_unregister);
 
+void nf_ct_set_auto_assign_helper_warned(struct net *net)
+{
+	nf_ct_pernet(net)->auto_assign_helper_warned = true;
+}
+EXPORT_SYMBOL_GPL(nf_ct_set_auto_assign_helper_warned);
+
+void nf_conntrack_helper_pernet_init(struct net *net)
+{
+	struct nf_conntrack_net *cnet = nf_ct_pernet(net);
+
+	cnet->sysctl_auto_assign_helper = nf_ct_auto_assign_helper;
+}
+
 int nf_conntrack_helper_init(void)
 {
 	nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
diff -ruw linux-6.4/net/netfilter/nf_conntrack_proto_tcp.c linux-6.4-fbx/net/netfilter/nf_conntrack_proto_tcp.c
--- linux-6.4/net/netfilter/nf_conntrack_proto_tcp.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_conntrack_proto_tcp.c	2023-11-29 17:07:14.241662360 +0100
@@ -1247,6 +1247,7 @@
 		break;
 	}
 
+	if (!ct->proto.tcp.no_window_track) {
 	res = tcp_in_window(ct, dir, index,
 			    skb, dataoff, th, state);
 	switch (res) {
@@ -1260,6 +1261,7 @@
 	case NFCT_TCP_ACCEPT:
 		break;
 	}
+	}
      in_window:
 	/* From now on we have got in-window packets */
 	ct->proto.tcp.last_index = index;
@@ -1333,6 +1335,38 @@
 	return NF_ACCEPT;
 }
 
+#ifdef CONFIG_IP_FFN
+int external_tcpv4_packet(struct nf_conn *ct,
+			  struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo)
+{
+	/* fixme: is is always PRE_ROUTING ?*/
+	struct nf_hook_state state = {
+		.hook = NF_INET_PRE_ROUTING,
+		.pf = AF_INET,
+		.net = nf_ct_net(ct),
+	};
+	return nf_conntrack_tcp_packet(ct, skb, dataoff, ctinfo, &state);
+}
+#endif
+
+#ifdef CONFIG_IPV6_FFN
+int external_tcpv6_packet(struct nf_conn *ct,
+			  struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo)
+{
+	/* fixme: is is always PRE_ROUTING ?*/
+	struct nf_hook_state state = {
+		.hook = NF_INET_PRE_ROUTING,
+		.pf = AF_INET6,
+		.net = nf_ct_net(ct),
+	};
+	return nf_conntrack_tcp_packet(ct, skb, dataoff, ctinfo, &state);
+}
+#endif
+
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 
 #include <linux/netfilter/nfnetlink.h>
diff -ruw linux-6.4/net/netfilter/nf_conntrack_proto_udp.c linux-6.4-fbx/net/netfilter/nf_conntrack_proto_udp.c
--- linux-6.4/net/netfilter/nf_conntrack_proto_udp.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_conntrack_proto_udp.c	2023-11-29 17:07:14.241662360 +0100
@@ -129,6 +129,38 @@
 	return NF_ACCEPT;
 }
 
+#ifdef CONFIG_IP_FFN
+int external_udpv4_packet(struct nf_conn *ct,
+			  struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo)
+{
+	/* fixme: is is always PRE_ROUTING ?*/
+	struct nf_hook_state state = {
+		.hook = NF_INET_PRE_ROUTING,
+		.pf = AF_INET,
+		.net = nf_ct_net(ct),
+	};
+	return nf_conntrack_udp_packet(ct, skb, dataoff, ctinfo, &state);
+}
+#endif
+
+#ifdef CONFIG_IPV6_FFN
+int external_udpv6_packet(struct nf_conn *ct,
+			  struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo)
+{
+	/* fixme: is is always PRE_ROUTING ?*/
+	struct nf_hook_state state = {
+		.hook = NF_INET_PRE_ROUTING,
+		.pf = AF_INET6,
+		.net = nf_ct_net(ct),
+	};
+	return nf_conntrack_udp_packet(ct, skb, dataoff, ctinfo, &state);
+}
+#endif
+
 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
 static void udplite_error_log(const struct sk_buff *skb,
 			      const struct nf_hook_state *state,
diff -ruw linux-6.4/net/netfilter/nf_conntrack_standalone.c linux-6.4-fbx/net/netfilter/nf_conntrack_standalone.c
--- linux-6.4/net/netfilter/nf_conntrack_standalone.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_conntrack_standalone.c	2023-11-29 17:07:14.241662360 +0100
@@ -557,6 +557,7 @@
 	NF_SYSCTL_CT_LOG_INVALID,
 	NF_SYSCTL_CT_EXPECT_MAX,
 	NF_SYSCTL_CT_ACCT,
+	NF_SYSCTL_CT_HELPER,
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 	NF_SYSCTL_CT_EVENTS,
 #endif
@@ -674,6 +675,14 @@
 		.extra1 	= SYSCTL_ZERO,
 		.extra2 	= SYSCTL_ONE,
 	},
+	[NF_SYSCTL_CT_HELPER] = {
+		.procname	= "nf_conntrack_helper",
+		.maxlen		= sizeof(u8),
+		.mode		= 0644,
+		.proc_handler	= proc_dou8vec_minmax,
+		.extra1 	= SYSCTL_ZERO,
+		.extra2 	= SYSCTL_ONE,
+	},
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 	[NF_SYSCTL_CT_EVENTS] = {
 		.procname	= "nf_conntrack_events",
@@ -1079,6 +1088,7 @@
 	table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum;
 	table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid;
 	table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct;
+	table[NF_SYSCTL_CT_HELPER].data = &cnet->sysctl_auto_assign_helper;
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
 	table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events;
 #endif
diff -ruw linux-6.4/net/netfilter/nf_nat_core.c linux-6.4-fbx/net/netfilter/nf_nat_core.c
--- linux-6.4/net/netfilter/nf_nat_core.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_nat_core.c	2023-11-29 17:07:14.244995698 +0100
@@ -641,6 +641,11 @@
 	else
 		ct->status |= IPS_SRC_NAT_DONE;
 
+	if (maniptype == NF_NAT_MANIP_SRC) {
+		ct->nat_src_proto_min = range->min_proto;
+		ct->nat_src_proto_max = range->max_proto;
+	}
+
 	return NF_ACCEPT;
 }
 EXPORT_SYMBOL(nf_nat_setup_info);
diff -ruw linux-6.4/net/netfilter/nf_nat_helper.c linux-6.4-fbx/net/netfilter/nf_nat_helper.c
--- linux-6.4/net/netfilter/nf_nat_helper.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_nat_helper.c	2023-11-29 17:07:14.244995698 +0100
@@ -188,6 +188,14 @@
 	range.flags = NF_NAT_RANGE_MAP_IPS;
 	range.min_addr = range.max_addr
 		= ct->master->tuplehash[!exp->dir].tuple.dst.u3;
+
+	if (ct->master->nat_src_proto_min.all &&
+	    ct->master->nat_src_proto_max.all) {
+		range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+		range.min_proto = ct->master->nat_src_proto_min;
+		range.max_proto = ct->master->nat_src_proto_max;
+	}
+
 	nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
 
 	/* For DST manip, map port here to where it's expected. */
diff -ruw linux-6.4/net/netfilter/nf_nat_proto.c linux-6.4-fbx/net/netfilter/nf_nat_proto.c
--- linux-6.4/net/netfilter/nf_nat_proto.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/netfilter/nf_nat_proto.c	2022-08-30 19:20:33.419660807 +0200
@@ -385,6 +385,8 @@
 {
 #if IS_ENABLED(CONFIG_IPV6)
 	struct ipv6hdr *ipv6h;
+	const __be32 *to;
+	__be32 *from;
 	__be16 frag_off;
 	int hdroff;
 	u8 nexthdr;
@@ -407,10 +409,24 @@
 	ipv6h = (void *)skb->data + iphdroff;
 
 manip_addr:
-	if (maniptype == NF_NAT_MANIP_SRC)
-		ipv6h->saddr = target->src.u3.in6;
-	else
-		ipv6h->daddr = target->dst.u3.in6;
+	if (maniptype == NF_NAT_MANIP_SRC) {
+		from = ipv6h->saddr.s6_addr32;
+		to = target->src.u3.in6.s6_addr32;
+	} else {
+		from = ipv6h->daddr.s6_addr32;
+		to = target->dst.u3.in6.s6_addr32;
+	}
+
+	if (skb->ip_summed == CHECKSUM_COMPLETE) {
+		__be32 diff[] = {
+			~from[0], ~from[1], ~from[2], ~from[3],
+			to[0], to[1], to[2], to[3],
+		};
+
+		skb->csum = ~csum_partial(diff, sizeof(diff), ~skb->csum);
+	}
+
+	memcpy(from, to, sizeof (struct in6_addr));
 
 #endif
 	return true;
diff -ruw linux-6.4/net/socket.c linux-6.4-fbx/net/socket.c
--- linux-6.4/net/socket.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/socket.c	2023-11-29 17:07:14.321662484 +0100
@@ -1220,6 +1220,29 @@
 	return err;
 }
 
+static DEFINE_MUTEX(fbxbridge_ioctl_mutex);
+static int (*fbxbridge_ioctl_hook)(struct net *, unsigned int cmd, void __user *arg) = NULL;
+
+void fbxbridge_set(int (*hook)(struct net *, unsigned int, void __user *))
+{
+	mutex_lock(&fbxbridge_ioctl_mutex);
+	fbxbridge_ioctl_hook = hook;
+	mutex_unlock(&fbxbridge_ioctl_mutex);
+}
+
+static DEFINE_MUTEX(fbxdiverter_ioctl_mutex);
+static int (*fbxdiverter_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
+
+void fbxdiverter_ioctl_set(int (*hook) (struct net *, unsigned int,
+					void __user *))
+{
+	mutex_lock(&fbxdiverter_ioctl_mutex);
+	fbxdiverter_ioctl_hook = hook;
+	mutex_unlock(&fbxdiverter_ioctl_mutex);
+}
+
+EXPORT_SYMBOL(fbxdiverter_ioctl_set);
+
 /*
  *	With an ioctl, arg may well be a user mode pointer, but we don't know
  *	what to do with it - that's up to the protocol still.
@@ -1289,6 +1312,17 @@
 
 			err = open_related_ns(&net->ns, get_net_ns);
 			break;
+		case SIOCGFBXDIVERT:
+		case SIOCSFBXDIVERT:
+			err = -ENOPKG;
+			if (!fbxdiverter_ioctl_hook)
+				request_module("fbxdiverter");
+
+			mutex_lock(&fbxdiverter_ioctl_mutex);
+			if (fbxdiverter_ioctl_hook)
+				err = fbxdiverter_ioctl_hook(net, cmd, argp);
+			mutex_unlock(&fbxdiverter_ioctl_mutex);
+			break;
 		case SIOCGSTAMP_OLD:
 		case SIOCGSTAMPNS_OLD:
 			if (!sock->ops->gettstamp) {
@@ -1314,6 +1348,17 @@
 			err = dev_ifconf(net, argp);
 			break;
 
+		case SIOCGFBXBRIDGE:
+		case SIOCSFBXBRIDGE:
+			err = -ENOPKG;
+			if (!fbxbridge_ioctl_hook)
+				request_module("fbxbridge");
+
+			mutex_lock(&fbxbridge_ioctl_mutex);
+			if (fbxbridge_ioctl_hook)
+				err = fbxbridge_ioctl_hook(net, cmd, argp);
+			mutex_unlock(&fbxbridge_ioctl_mutex);
+			break;
 		default:
 			err = sock_do_ioctl(net, sock, cmd, arg);
 			break;
diff -ruw linux-6.4/net/unix/Kconfig linux-6.4-fbx/net/unix/Kconfig
--- linux-6.4/net/unix/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/unix/Kconfig	2022-08-30 19:20:33.723664242 +0200
@@ -30,6 +30,9 @@
 	depends on UNIX
 	default y
 
+config UNIX_ABSTRACT_IGNORE_NETNS
+	bool "make abstract namespace global to all network namespaces"
+
 config UNIX_DIAG
 	tristate "UNIX: socket monitoring interface"
 	depends on UNIX
diff -ruw linux-6.4/net/unix/af_unix.c linux-6.4-fbx/net/unix/af_unix.c
--- linux-6.4/net/unix/af_unix.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/unix/af_unix.c	2023-11-29 17:07:14.341662515 +0100
@@ -1116,8 +1116,19 @@
 
 	if (sunaddr->sun_path[0])
 		sk = unix_find_bsd(sunaddr, addr_len, type);
-	else
+	else {
+#ifdef CONFIG_UNIX_ABSTRACT_IGNORE_NETNS
+		down_read(&net_rwsem);
+		for_each_net(net) {
+#endif
 		sk = unix_find_abstract(net, sunaddr, addr_len, type);
+#ifdef CONFIG_UNIX_ABSTRACT_IGNORE_NETNS
+			if (!IS_ERR(sk))
+				break;
+		}
+		up_read(&net_rwsem);
+#endif
+	}
 
 	return sk;
 }
diff -ruw linux-6.4/net/wireless/Kconfig linux-6.4-fbx/net/wireless/Kconfig
--- linux-6.4/net/wireless/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/wireless/Kconfig	2024-02-21 16:43:28.726470831 +0100
@@ -177,6 +177,9 @@
 
 	  If unsure, say N.
 
+config CFG80211_DFS_CACHE
+	bool "keep each channel dfs state in global cache"
+
 config CFG80211_CRDA_SUPPORT
 	bool "support CRDA" if EXPERT
 	default y
@@ -201,6 +204,22 @@
 	  Drivers should select this option if they require cfg80211's
 	  wext compatibility symbols to be exported.
 
+config CFG80211_KUNIT_TEST
+	tristate "KUnit tests for cfg80211" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	depends on CFG80211
+	default KUNIT_ALL_TESTS
+	depends on !KERNEL_6_2
+	help
+	  Enable this option to test cfg80211 functions with kunit.
+
+	  If unsure, say N.
+
+config FBX80211
+	bool "fbx genl family"
+	help
+	  Support for freebox specific genl family
+
 endif # CFG80211
 
 config LIB80211
diff -ruw linux-6.4/net/wireless/Makefile linux-6.4-fbx/net/wireless/Makefile
--- linux-6.4/net/wireless/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/wireless/Makefile	2024-01-12 13:49:05.016702436 +0100
@@ -4,6 +4,7 @@
 obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
 obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
 obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
+obj-y += tests/
 
 obj-$(CONFIG_WEXT_CORE) += wext-core.o
 obj-$(CONFIG_WEXT_PROC) += wext-proc.o
@@ -24,6 +25,8 @@
 cfg80211-y += extra-certs.o
 endif
 
+cfg80211-$(CONFIG_FBX80211) += nlfbx.o
+
 $(obj)/shipped-certs.c: $(wildcard $(srctree)/$(src)/certs/*.hex)
 	@$(kecho) "  GEN     $@"
 	$(Q)(echo '#include "reg.h"'; \
diff -ruw linux-6.4/net/xfrm/xfrm_device.c linux-6.4-fbx/net/xfrm/xfrm_device.c
--- linux-6.4/net/xfrm/xfrm_device.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/xfrm/xfrm_device.c	2023-11-29 17:07:14.361662546 +0100
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <net/dst.h>
+#include <net/gso.h>
 #include <net/xfrm.h>
 #include <linux/notifier.h>
 
diff -ruw linux-6.4/net/xfrm/xfrm_output.c linux-6.4-fbx/net/xfrm/xfrm_output.c
--- linux-6.4/net/xfrm/xfrm_output.c	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/net/xfrm/xfrm_output.c	2023-11-29 17:07:14.361662546 +0100
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <net/dst.h>
+#include <net/gso.h>
 #include <net/icmp.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
diff -ruw linux-6.4/scripts/Makefile.lib linux-6.4-fbx/scripts/Makefile.lib
--- linux-6.4/scripts/Makefile.lib	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/scripts/Makefile.lib	2023-11-29 17:07:14.391662593 +0100
@@ -372,7 +372,7 @@
       cmd_wrap_S_dtb = {								\
 		symbase=__$(patsubst .%,%,$(suffix $<))_$(subst -,_,$(notdir $*));	\
 		echo '\#include <asm-generic/vmlinux.lds.h>';				\
-		echo '.section .dtb.init.rodata,"a"';					\
+		echo '.section .dtb.rodata,"a"';					\
 		echo '.balign STRUCT_ALIGNMENT';					\
 		echo ".global $${symbase}_begin";					\
 		echo "$${symbase}_begin:";						\
diff -ruw linux-6.4/scripts/dtc/include-prefixes/dt-bindings/input/linux-event-codes.h linux-6.4-fbx/scripts/dtc/include-prefixes/dt-bindings/input/linux-event-codes.h
--- linux-6.4/scripts/dtc/include-prefixes/dt-bindings/input/linux-event-codes.h	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/scripts/dtc/include-prefixes/dt-bindings/input/linux-event-codes.h	2023-11-29 17:07:13.751661598 +0100
@@ -803,6 +803,18 @@
 #define BTN_TRIGGER_HAPPY39		0x2e6
 #define BTN_TRIGGER_HAPPY40		0x2e7
 
+#define KEY_APP_TV			0x2f1
+#define KEY_APP_REPLAY			0x2f2
+#define KEY_APP_VIDEOCLUB		0x2f3
+#define KEY_APP_WHATSON			0x2f4
+#define KEY_APP_RECORDS			0x2f5
+#define KEY_APP_MEDIA			0x2f6
+#define KEY_APP_YOUTUBE			0x2f7
+#define KEY_APP_RADIOS			0x2f8
+#define KEY_APP_CANALVOD		0x2f9
+#define KEY_APP_PIP			0x2fa
+#define KEY_APP_NETFLIX			0x2fb
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING	KEY_MUTE
 #define KEY_MAX			0x2ff
diff -ruw linux-6.4/scripts/gen_autoksyms.sh linux-6.4-fbx/scripts/gen_autoksyms.sh
--- linux-6.4/scripts/gen_autoksyms.sh	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/scripts/gen_autoksyms.sh	2023-11-29 17:07:14.414995963 +0100
@@ -22,7 +22,7 @@
 
 output_file="$1"
 
-needed_symbols=
+needed_symbols=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST_SYMS=\(.*\)$/\1/p' include/config/auto.conf)
 
 # Special case for modversions (see modpost.c)
 if grep -q "^CONFIG_MODVERSIONS=y$" include/config/auto.conf; then
diff -ruw linux-6.4/sound/soc/kirkwood/Kconfig linux-6.4-fbx/sound/soc/kirkwood/Kconfig
--- linux-6.4/sound/soc/kirkwood/Kconfig	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/sound/soc/kirkwood/Kconfig	2020-02-08 00:30:25.800543782 +0100
@@ -16,3 +16,8 @@
 	  Say Y if you want to add support for SoC audio on
 	  the Armada 370 Development Board.
 
+config SND_KIRKWOOD_SOC_FBXGW2R
+	tristate "Soc Audio support for fbxgw2r"
+	depends on SND_KIRKWOOD_SOC && MACH_FBXGW2R && I2C
+	select SND_KIRKWOOD_SOC_I2S
+	select SND_SOC_CS42L52
diff -ruw linux-6.4/sound/soc/kirkwood/Makefile linux-6.4-fbx/sound/soc/kirkwood/Makefile
--- linux-6.4/sound/soc/kirkwood/Makefile	2023-06-26 01:29:58.000000000 +0200
+++ linux-6.4-fbx/sound/soc/kirkwood/Makefile	2020-02-08 00:30:25.800543782 +0100
@@ -6,3 +6,6 @@
 snd-soc-armada-370-db-objs := armada-370-db.o
 
 obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o
+
+snd-soc-fbxgw2r-objs := kirkwood-fbxgw2r.o
+obj-$(CONFIG_SND_KIRKWOOD_SOC_FBXGW2R) += snd-soc-fbxgw2r.o
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/arch/x86/kernel/fbxbootinfo.c	2016-05-18 16:00:59.452084227 +0200
@@ -0,0 +1,47 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fbxbootinfo.h>
+#include <linux/init.h>
+
+#include <asm/bootparam.h>
+#include <asm/io.h>
+
+static struct fbx_bootinfo fbx_bootinfo;
+
+u32 loader_bank_number;
+EXPORT_SYMBOL(loader_bank_number);
+
+char loader_version_str[128];
+EXPORT_SYMBOL(loader_version_str);
+
+u32 loader_bank0_forced;
+EXPORT_SYMBOL(loader_bank0_forced);
+
+char cefdk_version_str[256];
+EXPORT_SYMBOL(cefdk_version_str);
+
+void __init parse_fbxbootinfo(u64 phys_addr, u32 data_len)
+{
+	struct setup_data *data;
+
+	data = early_memremap(phys_addr, data_len);
+	if (data->len != sizeof (fbx_bootinfo)) {
+		printk(KERN_ERR "%s: invalid length: "
+		       "have %d, want %zd\n", __func__, data->len,
+			sizeof (fbx_bootinfo));
+	}
+	memcpy(&fbx_bootinfo, data->data, data->len);
+	early_iounmap(data, data_len);
+
+	loader_bank_number = fbx_bootinfo.bank_number;
+	memcpy(&loader_version_str, &fbx_bootinfo.uboot_version_str,
+				sizeof(loader_version_str));
+	loader_bank0_forced = fbx_bootinfo.bank0_forced;
+	memcpy(&cefdk_version_str, &fbx_bootinfo.cefdk_version_str,
+				sizeof(cefdk_version_str));
+}
+
+const struct fbx_bootinfo *arch_get_fbxbootinfo(void)
+{
+	return &fbx_bootinfo;
+}
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/arch/x86/kernel/fbxserial.c	2016-05-18 16:00:59.452084227 +0200
@@ -0,0 +1,57 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fbxserial.h>
+#include <linux/init.h>
+#include <linux/random.h>
+
+#include <asm/bootparam.h>
+#include <asm/io.h>
+
+static struct fbx_serial serial_info;
+static int parse_done;
+
+void __init parse_fbxserial_ext(u64 phys_addr, u32 data_len)
+{
+	struct setup_data *data;
+
+	data = early_memremap(phys_addr, data_len);
+	if (data->len != sizeof (serial_info)) {
+		printk(KERN_ERR "parse_fbxserial_ext: invalid length: "
+		       "have %u, want %zu\n", data->len, sizeof (serial_info));
+	}
+	fbxserialinfo_read(data->data, &serial_info);
+	early_iounmap(data, data_len);
+	add_device_randomness(&serial_info, sizeof (serial_info));
+	parse_done = 1;
+}
+
+static int __init fbxserial_parse_check(void)
+{
+	if (!parse_done) {
+		/*
+		 * just setup magic and crc with bogus values.
+		 */
+		u32 bad_serial[sizeof (struct fbx_serial) / sizeof (u32)] =
+			{ 0xaa55aa55, 0xaa55aa55 };
+
+		/*
+		 * feed serial info deliberately with bad data to
+		 * enforce default settings.
+		 */
+		printk(KERN_ERR "parse_fbxserial_ext was not called. "
+		       "please fix/update your bootloader.\n");
+		fbxserialinfo_read(bad_serial, &serial_info);
+	}
+
+	return 0;
+}
+arch_initcall(fbxserial_parse_check);
+
+
+const struct fbx_serial *arch_get_fbxserial(void)
+{
+	return &serial_info;
+}
+
+EXPORT_SYMBOL(arch_get_fbxserial);
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/arch/x86/platform/ce4100/fbx6hd.c	2022-08-30 19:20:22.135533317 +0200
@@ -0,0 +1,611 @@
+/*
+ * fbx6hd board specific code
+ */
+#define PFX "fbx6hd: "
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/of_fdt.h>
+
+#include <asm/e820/api.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+
+int fbx6hd_board_ecc_level = 1;
+EXPORT_SYMBOL(fbx6hd_board_ecc_level);
+
+/*
+ * i2c hardware definitions
+ */
+#define ICR             (0x00)
+#define ISR             (0x04)
+#define ISAR            (0x08)
+#define IBMR            (0x10)
+#define IDBR            (0x0C)
+
+#define ICR_START       (1 << 0)           /* start bit */
+#define ICR_STOP        (1 << 1)           /* stop bit */
+#define ICR_ACKNAK      (1 << 2)           /* send ACK(0) or NAK(1) */
+#define ICR_TB          (1 << 3)           /* transfer byte bit */
+#define ICR_MA          (1 << 4)           /* master abort */
+#define ICR_SCLE        (1 << 5)           /* master clock enable */
+#define ICR_IUE         (1 << 6)           /* unit enable */
+#define ICR_GCD         (1 << 7)           /* general call disable */
+#define ICR_ITEIE       (1 << 8)           /* enable tx interrupts */
+#define ICR_IRFIE       (1 << 9)           /* enable rx interrupts */
+#define ICR_BEIE        (1 << 10)          /* enable bus error ints */
+#define ICR_SSDIE       (1 << 11)          /* slave STOP detected int enable */
+#define ICR_ALDIE       (1 << 12)          /* enable arbitration interrupt */
+#define ICR_SADIE       (1 << 13)          /* slave address detected int enable */
+#define ICR_UR          (1 << 14)          /* unit reset */
+#define ICR_FM          (1 << 15)          /* fast mode */
+
+#define ISR_RWM         (1 << 0)           /* read/write mode */
+#define ISR_ACKNAK      (1 << 1)           /* ack/nak status */
+#define ISR_UB          (1 << 2)           /* unit busy */
+#define ISR_IBB         (1 << 3)           /* bus busy */
+#define ISR_SSD         (1 << 4)           /* slave stop detected */
+#define ISR_ALD         (1 << 5)           /* arbitration loss detected */
+#define ISR_ITE         (1 << 6)           /* tx buffer empty */
+#define ISR_IRF         (1 << 7)           /* rx buffer full */
+#define ISR_GCAD        (1 << 8)           /* general call address detected */
+#define ISR_SAD         (1 << 9)           /* slave address detected */
+#define ISR_BED         (1 << 10)          /* bus error no ACK/NAK */
+#define ISR_RESERVED	0xfffff800
+
+#define I2C_WRITE	0
+#define I2C_READ	1
+
+#define I2C_BUS_ADDR	(0xdffe0500)
+#define I2C_BUS1_ADDR	(I2C_BUS_ADDR + 0x100)
+#define I2C_BUS2_ADDR	(I2C_BUS_ADDR + 0x200)
+#define I2C_BUS_SIZE	(0x100 - 1)
+
+
+/*
+ * PIC16 PMU definitions
+ */
+#define PIC16PMU_I2C_ADDR	0x60
+
+#define REG_DEVID		0x00
+# define REG_DEVID_16F722	0x22
+
+#define REG_ECC_LEVEL		0x09
+# define REG_ECC_LEVEL_1BIT	0xff
+# define REG_ECC_LEVEL_4BIT	0x01
+
+/*
+ * CK505 definitions
+ */
+#define CK505_ADDR		(0x69)
+#define CK505_SPREAD_REG	(0x01)
+#define CK505_SPREAD_CENTRAL	(1 << 6)
+
+
+/*
+ * this is a hardcoded offset, we do not have working PCI right now to
+ * read the address from the PCI config space. (but it would be
+ * cleaner to do so).
+ */
+#define CRBAR_BASE		0xa0000000
+
+/*
+ * inside CRBAR_BASE
+ */
+#define CRBAR_FSB_REG		0x0
+# define FSB_MASK		0x03
+# define FSB_100		0x0
+# define FSB_133		0x1
+# define FSB_166		0x2
+# define FSB_200		0x3
+
+#define CRBAR_STRAP_RATIO_REG	0x14
+# define STRAP_RATIO_MASK	0xf
+
+/*
+ * name guessed from context in intel source code.
+ */
+#define FUSING_RATIO_MSR	0x198
+# define FUSING_RATIO_SHIFT	8
+# define FUSING_RATIO_MASK	0x1f
+
+/*
+ * udelay is not working yet, so provide a dummy version
+ * which is sufficent for polling.
+ */
+static u32 ticks_per_usec = 1000;
+
+static inline void __local_udelay(u32 usec)
+{
+	u64 now;
+	u64 end;
+
+	now = rdtsc();
+	end = now + (u64)usec * ticks_per_usec;
+
+	while (rdtsc() < end)
+		;
+}
+
+/*
+ * FSB is found inside CRBAR zone.
+ */
+static __init u32 get_cpu_fsb_mhz(void __iomem *crbar_base)
+{
+	u32 fsb_reg;
+
+	fsb_reg = readl(crbar_base + CRBAR_FSB_REG);
+	switch (fsb_reg & FSB_MASK) {
+	case FSB_100:
+		return 100;
+		break;
+	case FSB_133:
+		return 133;
+		break;
+	case FSB_166:
+		return 166;
+		break;
+	case FSB_200:
+		return 200;
+	}
+	/* safe default ? */
+	return 100;
+}
+
+/*
+ * strapped ratio is found on CRBAR zone too.
+ */
+static __init u32 get_cpu_strap_ratio(void __iomem *crbar_base)
+{
+	u32 strap_ratio_reg;
+
+	strap_ratio_reg = readl(crbar_base + CRBAR_STRAP_RATIO_REG);
+	return 21 - (strap_ratio_reg & STRAP_RATIO_MASK);
+}
+
+/*
+ * use MSRs to get fused limit.
+ */
+static __init u32 get_cpu_fusing_ratio(void __iomem *crbar_base)
+{
+	u32 dummy, fusing_ratio_msr;
+
+	rdmsr(FUSING_RATIO_MSR, dummy, fusing_ratio_msr);
+
+	return (fusing_ratio_msr >> FUSING_RATIO_SHIFT) & FUSING_RATIO_MASK;
+
+}
+
+static __init unsigned long __get_cpu_mhz(void)
+{
+	void __iomem *crbar_base;
+	u32 fsb_mhz;
+	u32 strap_ratio;
+	u32 fusing_ratio;
+	u32 ratio;
+	u32 cpu_mhz;
+
+	crbar_base = early_ioremap(CRBAR_BASE, 0x20);
+	if (!crbar_base) {
+		pr_err("failde to remap CRBAR base\n");
+		return 1200;
+	}
+
+	fsb_mhz = get_cpu_fsb_mhz(crbar_base);
+	strap_ratio = get_cpu_strap_ratio(crbar_base);
+	fusing_ratio = get_cpu_fusing_ratio(crbar_base);
+
+	if (strap_ratio > fusing_ratio) {
+		printk("warning: strap ratio higher than fused ratio, "
+		       "will use fused ratio.\n");
+		ratio = fusing_ratio;
+	} else
+		ratio = strap_ratio;
+
+	cpu_mhz = ratio * fsb_mhz;
+
+	early_iounmap(crbar_base, 0x20);
+
+	return cpu_mhz;
+}
+
+/*
+ *
+ */
+static inline u32 i2c_reg_read(void __iomem *base_addr, u32 reg)
+{
+	return readl(base_addr + reg);
+}
+
+static inline void i2c_reg_write(void __iomem *base_addr, u32 val, u32 reg)
+{
+	writel(val, base_addr + reg);
+}
+
+static __init void __iomem *i2c_hw_init(unsigned long bus_paddr)
+{
+	void __iomem *base_addr;
+	u32 reg = 0;
+	unsigned long cpu_hz;
+
+	/*
+	 * initialize udelay
+	 */
+	cpu_hz = __get_cpu_mhz() * 1000000;
+	ticks_per_usec = cpu_hz / 1000000;
+
+	base_addr = early_ioremap(bus_paddr, I2C_BUS_SIZE);
+	if (!base_addr) {
+		pr_err("failed to early_ioremap 0x%08lx\n",
+		       bus_paddr);
+		return NULL;
+	}
+
+	/*
+	 * reset the unit and clear any pending interrupt
+	 */
+	reg |= ICR_UR;
+	i2c_reg_write(base_addr, reg, ICR);
+	i2c_reg_write(base_addr, 0, ICR);
+	i2c_reg_write(base_addr, 0, ISR);
+
+	/*
+	 * TX empty and RX full interrupts are set automatically
+	 */
+	reg = ICR_IUE | ICR_SCLE | ICR_GCD;
+	i2c_reg_write(base_addr, reg, ICR);
+	__local_udelay(100);
+
+	return base_addr;
+}
+
+static void i2c_clear_interrupt(void __iomem *base_addr)
+{
+	u32 reg;
+
+	reg = i2c_reg_read(base_addr, ISR);
+	reg &= (ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | ISR_SAD | ISR_BED);
+	i2c_reg_write(base_addr, reg, ISR);
+}
+
+static int i2c_wait(void __iomem *base_addr, u32 cond, u32 *last_reg)
+{
+	volatile u32 reg;
+	int count = 100;
+
+	while (count) {
+		reg = i2c_reg_read(base_addr, ISR);
+		if (reg & cond) {
+			*last_reg = reg;
+			i2c_clear_interrupt(base_addr);
+			return 0;
+		}
+		count--;
+		__local_udelay(10);
+	}
+
+	i2c_clear_interrupt(base_addr);
+	return -1;
+}
+
+static int i2c_send_start(void __iomem *base_addr, u8 addr, unsigned op)
+{
+	u32 reg;
+	int status;
+
+	/* write slave address */
+	i2c_reg_write(base_addr, (addr << 1) | op, IDBR);
+
+	reg = i2c_reg_read(base_addr, ICR);
+	reg &= ~(ICR_START | ICR_STOP | ICR_ALDIE | ICR_ACKNAK | ICR_TB);
+	reg |= ICR_START | ICR_TB;
+	i2c_reg_write(base_addr, reg, ICR);
+
+	status = i2c_wait(base_addr, ISR_ITE | ISR_BED, &reg);
+	if (status < 0) {
+		pr_debug("%s: timeout\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_BED) {
+		pr_debug("%s: bus error\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_ACKNAK) {
+		pr_debug("%s: invalid return: %08x\n", __func__, reg);
+		return -2;
+	}
+
+	return 0;
+}
+
+static int i2c_tx_byte(void __iomem *base_addr, u8 byte, unsigned stop)
+{
+	u32 reg;
+	int status;
+
+	/* load data */
+	i2c_reg_write(base_addr, byte, IDBR);
+
+	reg = i2c_reg_read(base_addr, ICR);
+	reg &= ~(ICR_START | ICR_STOP | ICR_ALDIE | ICR_ACKNAK | ICR_TB);
+	reg |= ICR_ALDIE | ICR_TB;
+	if (stop)
+		reg |= ICR_STOP;
+
+	i2c_reg_write(base_addr, reg, ICR);
+
+	status = i2c_wait(base_addr, ISR_ITE, &reg);
+	if (status < 0) {
+		pr_debug("%s: timeout\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_BED) {
+		pr_debug("%s: bus error\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_ACKNAK) {
+		pr_debug("%s: invalid return: %08x\n", __func__, reg);
+		return -2;
+	}
+
+	return 0;
+}
+
+static int i2c_rx_byte(void __iomem *base_addr, unsigned stop)
+{
+	u32 reg;
+	int status;
+
+	reg = i2c_reg_read(base_addr, ICR);
+	reg &= ~(ICR_START | ICR_STOP | ICR_ALDIE | ICR_ACKNAK | ICR_TB);
+	reg |= ICR_ALDIE | ICR_TB;
+	if (stop)
+		reg |= ICR_STOP | ICR_ACKNAK;
+
+	i2c_reg_write(base_addr, reg, ICR);
+	status = i2c_wait(base_addr, ISR_IRF, &reg);
+	if (status < 0) {
+		pr_debug("%s: timeout\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_BED) {
+		pr_debug("%s: bus error\n", __func__);
+		return -1;
+	}
+
+	return i2c_reg_read(base_addr, IDBR);
+}
+
+static int __init try_fixup_ck505(void)
+{
+	void __iomem *base_addr;
+	int ret;
+	u8 byte;
+
+	base_addr = i2c_hw_init(I2C_BUS1_ADDR);
+	if (WARN_ON(!base_addr))
+		return 1;
+
+	ret = i2c_send_start(base_addr, CK505_ADDR, I2C_WRITE);
+	if (ret) {
+		pr_err("[%d]: failed to send i2c_send_start: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(base_addr, CK505_SPREAD_REG, 1);
+	if (ret) {
+		pr_err("[%d]: failed to write reg: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_send_start(base_addr, CK505_ADDR, I2C_READ);
+	if (ret) {
+		pr_err("[%d]: failed to i2c_send_start: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	byte = i2c_rx_byte(base_addr, 0);
+	if (byte < 0) {
+		pr_err("[%d]: failed to read: %d\n", __LINE__, byte);
+		goto out_unmap;
+	}
+
+	byte = i2c_rx_byte(base_addr, 1);
+	if (byte < 0) {
+		pr_err("[%d]: failed to read: %d\n", __LINE__, byte);
+		goto out_unmap;
+	}
+
+	if (byte & CK505_SPREAD_CENTRAL) {
+		pr_info("no fixup required: 0x%02x\n", byte);
+		goto out_unmap;
+	}
+
+	pr_info("fixing up: 0x%02x -> 0x%02x\n",
+		byte, byte | CK505_SPREAD_CENTRAL);
+
+	/* Set the PLL1_SSC_SEL to central spread spectrum mode */
+	byte |= CK505_SPREAD_CENTRAL;
+
+	ret = i2c_send_start(base_addr, CK505_ADDR, I2C_WRITE);
+	if (ret) {
+		pr_err("[%d]: failed to send start: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(base_addr, CK505_SPREAD_REG, 0);
+	if (ret) {
+		pr_err("[%d]: failed to write byte\n", ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(base_addr, CK505_SPREAD_REG, 0);
+	if (ret) {
+		pr_err("[%d]: failed to write byte\n", ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(base_addr, byte, 1);
+	if (ret) {
+		pr_err("[%d]: failed to write byte\n", ret);
+		goto out_unmap;
+	}
+
+	pr_info("successfully fixed-up\n");
+
+out_unmap:
+	early_iounmap(base_addr, I2C_BUS_SIZE);
+
+	return ret;
+}
+
+static void __init fixup_ck505(void)
+{
+	size_t i;
+
+	for (i = 0; i < 16; i++) {
+		if (!try_fixup_ck505())
+			break;
+	}
+}
+
+/*
+ * fetch ECC level from PMU config register.
+ */
+static int pic16pmu_smbus_read(void __iomem *base_addr, uint8_t reg, uint8_t *value)
+{
+	int error;
+
+	error = i2c_send_start(base_addr, PIC16PMU_I2C_ADDR, I2C_WRITE);
+	if (error < 0)
+		return error;
+
+	error = i2c_tx_byte(base_addr, reg, 0);
+	if (error < 0)
+		return error;
+
+	__local_udelay(10);
+
+	error = i2c_send_start(base_addr, PIC16PMU_I2C_ADDR, I2C_READ);
+	if (error)
+		return error;
+
+	error = i2c_rx_byte(base_addr,1);
+	if (error < 0)
+		return error;
+
+	*value = error;
+	return 0;
+}
+
+/*
+ *
+ */
+static int __init get_ecc_level(void)
+{
+	void __iomem *base_addr;
+	int ret;
+	uint8_t reg;
+
+	base_addr = i2c_hw_init(I2C_BUS2_ADDR);
+	if (WARN_ON(!base_addr))
+		return 1;
+
+	ret = pic16pmu_smbus_read(base_addr, REG_DEVID, &reg);
+	if (ret < 0) {
+		pr_err("unable to read REG_DEVID ...\n");
+		goto out_unmap;
+	}
+
+	if (reg != REG_DEVID_16F722) {
+		pr_err("no pic16-pmu detected at address 0x%02x.\n",
+		       PIC16PMU_I2C_ADDR);
+		ret = -ENODEV;
+		goto out_unmap;
+	}
+
+	ret = pic16pmu_smbus_read(base_addr, REG_ECC_LEVEL, &reg);
+	if (ret < 0) {
+		pr_err("unable to read REG_ECC_LEVEL ...\n");
+		goto out_unmap;
+	}
+
+	switch (reg) {
+	case REG_ECC_LEVEL_4BIT:
+		fbx6hd_board_ecc_level = 4;
+		break;
+	case REG_ECC_LEVEL_1BIT:
+		fbx6hd_board_ecc_level = 1;
+		break;
+	default:
+		ret = -EIO;
+		break;
+	}
+
+	if (ret < 0)
+		pr_warn("using default ECC level %d (unrecognized value in "
+			"register)\n", reg);
+	else
+		pr_info("using ECC level %d (register %02x)\n",
+			fbx6hd_board_ecc_level, reg);
+
+out_unmap:
+	early_iounmap(base_addr, I2C_BUS_SIZE);
+	return ret;
+}
+
+/*
+ *
+ */
+static char *__init fbx6hd_memory_setup(void)
+{
+	char *who = "fbx-rammap";
+	u64 usable_mem_size;
+
+	/* BIOS does not report correct ram size */
+	usable_mem_size = 1024 << 20;
+
+	/*
+	 * acpi tables are at 0x10000
+	 * uc8051 code is running at 0x40000
+	 */
+	e820__range_add(0x10000, 0x10000, E820_TYPE_ACPI);
+	e820__range_add(0x20000, 0x40000 - 0x20000, E820_TYPE_RAM);
+	e820__range_add(0x50000, 0x98000 - 0x50000, E820_TYPE_RAM);
+	e820__range_add(HIGH_MEMORY, usable_mem_size - HIGH_MEMORY, E820_TYPE_RAM);
+
+	return who;
+}
+
+extern __initdata u64 initial_dtb;
+
+/*
+ *
+ */
+void __init fbx6hd_arch_setup(void)
+{
+	const void *dtb;
+
+	panic_timeout = 10;
+
+	fixup_ck505();
+	get_ecc_level();
+
+	dtb = of_fdt_find_compatible_dtb("freebox,fbx6hd");
+	if (!dtb)
+		pr_err("fbx6hd linked in DTB not found");
+	else {
+		initial_dtb = __pa(dtb);
+	}
+
+	/* our crappy firmware does not pass a valid e820 map, so
+	 * fixup manually */
+	x86_init.resources.memory_setup = fbx6hd_memory_setup;
+}
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/arch/x86/platform/ce4100/fbx6hd.dts	2020-02-08 00:30:16.696455319 +0100
@@ -0,0 +1,501 @@
+/*
+ * CE4100 on Falcon Falls
+ *
+ * (c) Copyright 2010 Intel Corporation
+ *
+ * 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; version 2 of the License.
+ */
+/dts-v1/;
+/ {
+	model = "freebox,Freebox v6";
+	compatible = "intel,falconfalls", "freebox,fbx6hd";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "intel,ce4100";
+			reg = <0>;
+			lapic = <&lapic0>;
+		};
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		ramoops@3fffc000 {
+			compatible = "ramoops";
+			/* RAM top - 16k */
+			reg = <0x3fffc000 (16 * 1024)>;
+			record-size = <(16 * 1024)>;
+			ecc-size = <16>;
+			no-dump-oops;
+		};
+        };
+
+	remoti: ti,cc2530@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "ti,remoti";
+		reset-gpio = <100 0>;	// gpio, polarity
+		id = <0>;
+
+		gpio@0 {
+			compatible = "ti,remoti-gpio";
+			gpios = <200 3>;	// base, number
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		leds@1 {
+			compatible = "ti,remoti-leds";
+
+			rf-activity@0 {
+				label = "rf_activity:blue";
+			};
+
+			rf-pairing@1 {
+				label = "rf_pairing:red";
+			};
+		};
+
+		hdmi-cec@2 {
+			compatible = "ti,remoti-cec";
+		};
+	};
+
+	soc@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "intel,ce4100-cp";
+		ranges;
+
+		ioapic1: interrupt-controller@fec00000 {
+			#interrupt-cells = <2>;
+			compatible = "intel,ce4100-ioapic";
+			interrupt-controller;
+			reg = <0xfec00000 0x1000>;
+		};
+
+		timer@fed00000 {
+			compatible = "intel,ce4100-hpet";
+			reg = <0xfed00000 0x200>;
+		};
+
+		lapic0: interrupt-controller@fee00000 {
+			compatible = "intel,ce4100-lapic";
+			reg = <0xfee00000 0x1000>;
+		};
+
+		pci@3fc {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			compatible = "intel,ce4100-pci", "pci";
+			device_type = "pci";
+			bus-range = <0 0>;
+			ranges = <0x2000000 0 0xbffff000 0xbffff000 0 0x1000
+				  0x2000000 0 0xdffe0000 0xdffe0000 0 0x1000
+				  0x0000000 0 0x0	 0x0	    0 0x100>;
+
+			/* Secondary IO-APIC */
+			ioapic2: interrupt-controller@0,1 {
+				#interrupt-cells = <2>;
+				compatible = "intel,ce4100-ioapic";
+				interrupt-controller;
+				reg = <0x100 0x0 0x0 0x0 0x0>;
+				assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+			};
+
+			pci@1,0 {
+				#address-cells = <3>;
+				#size-cells = <2>;
+				compatible = "intel,ce4100-pci", "pci";
+				device_type = "pci";
+				bus-range = <1 1>;
+				reg = <0x0800 0x0 0x0 0x0 0x0>;
+				ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
+
+				interrupt-parent = <&ioapic2>;
+
+				display@2,0 {
+					compatible = "pci8086,2e5b.2",
+						   "pci8086,2e5b",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x11000 0x0 0x0 0x0 0x0>;
+					interrupts = <0 1>;
+				};
+
+				multimedia@3,0 {
+					compatible = "pci8086,2e5c.2",
+						   "pci8086,2e5c",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x11800 0x0 0x0 0x0 0x0>;
+					interrupts = <2 1>;
+				};
+
+				multimedia@4,0 {
+					compatible = "pci8086,2e5d.2",
+						   "pci8086,2e5d",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12000 0x0 0x0 0x0 0x0>;
+					interrupts = <4 1>;
+				};
+
+				multimedia@4,1 {
+					compatible = "pci8086,2e5e.2",
+						   "pci8086,2e5e",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12100 0x0 0x0 0x0 0x0>;
+					interrupts = <5 1>;
+				};
+
+				sound@6,0 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13000 0x0 0x0 0x0 0x0>;
+					interrupts = <6 1>;
+				};
+
+				sound@6,1 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13100 0x0 0x0 0x0 0x0>;
+					interrupts = <7 1>;
+				};
+
+				sound@6,2 {
+					compatible = "pci8086,2e60.2",
+						   "pci8086,2e60",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13200 0x0 0x0 0x0 0x0>;
+					interrupts = <8 1>;
+				};
+
+				display@8,0 {
+					compatible = "pci8086,2e61.2",
+						   "pci8086,2e61",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14000 0x0 0x0 0x0 0x0>;
+					interrupts = <9 1>;
+				};
+
+				display@8,1 {
+					compatible = "pci8086,2e62.2",
+						   "pci8086,2e62",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14100 0x0 0x0 0x0 0x0>;
+					interrupts = <10 1>;
+				};
+
+				multimedia@8,2 {
+					compatible = "pci8086,2e63.2",
+						   "pci8086,2e63",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x14200 0x0 0x0 0x0 0x0>;
+					interrupts = <11 1>;
+				};
+
+				entertainment-encryption@9,0 {
+					compatible = "pci8086,2e64.2",
+						   "pci8086,2e64",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x14800 0x0 0x0 0x0 0x0>;
+					interrupts = <12 1>;
+				};
+
+				localbus@a,0 {
+					compatible = "pci8086,2e65.2",
+						   "pci8086,2e65",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15000 0x0 0x0 0x0 0x0>;
+				};
+
+				serial@b,0 {
+					compatible = "pci8086,2e66.2",
+						   "pci8086,2e66",
+						   "pciclass070003",
+						   "pciclass0700";
+
+					reg = <0x15800 0x0 0x0 0x0 0x0>;
+					interrupts = <14 1>;
+				};
+
+				gpio@b,1 {
+					compatible = "pci8086,2e67.2",
+						   "pci8086,2e67",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15900 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+
+					gpio_intelce_grp0: gpio_intelce@0 {
+						compatible = "intel,intelce-gpio-controller";
+						#gpio-cells = <2>;
+						/* gpio 0 => 11 */
+						chip = <0>;
+						gpio-controller;
+					};
+
+					gpio_intelce_grp1: gpio_intelce@1 {
+						compatible = "intel,intelce-gpio-controller";
+						#gpio-cells = <2>;
+						/* gpio 12 => 14 */
+						gpio-controller;
+						chip = <1>;
+					};
+
+					gpio_intelce_grp2: gpio_intelce@2 {
+						compatible = "intel,intelce-gpio-controller";
+						#gpio-cells = <2>;
+						/* gpio 15 => 21 */
+						gpio-controller;
+						chip = <2>;
+					};
+
+					gpio_intelce_grp3: gpio_intelce@3 {
+						compatible = "intel,intelce-gpio-controller";
+						#gpio-cells = <2>;
+						/* gpio 22 => 25 */
+						gpio-controller;
+						chip = <3>;
+					};
+				};
+
+				i2c-controller@b,2 {
+					#address-cells = <2>;
+					#size-cells = <1>;
+					compatible = "pci8086,2e68.2",
+						   "pci8086,2e68",
+						   "pciclass,ff0000",
+						   "pciclass,ff00";
+
+					reg = <0x15a00 0x0 0x0 0x0 0x0>;
+					interrupts = <16 1>;
+					ranges = <0 0	0x02000000 0 0xdffe0500	0x100
+						  1 0	0x02000000 0 0xdffe0600	0x100
+						  2 0	0x02000000 0 0xdffe0700	0x100>;
+
+					i2c@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <0 0 0x100>;
+					};
+
+					i2c@1 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <1 0 0x100>;
+					};
+
+					i2c@2 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <2 0 0x100>;
+
+						pmu@60 {
+							#gpio-cells = <2>;
+							compatible = "freebox,pic16-pmu";
+							reg = <0x60>;
+							gpio-controller;
+						};
+					};
+				};
+
+				smard-card@b,3 {
+					compatible = "pci8086,2e69.2",
+						   "pci8086,2e69",
+						   "pciclass070500",
+						   "pciclass0705";
+
+					reg = <0x15b00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+				};
+
+				spi-controller@b,4 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible =
+						"pci8086,2e6a.2",
+						"pci8086,2e6a",
+						"pciclass,ff0000",
+						"pciclass,ff00";
+
+					reg = <0x15c00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+
+					dac@0 {
+						compatible = "ti,pcm1755";
+						reg = <0>;
+						spi-max-frequency = <115200>;
+					};
+
+					dac@1 {
+						compatible = "ti,pcm1609a";
+						reg = <1>;
+						spi-max-frequency = <115200>;
+					};
+
+					eeprom@2 {
+						compatible = "atmel,at93c46";
+						reg = <2>;
+						spi-max-frequency = <115200>;
+					};
+				};
+
+				multimedia@b,7 {
+					compatible = "pci8086,2e6d.2",
+						   "pci8086,2e6d",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15f00 0x0 0x0 0x0 0x0>;
+				};
+
+				ethernet@c,0 {
+					compatible = "pci8086,2e6e.2",
+						   "pci8086,2e6e",
+						   "pciclass020000",
+						   "pciclass0200";
+
+					reg = <0x16000 0x0 0x0 0x0 0x0>;
+					interrupts = <21 1>;
+					phy-link-gpio = <&gpio_intelce_grp2 5 0>;
+					fbxserial-mac-address = <0>;
+				};
+
+				clock@c,1 {
+					compatible = "pci8086,2e6f.2",
+						   "pci8086,2e6f",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x16100 0x0 0x0 0x0 0x0>;
+					interrupts = <3 1>;
+				};
+
+				usb@d,0 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16800 0x0 0x0 0x0 0x0>;
+					interrupts = <22 1>;
+				};
+
+				usb@d,1 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16900 0x0 0x0 0x0 0x0>;
+					interrupts = <22 1>;
+				};
+
+				sata@e,0 {
+					compatible = "pci8086,2e71.0",
+						   "pci8086,2e71",
+						   "pciclass010601",
+						   "pciclass0106";
+
+					reg = <0x17000 0x0 0x0 0x0 0x0>;
+					interrupts = <23 1>;
+				};
+
+				flash@f,0 {
+					compatible = "pci8086,701.1",
+						   "pci8086,701",
+						   "pciclass050100",
+						   "pciclass0501";
+
+					reg = <0x17800 0x0 0x0 0x0 0x0>;
+					interrupts = <13 1>;
+				};
+
+				entertainment-encryption@10,0 {
+					compatible = "pci8086,702.1",
+						   "pci8086,702",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x18000 0x0 0x0 0x0 0x0>;
+				};
+
+				co-processor@11,0 {
+					compatible = "pci8086,703.1",
+						   "pci8086,703",
+						   "pciclass0b4000",
+						   "pciclass0b40";
+
+					reg = <0x18800 0x0 0x0 0x0 0x0>;
+					interrupts = <1 1>;
+				};
+
+				multimedia@12,0 {
+					compatible = "pci8086,704.0",
+						   "pci8086,704",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x19000 0x0 0x0 0x0 0x0>;
+				};
+			};
+
+			isa@1f,0 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				compatible = "isa";
+				reg = <0xf800 0x0 0x0 0x0 0x0>;
+				ranges = <1 0 0 0 0 0x100>;
+
+				rtc@70 {
+					compatible = "intel,ce4100-rtc", "motorola,mc146818";
+					interrupts = <8 3>;
+					interrupt-parent = <&ioapic1>;
+					ctrl-reg = <2>;
+					freq-reg = <0x26>;
+					reg = <1 0x70 2>;
+				};
+			};
+		};
+	};
+};
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/config	2024-03-08 12:00:22.823277487 +0100
@@ -0,0 +1,4370 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 6.4.0 Kernel Configuration
+#
+CONFIG_CC_VERSION_TEXT="i686-linux-gnu-gcc (freebox) 12.3.0"
+CONFIG_CC_IS_GCC=y
+CONFIG_GCC_VERSION=120300
+CONFIG_CLANG_VERSION=0
+CONFIG_AS_IS_GNU=y
+CONFIG_AS_VERSION=24000
+CONFIG_LD_IS_BFD=y
+CONFIG_LD_VERSION=24000
+CONFIG_LLD_VERSION=0
+CONFIG_CC_CAN_LINK=y
+CONFIG_CC_CAN_LINK_STATIC=y
+CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
+CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
+CONFIG_TOOLS_SUPPORT_RELR=y
+CONFIG_CC_HAS_ASM_INLINE=y
+CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
+CONFIG_PAHOLE_VERSION=0
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_TABLE_SORT=y
+CONFIG_THREAD_INFO_IN_TASK=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE="/opt/toolchains/i686-glibc-2.37-gcc-12.3.0-binutils-2.40-gdb-13.1/bin/i686-linux-gnu-"
+# CONFIG_COMPILE_TEST is not set
+# CONFIG_WERROR is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_BUILD_SALT=""
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_HAVE_KERNEL_ZSTD=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_ZSTD is not set
+CONFIG_DEFAULT_INIT=""
+CONFIG_DEFAULT_HOSTNAME="fbx6hd"
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_WATCH_QUEUE is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_USELIB is not set
+CONFIG_AUDIT=y
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_GENERIC_MSI_IRQ=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_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_CONTEXT_TRACKING=y
+CONFIG_CONTEXT_TRACKING_IDLE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US=100
+# 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_BUILD=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_PREEMPTION=y
+CONFIG_PREEMPT_DYNAMIC=y
+# CONFIG_SCHED_CORE is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+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 is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_TREE_SRCU=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+# end of RCU Subsystem
+
+# CONFIG_IKCONFIG is not set
+# CONFIG_IKHEADERS is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+# CONFIG_FBX_DECRYPT_INITRD is not set
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+
+#
+# Scheduler features
+#
+# end of Scheduler features
+
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
+CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
+CONFIG_GCC11_NO_ARRAY_BOUNDS=y
+CONFIG_CC_NO_ARRAY_BOUNDS=y
+CONFIG_CGROUPS=y
+CONFIG_PAGE_COUNTER=y
+# CONFIG_CGROUP_FAVOR_DYNMODS is not set
+CONFIG_MEMCG=y
+CONFIG_MEMCG_KMEM=y
+# CONFIG_BLK_CGROUP is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_SCHED_MM_CID=y
+# CONFIG_CGROUP_PIDS is not set
+# CONFIG_CGROUP_RDMA is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+# CONFIG_CGROUP_PERF is not set
+# CONFIG_CGROUP_MISC is not set
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+# CONFIG_TIME_NS is not set
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_RD_ZSTD is not set
+# CONFIG_BOOT_CONFIG is not set
+# CONFIG_INITRAMFS_PRESERVE_MTIME is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_LD_ORPHAN_WARN=y
+CONFIG_LD_ORPHAN_WARN_LEVEL="warn"
+CONFIG_SYSCTL=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+# CONFIG_SYSFS_SYSCALL is not set
+# CONFIG_FHANDLE is not set
+CONFIG_POSIX_TIMERS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_FUTEX_PI=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_IO_URING is not set
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_MEMBARRIER=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_SELFTEST is not set
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
+# CONFIG_KCMP is not set
+CONFIG_RSEQ=y
+# CONFIG_DEBUG_RSEQ is not set
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+# CONFIG_PC104 is not set
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# end of Kernel Performance Events And Counters
+
+# CONFIG_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_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_X86_32_SMP=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_CC_HAS_SANE_STACKPROTECTOR=y
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+CONFIG_X86_FEATURE_NAMES=y
+CONFIG_X86_MPPARSE=y
+# CONFIG_GOLDFISH is not set
+# CONFIG_X86_CPU_RESCTRL is not set
+# CONFIG_X86_BIGSMP is not set
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_GOLDFISH is not set
+CONFIG_X86_INTEL_CE=y
+CONFIG_FBX6HD=y
+# CONFIG_X86_INTEL_LPSS is not set
+# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
+# CONFIG_IOSF_MBI is not set
+# CONFIG_X86_RDC321X is not set
+# CONFIG_X86_32_NON_STANDARD is not set
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+# CONFIG_X86_32_IRIS is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_HYPERVISOR_GUEST is not set
+# CONFIG_M486SX is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MELAN is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MCORE2 is not set
+CONFIG_MATOM=y
+# CONFIG_X86_GENERIC is not set
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=6
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_IA32_FEAT_CTL=y
+CONFIG_X86_VMX_FEATURE_NAMES=y
+CONFIG_PROCESSOR_SELECT=y
+CONFIG_CPU_SUP_INTEL=y
+# CONFIG_CPU_SUP_CYRIX_32 is not set
+# CONFIG_CPU_SUP_AMD is not set
+# CONFIG_CPU_SUP_HYGON is not set
+# CONFIG_CPU_SUP_CENTAUR is not set
+# CONFIG_CPU_SUP_TRANSMETA_32 is not set
+# CONFIG_CPU_SUP_UMC_32 is not set
+# CONFIG_CPU_SUP_ZHAOXIN is not set
+# CONFIG_CPU_SUP_VORTEX_32 is not set
+CONFIG_HPET_TIMER=y
+# CONFIG_DMI is not set
+CONFIG_NR_CPUS_RANGE_BEGIN=2
+CONFIG_NR_CPUS_RANGE_END=8
+CONFIG_NR_CPUS_DEFAULT=8
+CONFIG_NR_CPUS=2
+# CONFIG_SCHED_CLUSTER is not set
+CONFIG_SCHED_SMT=y
+# CONFIG_SCHED_MC is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCELOG_LEGACY is not set
+CONFIG_X86_MCE_INTEL=y
+# CONFIG_X86_ANCIENT_MCE is not set
+CONFIG_X86_MCE_THRESHOLD=y
+
+#
+# Performance monitoring
+#
+# CONFIG_PERF_EVENTS_INTEL_UNCORE is not set
+# CONFIG_PERF_EVENTS_INTEL_RAPL is not set
+CONFIG_PERF_EVENTS_INTEL_CSTATE=y
+# end of Performance monitoring
+
+# CONFIG_X86_LEGACY_VM86 is not set
+CONFIG_X86_16BIT=y
+CONFIG_X86_ESPFIX32=y
+# CONFIG_X86_IOPL_IOPERM is not set
+# CONFIG_TOSHIBA is not set
+CONFIG_X86_REBOOTFIXUPS=y
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_X86_PAE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0
+# CONFIG_X86_PMEM_LEGACY is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+# CONFIG_X86_UMIP is not set
+CONFIG_CC_HAS_IBT=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_EFI is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x100000
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
+# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlyprintk=ttyS0,115200 console=ttyS0,115200 root=/dev/nfs ip=dhcp dhcpclass=linux-fbx6hd pci=noacpi mem=650M debug iommu=off memtest=2"
+CONFIG_CMDLINE_OVERRIDE=y
+CONFIG_MODIFY_LDT_SYSCALL=y
+# CONFIG_STRICT_SIGALTSTACK_SIZE is not set
+# end of Processor type and features
+
+CONFIG_CC_HAS_SLS=y
+CONFIG_CC_HAS_RETURN_THUNK=y
+CONFIG_CC_HAS_ENTRY_PADDING=y
+CONFIG_FUNCTION_PADDING_CFI=0
+CONFIG_FUNCTION_PADDING_BYTES=4
+# CONFIG_SPECULATION_MITIGATIONS is not set
+CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
+
+#
+# Power management and ACPI options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+CONFIG_ARCH_SUPPORTS_ACPI=y
+CONFIG_ACPI=y
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_DEBUGGER is not set
+# CONFIG_ACPI_SPCR_TABLE is not set
+# CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set
+# CONFIG_ACPI_EC_DEBUGFS is not set
+# CONFIG_ACPI_AC is not set
+# CONFIG_ACPI_BATTERY is not set
+# CONFIG_ACPI_BUTTON is not set
+# CONFIG_ACPI_TINY_POWER_BUTTON is not set
+# CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_PROCESSOR is not set
+CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
+# CONFIG_ACPI_TABLE_UPGRADE is not set
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+# CONFIG_ACPI_CONTAINER is not set
+CONFIG_ACPI_HOTPLUG_IOAPIC=y
+# CONFIG_ACPI_SBS is not set
+# CONFIG_ACPI_HED is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY 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_CONFIGFS is not set
+# CONFIG_ACPI_FFH is not set
+# CONFIG_PMIC_OPREGION is not set
+CONFIG_X86_PM_TIMER=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+# end of CPU Frequency scaling
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_GOV_LADDER is not set
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_CPU_IDLE_GOV_TEO is not set
+# end of CPU Idle
+
+CONFIG_INTEL_IDLE=y
+# end of Power management and ACPI options
+
+#
+# Bus options (PCI etc.)
+#
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+CONFIG_PCI_GODIRECT=y
+# CONFIG_PCI_GOANY is not set
+CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+# CONFIG_ISA_BUS is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISA is not set
+# CONFIG_SCx200 is not set
+# CONFIG_ALIX is not set
+# CONFIG_NET5501 is not set
+# end of Bus options (PCI etc.)
+
+#
+# Binary Emulations
+#
+CONFIG_COMPAT_32=y
+# end of Binary Emulations
+
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_HAVE_KVM=y
+# CONFIG_VIRTUALIZATION is not set
+CONFIG_AS_AVX512=y
+CONFIG_AS_SHA1_NI=y
+CONFIG_AS_SHA256_NI=y
+CONFIG_AS_TPAUSE=y
+CONFIG_AS_GFNI=y
+
+#
+# General architecture-dependent options
+#
+CONFIG_CRASH_CORE=y
+CONFIG_HOTPLUG_SMT=y
+CONFIG_GENERIC_ENTRY=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_STATIC_CALL_SELFTEST is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=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_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
+CONFIG_HAVE_NMI=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_ARCH_WANTS_NO_INSTR=y
+CONFIG_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_MERGE_VMAS=y
+CONFIG_MMU_LAZY_TLB_REFCOUNT=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=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=y
+CONFIG_HAVE_ARCH_STACKLEAK=y
+CONFIG_HAVE_STACKPROTECTOR=y
+# CONFIG_STACKPROTECTOR is not set
+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_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_PAGE_SIZE_LESS_THAN_64KB=y
+CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
+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 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_HAS_MEM_ENCRYPT=y
+CONFIG_HAVE_STATIC_CALL=y
+CONFIG_HAVE_PREEMPT_DYNAMIC=y
+CONFIG_HAVE_PREEMPT_DYNAMIC_CALL=y
+CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_SPLIT_ARG64=y
+CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y
+CONFIG_DYNAMIC_SIGFRAME=y
+CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=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 is not set
+CONFIG_FUNCTION_ALIGNMENT_4B=y
+CONFIG_FUNCTION_ALIGNMENT=4
+# 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 is not set
+# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set
+# 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_TRIM_UNUSED_KSYMS=y
+CONFIG_UNUSED_KSYMS_WHITELIST=""
+CONFIG_UNUSED_KSYMS_WHITELIST_SYMS="dib7000p_attach dib0070_attach"
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
+CONFIG_BLK_DEV_BSG_COMMON=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_DEV_ZONED is not set
+CONFIG_BLK_WBT=y
+# CONFIG_BLK_WBT_MQ is not set
+# 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
+# CONFIG_OF_PARTITION is not set
+# end of Partition Types
+
+CONFIG_BLK_MQ_PCI=y
+
+#
+# IO Schedulers
+#
+CONFIG_MQ_IOSCHED_DEADLINE=y
+# CONFIG_MQ_IOSCHED_KYBER is not set
+# CONFIG_IOSCHED_BFQ is not set
+# end of IO Schedulers
+
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_FREEZER=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+# end of Executable file formats
+
+#
+# Memory Management options
+#
+# CONFIG_SWAP is not set
+
+#
+# SLAB allocator options
+#
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLUB_TINY is not set
+CONFIG_SLAB_MERGE_DEFAULT=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SLAB_FREELIST_HARDENED is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_SLUB_CPU_PARTIAL is not set
+# end of SLAB allocator options
+
+# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set
+# CONFIG_COMPAT_BRK is not set
+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_SPLIT_PTLOCK_CPUS=4
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+# CONFIG_COMPACTION is not set
+# CONFIG_PAGE_REPORTING is not set
+CONFIG_PHYS_ADDR_T_64BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_PAGE_FRAG_CACHE_ORDER=3
+# CONFIG_MEMORY_FAILURE is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+# CONFIG_CMA is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y
+CONFIG_ARCH_HAS_ZONE_DMA_SET=y
+# CONFIG_ZONE_DMA is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_PERCPU_STATS is not set
+
+#
+# GUP_TEST needs to have DEBUG_FS enabled
+#
+CONFIG_GUP_GET_PXX_LOW_HIGH=y
+# CONFIG_DMAPOOL_TEST is not set
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
+CONFIG_KMAP_LOCAL=y
+# CONFIG_SECRETMEM is not set
+# CONFIG_ANON_VMA_NAME is not set
+# CONFIG_USERFAULTFD is not set
+# CONFIG_LRU_GEN is not set
+
+#
+# Data Access Monitoring
+#
+# CONFIG_DAMON is not set
+# end of Data Access Monitoring
+# end of Memory Management options
+
+CONFIG_NET=y
+CONFIG_NET_PROMISC_MESSAGES=y
+CONFIG_SKB_EXTENSIONS=y
+
+#
+# Networking options
+#
+CONFIG_NETSKBPAD=16
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+CONFIG_UNIX_SCM=y
+CONFIG_AF_UNIX_OOB=y
+# CONFIG_UNIX_ABSTRACT_IGNORE_NETNS is not set
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_TLS is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# 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=y
+CONFIG_XFRM_ESP=y
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_NET_HANDSHAKE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_FOU is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_ESP_OFFLOAD is not set
+# CONFIG_INET_ESPINTCP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TABLE_PERTURB_ORDER=16
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_IPV6_ILA is not set
+# CONFIG_IPV6_VTI is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_IPV6_SEG6_LWTUNNEL is not set
+# CONFIG_IPV6_SEG6_HMAC is not set
+# CONFIG_IPV6_RPL_LWTUNNEL is not set
+# CONFIG_IPV6_IOAM6_LWTUNNEL is not set
+# CONFIG_MPTCP is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_INGRESS is not set
+# CONFIG_NETFILTER_EGRESS is not set
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NETFILTER_NETLINK_OSF is not set
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_LOG_SYSLOG=y
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_ZONES is not set
+CONFIG_NF_CONNTRACK_PROCFS=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# 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 is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_REDIRECT=y
+# CONFIG_NF_TABLES is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+# CONFIG_NETFILTER_XT_MARK is not set
+# CONFIG_NETFILTER_XT_CONNMARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+CONFIG_NETFILTER_XT_NAT=y
+# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_MASQUERADE is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# end of Core Netfilter Configuration
+
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_FFN is not set
+CONFIG_NF_DEFRAG_IPV4=y
+# CONFIG_NF_SOCKET_IPV4 is not set
+# CONFIG_NF_TPROXY_IPV4 is not set
+# CONFIG_NF_DUP_IPV4 is not set
+# CONFIG_NF_LOG_ARP is not set
+CONFIG_NF_LOG_IPV4=y
+CONFIG_NF_REJECT_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+CONFIG_IP_NF_NAT=y
+# CONFIG_IP_NF_TARGET_MASQUERADE is not set
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+CONFIG_IP_NF_TARGET_REDIRECT=y
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# end of IP: Netfilter Configuration
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IPV6_FFN is not set
+# CONFIG_NF_SOCKET_IPV6 is not set
+# CONFIG_NF_TPROXY_IPV6 is not set
+# CONFIG_NF_DUP_IPV6 is not set
+CONFIG_NF_REJECT_IPV6=y
+CONFIG_NF_LOG_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_MATCH_SRH is not set
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+# CONFIG_IP6_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP6_NF_MANGLE is not set
+# CONFIG_IP6_NF_RAW is not set
+# CONFIG_IP6_NF_NAT is not set
+# end of IPv6: Netfilter Configuration
+
+CONFIG_NF_DEFRAG_IPV6=y
+# CONFIG_NF_CONNTRACK_BRIDGE is not set
+# CONFIG_BPFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_FBXATM is not set
+# CONFIG_FBXBRIDGE is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q_MVRP is not set
+# CONFIG_VLAN_FBX is not set
+# CONFIG_LLC2 is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_NET_NSH is not set
+# CONFIG_HSR is not set
+# 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_MAX_SKB_FRAGS=17
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+CONFIG_XPS=y
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# 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_BT=y
+CONFIG_BT_BREDR=y
+# CONFIG_BT_RFCOMM is not set
+# CONFIG_BT_BNEP is not set
+# CONFIG_BT_HIDP is not set
+CONFIG_BT_HS=y
+# CONFIG_BT_LE is not set
+# CONFIG_BT_LEDS is not set
+# CONFIG_BT_MSFTEXT is not set
+# CONFIG_BT_AOSPEXT is not set
+# CONFIG_BT_SELFTEST is not set
+# CONFIG_BT_FEATURE_DEBUG is not set
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_INTEL=y
+CONFIG_BT_HCIBTUSB=y
+# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set
+# CONFIG_BT_HCIBTUSB_POLL_SYNC is not set
+# CONFIG_BT_HCIBTUSB_BCM is not set
+# CONFIG_BT_HCIBTUSB_MTK is not set
+# CONFIG_BT_HCIBTUSB_RTL is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBCM4377 is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+# end of Bluetooth device drivers
+
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_MCTP is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# 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_GRO_CELLS=y
+# CONFIG_FAILOVER is not set
+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 is not set
+# CONFIG_PCIEASPM is not set
+# CONFIG_PCIE_PTM is not set
+CONFIG_PCI_MSI=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_PCI_LOCKLESS_CONFIG=y
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+CONFIG_PCI_LABEL=y
+# CONFIG_PCIE_BUS_TUNE_OFF is not set
+CONFIG_PCIE_BUS_DEFAULT=y
+# CONFIG_PCIE_BUS_SAFE is not set
+# CONFIG_PCIE_BUS_PERFORMANCE is not set
+# CONFIG_PCIE_BUS_PEER2PEER is not set
+# CONFIG_VGA_ARB is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCI controller drivers
+#
+# CONFIG_PCI_FTPCI100 is not set
+# CONFIG_PCI_HOST_GENERIC is not set
+# CONFIG_PCIE_MICROCHIP_HOST is not set
+# CONFIG_PCIE_XILINX is not set
+
+#
+# Cadence-based PCIe controllers
+#
+# CONFIG_PCIE_CADENCE_PLAT_HOST is not set
+# CONFIG_PCI_J721E_HOST is not set
+# end of Cadence-based PCIe controllers
+
+#
+# DesignWare-based PCIe controllers
+#
+# CONFIG_PCI_MESON is not set
+# CONFIG_PCIE_INTEL_GW is not set
+# CONFIG_PCIE_DW_PLAT_HOST is not set
+# end of DesignWare-based PCIe controllers
+
+#
+# Mobiveil-based PCIe controllers
+#
+# end of Mobiveil-based PCIe controllers
+# 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_UEVENT_HELPER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_DEVTMPFS_SAFE is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+
+#
+# Firmware loader
+#
+CONFIG_FW_LOADER=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER is not set
+# CONFIG_FW_LOADER_COMPRESS is not set
+# CONFIG_FW_UPLOAD is not set
+# end of Firmware loader
+
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CPU_VULNERABILITIES=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=m
+# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set
+# end of Generic Driver Options
+
+#
+# Bus devices
+#
+# CONFIG_MHI_BUS is not set
+# CONFIG_MHI_BUS_EP is not set
+# end of Bus devices
+
+# CONFIG_CONNECTOR is not set
+
+#
+# Firmware Drivers
+#
+
+#
+# ARM System Control and Management Interface Protocol
+#
+# end of ARM System Control and Management Interface Protocol
+
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+# CONFIG_FW_CFG_SYSFS is not set
+# CONFIG_SYSFB_SIMPLEFB is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# Tegra firmware driver
+#
+# end of Tegra firmware driver
+# end of Firmware Drivers
+
+# CONFIG_GNSS is not set
+CONFIG_FREEBOX_PROCFS=y
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_ERASE_PRINTK=y
+
+#
+# Partition parsers
+#
+# CONFIG_MTD_AR7_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_OF_PARTS_IGNORE_RO is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_FBX6HD_PARTS=y
+# CONFIG_MTD_FBX6HD_PARTS_WRITE_ALL is not set
+# end of Partition parsers
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+
+#
+# Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK.
+#
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# end of RAM/ROM/Flash chip drivers
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+# end of Mapping drivers for chip access
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_BCH_CONST_M=13
+CONFIG_BCH_CONST_T=4
+# end of Self-contained MTD device drivers
+
+#
+# NAND
+#
+CONFIG_MTD_NAND_CORE=y
+# CONFIG_MTD_ONENAND is not set
+CONFIG_MTD_RAW_NAND=y
+
+#
+# Raw/parallel NAND flash controllers
+#
+CONFIG_MTD_FORCE_BAD_BLOCK_ERASE=y
+# CONFIG_MTD_NAND_DENALI_PCI is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+CONFIG_MTD_NAND_DENALI_FBX=m
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_CS553X is not set
+# CONFIG_MTD_NAND_MXIC is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_CADENCE is not set
+# CONFIG_MTD_NAND_ARASAN is not set
+# CONFIG_MTD_NAND_INTEL_LGM is not set
+
+#
+# Misc
+#
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_RICOH is not set
+# CONFIG_MTD_NAND_DISKONCHIP 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=y
+# CONFIG_MTD_NAND_ECC_MXIC is not set
+# end of ECC engine support
+# end of NAND
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# end of LPDDR & LPDDR2 PCM memory drivers
+
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+# CONFIG_MTD_HYPERBUS is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_DTB_BUILTIN_LIST=""
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+# CONFIG_OF_CONFIGFS is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_CDROM=y
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_ZRAM is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_UBLK is not set
+
+#
+# NVME Support
+#
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_NVME_FC is not set
+# CONFIG_NVME_TCP is not set
+# end of NVME Support
+
+#
+# Misc devices
+#
+# CONFIG_WINTEGRA_MMAP 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_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+CONFIG_INTELCE_PIC16PMU=y
+# CONFIG_PCH_PHUB is not set
+# CONFIG_FBXSERIAL_OF 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_OPEN_DICE is not set
+# CONFIG_VCPU_STALL_DETECTOR is not set
+# CONFIG_DGASP is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_IDT_89HPESX is not set
+# CONFIG_EEPROM_EE1004 is not set
+# CONFIG_EEPROM_EE1004_RAW is not set
+# end of EEPROM support
+
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# end of Texas Instruments shared transport line discipline
+
+# CONFIG_SENSORS_LIS3_I2C is not set
+# 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 is not set
+# 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_PVPANIC is not set
+# CONFIG_GP_PCI1XXXX is not set
+
+#
+# RemoTI support
+#
+CONFIG_REMOTI=y
+CONFIG_REMOTI_LEDS=y
+# CONFIG_REMOTI_GPIO is not set
+CONFIG_REMOTI_USER=y
+# end of RemoTI support
+
+#
+# HDMI CEC support
+#
+CONFIG_HDMI_CEC=y
+CONFIG_HDMI_CEC_REMOTI=y
+# end of HDMI CEC support
+# end of Misc devices
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI_COMMON=y
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_CHR_DEV_SG is not set
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# end of SCSI Transports
+
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# end of SCSI device support
+
+CONFIG_ATA=y
+CONFIG_SATA_HOST=y
+CONFIG_PATA_TIMINGS=y
+CONFIG_ATA_VERBOSE_ERROR=y
+# CONFIG_ATA_FORCE is not set
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_MOBILE_LPM_POLICY=0
+# CONFIG_SATA_AHCI_PLATFORM is not set
+# CONFIG_AHCI_DWC is not set
+# CONFIG_AHCI_CEVA is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_SATA_ACARD_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_ATA_SFF is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# end of IEEE 1394 (FireWire) support
+
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_WIREGUARD is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_GENEVE is not set
+# CONFIG_BAREUDP is not set
+# CONFIG_GTP is not set
+# CONFIG_AMT is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ASIX is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_CX_ECAT is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_DAVICOM is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_ENGLEDER is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FUNGIBLE is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
+# CONFIG_NET_VENDOR_I825XX is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+CONFIG_E1000=y
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_I40E is not set
+# CONFIG_I40EVF is not set
+# CONFIG_ICE is not set
+# CONFIG_FM10K is not set
+# CONFIG_IGC is not set
+# CONFIG_JME is not set
+# CONFIG_NET_VENDOR_LITEX is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
+# CONFIG_NET_VENDOR_MICROSOFT is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VERTEXCOM is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XILINX is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PSE_CONTROLLER is not set
+# CONFIG_MDIO_DEVICE is not set
+
+#
+# PCS device drivers
+#
+# end of PCS device drivers
+
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+# CONFIG_WAN is not set
+
+#
+# Wireless WAN
+#
+# CONFIG_WWAN is not set
+# end of Wireless WAN
+
+# CONFIG_VMXNET3 is not set
+# CONFIG_FUJITSU_ES is not set
+# CONFIG_NET_FAILOVER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_LEDS is not set
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_ZHENHUA is not set
+# CONFIG_JOYSTICK_AS5011 is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
+# CONFIG_JOYSTICK_PXRC is not set
+# CONFIG_JOYSTICK_QWIIC is not set
+# CONFIG_JOYSTICK_FSIA6B is not set
+# CONFIG_JOYSTICK_SENSEHAT is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_APANEL 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_WISTRON_BTNS is not set
+# CONFIG_INPUT_ATLAS_BTNS is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# 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_IQS7222 is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_INPUT_SMSC_CAP1066 is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+# CONFIG_GAMEPORT is not set
+# end of Hardware I/O ports
+# end of Input device support
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_LEGACY_TIOCSTI is not set
+CONFIG_LDISC_AUTOLOAD=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_PNP=y
+# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCILIB=y
+CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_EXAR is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+# CONFIG_SERIAL_8250_PCI1XXXX is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_RT288X is not set
+# CONFIG_SERIAL_8250_LPSS is not set
+# CONFIG_SERIAL_8250_MID is not set
+# CONFIG_SERIAL_8250_PERICOM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SIFIVE is not set
+# 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_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_RP2 is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_FSL_LINFLEXUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR 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_SERIAL_DEV_BUS is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_VIRTIO_CONSOLE is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_INTEL is not set
+# CONFIG_HW_RANDOM_AMD is not set
+# CONFIG_HW_RANDOM_BA431 is not set
+# CONFIG_HW_RANDOM_GEODE is not set
+# CONFIG_HW_RANDOM_VIA is not set
+# CONFIG_HW_RANDOM_CCTRNG is not set
+# CONFIG_HW_RANDOM_XIPHERA is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVPHYSMEM=y
+# CONFIG_NVRAM is not set
+CONFIG_DEVPORT=y
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+# CONFIG_XILLYBUS is not set
+# CONFIG_XILLYUSB is not set
+# end of Character devices
+
+#
+# Diag Support
+#
+# CONFIG_DIAG_CHAR is not set
+# end of Diag Support
+
+#
+# DIAG traffic over USB
+#
+# end of DIAG traffic over USB
+
+#
+# DIAG traffic over QRTR
+#
+# end of DIAG traffic over QRTR
+
+#
+# HSIC/SMUX support for DIAG
+#
+# end of HSIC/SMUX support for DIAG
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_ACPI_I2C_OPREGION is not set
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_AMD_MP2 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_ISMT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_NVIDIA_GPU is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_I2C_SCMI is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_DESIGNWARE_PCI is not set
+# CONFIG_I2C_EG20T is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+CONFIG_I2C_PXA=y
+CONFIG_I2C_PXA_PCI=y
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_CP2615 is not set
+# CONFIG_I2C_PCI1XXXX is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_VIRTIO is not set
+# end of I2C Hardware Bus support
+
+# CONFIG_I2C_STUB 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
+# CONFIG_PPS is not set
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+# end of PTP clock support
+
+# CONFIG_PINCTRL is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_FASTPATH_LIMIT=512
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_ACPI=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_CDEV_V1=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_AMDPT is not set
+# CONFIG_GPIO_CADENCE is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_FTGPIO010 is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_HLWD is not set
+# CONFIG_GPIO_MB86S7X is not set
+# CONFIG_GPIO_SIFIVE is not set
+# CONFIG_GPIO_VX855 is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_AMD_FCH is not set
+# end of Memory mapped GPIO drivers
+
+#
+# Port-mapped I/O GPIO drivers
+#
+# CONFIG_GPIO_F7188X is not set
+# CONFIG_GPIO_IT87 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
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_FXL6408 is not set
+# CONFIG_GPIO_GW_PLD is not set
+# CONFIG_GPIO_MAX7300 is not set
+# 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
+#
+# CONFIG_GPIO_ELKHARTLAKE is not set
+# end of MFD GPIO expanders
+
+#
+# PCI GPIO expanders
+#
+# CONFIG_GPIO_AMD8111 is not set
+# CONFIG_GPIO_BT8XX 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
+# CONFIG_GPIO_SODAVILLE is not set
+# end of PCI GPIO expanders
+
+#
+# USB GPIO expanders
+#
+# end of USB GPIO expanders
+
+#
+# Virtual GPIO drivers
+#
+# CONFIG_GPIO_AGGREGATOR is not set
+# CONFIG_GPIO_LATCH is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_SIM is not set
+# end of Virtual GPIO drivers
+
+# CONFIG_FREEBOX_GPIO is not set
+# CONFIG_FREEBOX_GPIO_DT is not set
+# CONFIG_FREEBOX_JTAG is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_RESET is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_POWER_SUPPLY_HWMON is not set
+# CONFIG_IP5XXX_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_SAMSUNG_SDI 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
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# 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_DETECTOR_MAX14656 is not set
+# CONFIG_CHARGER_MAX77976 is not set
+# CONFIG_CHARGER_BQ2415X 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_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_BATTERY_UG3105 is not set
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM1177 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+CONFIG_SENSORS_ADT7475=y
+# CONFIG_SENSORS_AHT10 is not set
+# CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set
+# CONFIG_SENSORS_AS370 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_AXI_FAN_CONTROL is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_CORSAIR_CPRO is not set
+# CONFIG_SENSORS_CORSAIR_PSU is not set
+# CONFIG_SENSORS_DRIVETEMP is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_DELL_SMM is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_G762 is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_I5500 is not set
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_POWR1220 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LTC2945 is not set
+# CONFIG_SENSORS_LTC2947_I2C is not set
+# CONFIG_SENSORS_LTC2990 is not set
+# CONFIG_SENSORS_LTC2992 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4222 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4260 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX127 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX31730 is not set
+# CONFIG_SENSORS_MAX31760 is not set
+# CONFIG_SENSORS_MAX6620 is not set
+# CONFIG_SENSORS_MAX6621 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MAX6697 is not set
+# CONFIG_SENSORS_MAX31790 is not set
+# CONFIG_SENSORS_MC34VR500 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_TC654 is not set
+# CONFIG_SENSORS_TPS23861 is not set
+# CONFIG_SENSORS_MR75203 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+CONFIG_SENSORS_LM85=y
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LM95234 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_NCT6775_I2C is not set
+# CONFIG_SENSORS_NCT7802 is not set
+# CONFIG_SENSORS_NPCM7XX is not set
+# CONFIG_SENSORS_NZXT_KRAKEN2 is not set
+# CONFIG_SENSORS_NZXT_SMART2 is not set
+# CONFIG_SENSORS_OCC_P8_I2C is not set
+# CONFIG_SENSORS_OXP is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SBTSI is not set
+# CONFIG_SENSORS_SBRMI is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SHT3x is not set
+# CONFIG_SENSORS_SHT4x is not set
+# CONFIG_SENSORS_SHTC1 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC2305 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_STTS751 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_ADC128D818 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA209 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_INA238 is not set
+# CONFIG_SENSORS_INA3221 is not set
+# CONFIG_SENSORS_TC74 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP103 is not set
+# CONFIG_SENSORS_TMP108 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_TMP464 is not set
+# CONFIG_SENSORS_TMP513 is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83773G is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LD6710_FBX is not set
+# CONFIG_SENSORS_AP806 is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_SENSORS_ACPI_POWER is not set
+# CONFIG_SENSORS_ATK0110 is not set
+# CONFIG_SENSORS_ASUS_EC is not set
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_NETLINK is not set
+# CONFIG_THERMAL_STATISTICS is not set
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_OF=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_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_CPU_THERMAL is not set
+# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_THERMAL_MMIO is not set
+
+#
+# Intel thermal drivers
+#
+# CONFIG_INTEL_POWERCLAMP is not set
+CONFIG_X86_THERMAL_VECTOR=y
+CONFIG_INTEL_TCC=y
+CONFIG_X86_PKG_TEMP_THERMAL=y
+# CONFIG_INTEL_SOC_DTS_THERMAL is not set
+
+#
+# ACPI INT340X thermal drivers
+#
+# end of ACPI INT340X thermal drivers
+
+# CONFIG_INTEL_PCH_THERMAL is not set
+# CONFIG_INTEL_TCC_COOLING is not set
+# CONFIG_INTEL_HFI_THERMAL is not set
+# end of Intel thermal drivers
+
+# CONFIG_FREEBOX_WATCHDOG is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CS5535 is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_SMPRO is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC 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_MAX597X is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_GATEWORKS_GSC is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_MP2629 is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_INTEL_LPSS_ACPI is not set
+# CONFIG_MFD_INTEL_LPSS_PCI 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_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77650 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77714 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6360 is not set
+# CONFIG_MFD_MT6370 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_NTXEC is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_SY7636A is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RT4831 is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RT5120 is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_TI_LMU is not set
+# CONFIG_MFD_PALMAS 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_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TI_LP87565 is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS65219 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TIMBERDALE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TQMX86 is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_MFD_LOCHNAGAR is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_ROHM_BD718XX is not set
+# CONFIG_MFD_ROHM_BD71828 is not set
+# CONFIG_MFD_ROHM_BD957XMUF is not set
+# CONFIG_MFD_STPMIC1 is not set
+# CONFIG_MFD_STMFX is not set
+# CONFIG_MFD_FBXGWR_PMU is not set
+# CONFIG_MFD_ATC260X_I2C is not set
+# CONFIG_MFD_QCOM_PM8008 is not set
+# CONFIG_MFD_RSMU_I2C is not set
+# end of Multifunction device drivers
+
+# CONFIG_REGULATOR is not set
+CONFIG_RC_CORE=y
+# CONFIG_LIRC is not set
+CONFIG_RC_MAP=y
+CONFIG_RC_DECODERS=y
+# CONFIG_IR_IMON_DECODER is not set
+# CONFIG_IR_JVC_DECODER is not set
+CONFIG_IR_MCE_KBD_DECODER=y
+# CONFIG_IR_NEC_DECODER is not set
+# CONFIG_IR_RC5_DECODER is not set
+CONFIG_IR_RC6_DECODER=y
+# CONFIG_IR_RCMM_DECODER is not set
+# CONFIG_IR_SANYO_DECODER is not set
+# CONFIG_IR_SHARP_DECODER is not set
+# CONFIG_IR_SONY_DECODER is not set
+# CONFIG_IR_XMP_DECODER is not set
+CONFIG_RC_DEVICES=y
+# CONFIG_IR_ENE is not set
+# CONFIG_IR_FINTEK is not set
+# CONFIG_IR_GPIO_CIR is not set
+# CONFIG_IR_HIX5HD2 is not set
+# CONFIG_IR_IGORPLUGUSB is not set
+# CONFIG_IR_IGUANA is not set
+# CONFIG_IR_IMON is not set
+# CONFIG_IR_IMON_RAW is not set
+# CONFIG_IR_ITE_CIR is not set
+CONFIG_IR_MCEUSB=y
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_REDRAT3 is not set
+# CONFIG_IR_SERIAL is not set
+# CONFIG_IR_STREAMZAP is not set
+# CONFIG_IR_TOY is not set
+# CONFIG_IR_TTUSBIR is not set
+# CONFIG_IR_WINBOND_CIR is not set
+# CONFIG_RC_ATI_REMOTE is not set
+# CONFIG_RC_LOOPBACK is not set
+# CONFIG_RC_XBOX_DVD is not set
+
+#
+# CEC support
+#
+# CONFIG_MEDIA_CEC_SUPPORT is not set
+# end of CEC support
+
+CONFIG_MEDIA_SUPPORT=y
+# CONFIG_MEDIA_SUPPORT_FILTER is not set
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+
+#
+# Media device types
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_SDR_SUPPORT=y
+CONFIG_MEDIA_PLATFORM_SUPPORT=y
+CONFIG_MEDIA_TEST_SUPPORT=y
+# end of Media device types
+
+#
+# Media core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_DVB_CORE=y
+# end of Media core support
+
+#
+# Digital TV options
+#
+# CONFIG_DVB_NET is not set
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set
+# CONFIG_DVB_ULE_DEBUG is not set
+# end of Digital TV options
+
+#
+# Media drivers
+#
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+
+#
+# Analog TV USB devices
+#
+
+#
+# Analog/digital TV USB devices
+#
+
+#
+# Digital TV USB devices
+#
+# CONFIG_DVB_AS102 is not set
+# CONFIG_DVB_B2C2_FLEXCOP_USB is not set
+CONFIG_DVB_USB_V2=y
+CONFIG_DVB_USB_AF9035=m
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_AU6610 is not set
+# CONFIG_DVB_USB_AZ6007 is not set
+# CONFIG_DVB_USB_CE6230 is not set
+# CONFIG_DVB_USB_DVBSKY is not set
+# CONFIG_DVB_USB_EC168 is not set
+# CONFIG_DVB_USB_GL861 is not set
+# CONFIG_DVB_USB_LME2510 is not set
+# CONFIG_DVB_USB_MXL111SF is not set
+# CONFIG_DVB_USB_ZD1301 is not set
+CONFIG_DVB_USB=y
+# CONFIG_DVB_USB_DEBUG is not set
+# CONFIG_DVB_USB_A800 is not set
+# CONFIG_DVB_USB_AF9005 is not set
+# CONFIG_DVB_USB_AZ6027 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_CXUSB is not set
+CONFIG_DVB_USB_DIB0700=m
+# CONFIG_DVB_USB_DIBUSB_MB is not set
+# CONFIG_DVB_USB_DIBUSB_MC is not set
+# CONFIG_DVB_USB_DIGITV is not set
+# CONFIG_DVB_USB_DTT200U is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_GP8PSK is not set
+# CONFIG_DVB_USB_M920X is not set
+# CONFIG_DVB_USB_NOVA_T_USB2 is not set
+# CONFIG_DVB_USB_OPERA1 is not set
+# CONFIG_DVB_USB_PCTV452E is not set
+# CONFIG_DVB_USB_TECHNISAT_USB2 is not set
+# CONFIG_DVB_USB_TTUSB2 is not set
+# CONFIG_DVB_USB_UMT_010 is not set
+# CONFIG_DVB_USB_VP702X is not set
+# CONFIG_DVB_USB_VP7045 is not set
+# CONFIG_SMS_USB_DRV is not set
+# CONFIG_DVB_TTUSB_BUDGET is not set
+# CONFIG_DVB_TTUSB_DEC is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+
+#
+# Software defined radio USB devices
+#
+# CONFIG_MEDIA_PCI_SUPPORT is not set
+# CONFIG_MEDIA_PLATFORM_DRIVERS is not set
+# CONFIG_DVB_TEST_DRIVERS is not set
+CONFIG_CYPRESS_FIRMWARE=y
+# end of Media drivers
+
+#
+# Media ancillary drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=y
+
+#
+# Customize TV tuners
+#
+# CONFIG_MEDIA_TUNER_FC0011 is not set
+# CONFIG_MEDIA_TUNER_FC0012 is not set
+# CONFIG_MEDIA_TUNER_FC0013 is not set
+CONFIG_MEDIA_TUNER_IT913X=m
+# CONFIG_MEDIA_TUNER_M88RS6000T is not set
+# CONFIG_MEDIA_TUNER_MAX2165 is not set
+# CONFIG_MEDIA_TUNER_MC44S803 is not set
+# CONFIG_MEDIA_TUNER_MT2060 is not set
+# CONFIG_MEDIA_TUNER_MT2063 is not set
+# CONFIG_MEDIA_TUNER_MT20XX is not set
+# CONFIG_MEDIA_TUNER_MT2131 is not set
+# CONFIG_MEDIA_TUNER_MT2266 is not set
+# CONFIG_MEDIA_TUNER_MXL301RF is not set
+# CONFIG_MEDIA_TUNER_MXL5005S is not set
+# CONFIG_MEDIA_TUNER_MXL5007T is not set
+# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set
+# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
+# CONFIG_MEDIA_TUNER_QT1010 is not set
+# CONFIG_MEDIA_TUNER_R820T is not set
+# CONFIG_MEDIA_TUNER_SI2157 is not set
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA18212 is not set
+# CONFIG_MEDIA_TUNER_TDA18218 is not set
+# CONFIG_MEDIA_TUNER_TDA18250 is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+# CONFIG_MEDIA_TUNER_TEA5767 is not set
+# CONFIG_MEDIA_TUNER_TUA9001 is not set
+# CONFIG_MEDIA_TUNER_XC2028 is not set
+# CONFIG_MEDIA_TUNER_XC4000 is not set
+# CONFIG_MEDIA_TUNER_XC5000 is not set
+# end of Customize TV tuners
+
+#
+# Customise DVB Frontends
+#
+
+#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_MXL5XX is not set
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+# CONFIG_DVB_STV090x is not set
+# CONFIG_DVB_STV0910 is not set
+# CONFIG_DVB_STV6110x is not set
+# CONFIG_DVB_STV6111 is not set
+
+#
+# Multistandard (cable + terrestrial) frontends
+#
+# CONFIG_DVB_DRXK is not set
+# CONFIG_DVB_MN88472 is not set
+# CONFIG_DVB_MN88473 is not set
+# CONFIG_DVB_SI2165 is not set
+# CONFIG_DVB_TDA18271C2DD is not set
+
+#
+# DVB-S (satellite) frontends
+#
+# CONFIG_DVB_CX24110 is not set
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_CX24117 is not set
+# CONFIG_DVB_CX24120 is not set
+# CONFIG_DVB_CX24123 is not set
+# CONFIG_DVB_DS3000 is not set
+# CONFIG_DVB_MB86A16 is not set
+# CONFIG_DVB_MT312 is not set
+# CONFIG_DVB_S5H1420 is not set
+# CONFIG_DVB_SI21XX is not set
+# CONFIG_DVB_STB6000 is not set
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STV0299 is not set
+# CONFIG_DVB_STV0900 is not set
+# CONFIG_DVB_STV6110 is not set
+# CONFIG_DVB_TDA10071 is not set
+# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8083 is not set
+# CONFIG_DVB_TDA8261 is not set
+# CONFIG_DVB_TDA826X is not set
+# CONFIG_DVB_TS2020 is not set
+# CONFIG_DVB_TUA6100 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
+# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_VES1X93 is not set
+# CONFIG_DVB_ZL10036 is not set
+# CONFIG_DVB_ZL10039 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+# CONFIG_DVB_CX22700 is not set
+# CONFIG_DVB_CX22702 is not set
+# CONFIG_DVB_CXD2820R is not set
+# CONFIG_DVB_CXD2841ER is not set
+# CONFIG_DVB_DIB3000MB is not set
+# CONFIG_DVB_DIB3000MC is not set
+CONFIG_DVB_DIB7000M=y
+CONFIG_DVB_DIB7000P=y
+# CONFIG_DVB_DIB9000 is not set
+# CONFIG_DVB_DRXD is not set
+# CONFIG_DVB_EC100 is not set
+# CONFIG_DVB_L64781 is not set
+# CONFIG_DVB_MT352 is not set
+# CONFIG_DVB_NXT6000 is not set
+# CONFIG_DVB_S5H1432 is not set
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_STV0367 is not set
+# CONFIG_DVB_TDA10048 is not set
+# CONFIG_DVB_TDA1004X is not set
+# CONFIG_DVB_ZD1301_DEMOD is not set
+# CONFIG_DVB_ZL10353 is not set
+
+#
+# DVB-C (cable) frontends
+#
+# CONFIG_DVB_STV0297 is not set
+# CONFIG_DVB_TDA10021 is not set
+# CONFIG_DVB_TDA10023 is not set
+# CONFIG_DVB_VES1820 is not set
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+# CONFIG_DVB_AU8522_DTV is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LG2160 is not set
+# CONFIG_DVB_LGDT3305 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_MXL692 is not set
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_S5H1409 is not set
+# CONFIG_DVB_S5H1411 is not set
+
+#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_DIB8000 is not set
+# CONFIG_DVB_MB86A20S is not set
+# CONFIG_DVB_S921 is not set
+
+#
+# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_MN88443X is not set
+# CONFIG_DVB_TC90522 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+# CONFIG_DVB_PLL is not set
+CONFIG_DVB_TUNER_DIB0070=y
+# CONFIG_DVB_TUNER_DIB0090 is not set
+
+#
+# SEC control devices for DVB-S
+#
+# CONFIG_DVB_A8293 is not set
+CONFIG_DVB_AF9033=m
+# CONFIG_DVB_ASCOT2E is not set
+# CONFIG_DVB_ATBM8830 is not set
+# CONFIG_DVB_HELENE is not set
+# CONFIG_DVB_HORUS3A is not set
+# CONFIG_DVB_ISL6405 is not set
+# CONFIG_DVB_ISL6421 is not set
+# CONFIG_DVB_ISL6423 is not set
+# CONFIG_DVB_IX2505V is not set
+# CONFIG_DVB_LGS8GL5 is not set
+# CONFIG_DVB_LGS8GXX is not set
+# CONFIG_DVB_LNBH25 is not set
+# CONFIG_DVB_LNBH29 is not set
+# CONFIG_DVB_LNBP21 is not set
+# CONFIG_DVB_LNBP22 is not set
+# CONFIG_DVB_M88RS2000 is not set
+# CONFIG_DVB_TDA665x is not set
+# CONFIG_DVB_DRX39XYJ is not set
+
+#
+# Common Interface (EN50221) controller drivers
+#
+# CONFIG_DVB_CXD2099 is not set
+# CONFIG_DVB_SP2 is not set
+# end of Customise DVB Frontends
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+# end of Media ancillary drivers
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_VGA_SWITCHEROO is not set
+# CONFIG_DRM is not set
+# CONFIG_DRM_DEBUG_MODESET_LOCK is not set
+
+#
+# ARM devices
+#
+# end of ARM devices
+
+#
+# Frame buffer Devices
+#
+# CONFIG_FB 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
+# end of Graphics support
+
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_SEQ_DEVICE=m
+# CONFIG_SND_OSSEMUL is not set
+CONFIG_SND_PCM_TIMER=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_PROC_FS=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_CTL_FAST_LOOKUP is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_CTL_INPUT_VALIDATION is not set
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+
+#
+# HD-Audio
+#
+# end of HD-Audio
+
+CONFIG_SND_HDA_PREALLOC_SIZE=0
+# CONFIG_SND_USB is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SND_X86 is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACCUTOUCH is not set
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_ASUS is not set
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_BIGBEN_FF is not set
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+# CONFIG_HID_CORSAIR is not set
+# CONFIG_HID_COUGAR is not set
+# CONFIG_HID_MACALLY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CREATIVE_SB0540 is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+# CONFIG_DRAGONRISE_FF 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
+# CONFIG_HID_EVISION is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_FT260 is not set
+# 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
+CONFIG_HID_KYE=y
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_VIEWSONIC is not set
+# CONFIG_HID_VRC2 is not set
+# CONFIG_HID_XIAOMI is not set
+# CONFIG_HID_FBX_REMOTE_AUDIO is not set
+CONFIG_HID_GYRATION=y
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_ITE is not set
+# CONFIG_HID_JABRA is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LED is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LETSKETCH is not set
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_HID_LOGITECH_HIDPP=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MALTRON is not set
+# CONFIG_HID_MAYFLASH is not set
+# CONFIG_HID_MEGAWORLD_FF is not set
+# CONFIG_HID_REDRAGON is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NINTENDO is not set
+# CONFIG_HID_NTI is not set
+CONFIG_HID_NTRIG=y
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PXRC is not set
+# CONFIG_HID_RAZER 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_SIGMAMICRO is not set
+CONFIG_HID_SONY=y
+# CONFIG_SONY_FF is not set
+# CONFIG_HID_SPEEDLINK is not set
+CONFIG_HID_STEAM=y
+# CONFIG_STEAM_FF is not set
+# CONFIG_HID_STEELSERIES is not set
+CONFIG_HID_SUNPLUS=y
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_HID_TOPRE is not set
+# 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
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# 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
+
+#
+# HID-BPF support
+#
+# end of HID-BPF support
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+# end of USB HID support
+
+CONFIG_I2C_HID=y
+# CONFIG_I2C_HID_ACPI is not set
+# CONFIG_I2C_HID_OF is not set
+# CONFIG_I2C_HID_OF_ELAN is not set
+# CONFIG_I2C_HID_OF_GOODIX is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_USB_CONN_GPIO is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_PCI=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEFAULT_PERSIST is not set
+# CONFIG_USB_FEW_INIT_RETRIES is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_PRODUCTLIST is not set
+# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set
+# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set
+CONFIG_USB_AUTOSUSPEND_DELAY=2
+# CONFIG_USB_MON is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=m
+# CONFIG_USB_EHCI_FSL is not set
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+
+#
+# USB dual-mode controller drivers
+#
+# CONFIG_USB_CDNS_SUPPORT is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE 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
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# 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
+# CONFIG_USB_ONBOARD_HUB is not set
+
+#
+# USB Physical Layer drivers
+#
+# 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_MMC is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# 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_AN30259A is not set
+# CONFIG_LEDS_AW2013 is not set
+# CONFIG_LEDS_BCM6328 is not set
+# CONFIG_LEDS_BCM6358 is not set
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LM3532 is not set
+# CONFIG_LEDS_LM3642 is not set
+# CONFIG_LEDS_LM3692X 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_LP55XX_COMMON is not set
+# CONFIG_LEDS_LP8860 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA963X is not set
+# CONFIG_LEDS_BD2606MVV is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_TLC591XX is not set
+# CONFIG_LEDS_LM355x is not set
+# CONFIG_LEDS_OT200 is not set
+# CONFIG_LEDS_IS31FL319X is not set
+# CONFIG_LEDS_IS31FL32XX is not set
+# CONFIG_LEDS_IS31FL3299 is not set
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+# CONFIG_LEDS_BLINKM 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
+# CONFIG_LEDS_LED1202 is not set
+
+#
+# Flash and Torch LED drivers
+#
+
+#
+# RGB LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+# CONFIG_LEDS_TRIGGER_DISK is not set
+# CONFIG_LEDS_TRIGGER_MTD is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_CPU is not set
+# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_LEDS_TRIGGER_CAMERA is not set
+# CONFIG_LEDS_TRIGGER_PANIC is not set
+# CONFIG_LEDS_TRIGGER_NETDEV is not set
+# CONFIG_LEDS_TRIGGER_PATTERN is not set
+# CONFIG_LEDS_TRIGGER_AUDIO is not set
+# CONFIG_LEDS_TRIGGER_TTY is not set
+
+#
+# Simple LED drivers
+#
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_RTC_LIB=y
+CONFIG_RTC_MC146818_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES 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 is not set
+# CONFIG_VFIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_VIRTIO_MENU is not set
+# CONFIG_VDPA is not set
+# CONFIG_VHOST_MENU is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# end of Microsoft Hyper-V guest support
+
+# CONFIG_GREYBUS is not set
+# CONFIG_COMEDI is not set
+# CONFIG_STAGING is not set
+# CONFIG_CHROME_PLATFORMS is not set
+# CONFIG_MELLANOX_PLATFORM is not set
+# CONFIG_SURFACE_PLATFORMS is not set
+# CONFIG_X86_PLATFORM_DEVICES is not set
+# CONFIG_P2SB is not set
+
+#
+# IntelCE devices
+#
+CONFIG_INTELCE_GPIO=y
+CONFIG_INTELCE_DFX=y
+# end of IntelCE devices
+
+# CONFIG_FBXGW7R_PLATFORM is not set
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+# CONFIG_COMMON_CLK_MAX9485 is not set
+# CONFIG_COMMON_CLK_SI5341 is not set
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI544 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_AXI_CLKGEN is not set
+# CONFIG_COMMON_CLK_RS9_PCIE is not set
+# CONFIG_COMMON_CLK_SI521XX is not set
+# CONFIG_COMMON_CLK_VC5 is not set
+# CONFIG_COMMON_CLK_VC7 is not set
+# CONFIG_COMMON_CLK_FIXED_MMIO is not set
+# CONFIG_CLK_LGM_CGU is not set
+# CONFIG_XILINX_VCU is not set
+# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set
+# CONFIG_HWSPINLOCK is not set
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_CLKBLD_I8253=y
+# end of Clock Source drivers
+
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_REMOTEPROC is not set
+# end of Remoteproc drivers
+
+#
+# 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
+
+#
+# fujitsu SoC drivers
+#
+# end of fujitsu SoC drivers
+
+#
+# i.MX SoC drivers
+#
+# end of i.MX SoC drivers
+
+#
+# Enable LiteX SoC Builder specific drivers
+#
+# CONFIG_LITEX_SOC_CONTROLLER is not set
+# end of Enable LiteX SoC Builder specific drivers
+
+# CONFIG_WPCM450_SOC is not set
+
+#
+# Qualcomm SoC drivers
+#
+# end of Qualcomm SoC drivers
+
+# 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 is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_NTB is not set
+# CONFIG_PWM is not set
+
+#
+# IRQ chip support
+#
+CONFIG_IRQCHIP=y
+# CONFIG_AL_FIC is not set
+# CONFIG_XILINX_INTC is not set
+# end of IRQ chip support
+
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_USB_LGM_PHY is not set
+# CONFIG_PHY_CAN_TRANSCEIVER is not set
+# CONFIG_XDSL_PHY_API is not set
+
+#
+# PHY drivers for Broadcom platforms
+#
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# end of PHY drivers for Broadcom platforms
+
+# CONFIG_PHY_CADENCE_TORRENT is not set
+# CONFIG_PHY_CADENCE_DPHY is not set
+# CONFIG_PHY_CADENCE_DPHY_RX is not set
+# CONFIG_PHY_CADENCE_SALVO is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_PHY_MAPPHONE_MDM6600 is not set
+# CONFIG_PHY_INTEL_LGM_COMBO is not set
+# CONFIG_PHY_INTEL_LGM_EMMC is not set
+# end of PHY Subsystem
+
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# end of Performance monitor support
+
+# CONFIG_RAS is not set
+# CONFIG_USB4 is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID_BINDER_IPC is not set
+# end of Android
+
+# CONFIG_LIBNVDIMM is not set
+# CONFIG_DAX is not set
+# CONFIG_NVMEM is not set
+
+#
+# HW tracing support
+#
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+# end of HW tracing support
+
+# CONFIG_FPGA is not set
+# CONFIG_FSI is not set
+# CONFIG_SIOX is not set
+# CONFIG_SLIMBUS is not set
+# CONFIG_INTERCONNECT is not set
+# CONFIG_COUNTER is not set
+# CONFIG_PECI is not set
+# CONFIG_HTE is not set
+# end of Device Drivers
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_VALIDATE_FS_PARSER is not set
+CONFIG_FS_IOMAP=y
+CONFIG_LEGACY_DIRECT_IO=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_SUPPORT_V4=y
+CONFIG_XFS_SUPPORT_ASCII_CI=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# 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
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+# CONFIG_FS_VERITY is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+# CONFIG_VIRTIO_FS is not set
+CONFIG_OVERLAY_FS=m
+# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set
+CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y
+# CONFIG_OVERLAY_FS_INDEX is not set
+# CONFIG_OVERLAY_FS_METACOPY is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+# end of Caches
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+# end of CD-ROM/DVD Filesystems
+
+#
+# DOS/FAT/EXFAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_EXFAT_FS=m
+CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8"
+# CONFIG_NTFS_FS is not set
+CONFIG_NTFS3_FS=m
+# CONFIG_NTFS3_LZX_XPRESS is not set
+# CONFIG_NTFS3_FS_POSIX_ACL is not set
+# CONFIG_EXFAT_FS_FBX is not set
+# end of DOS/FAT/EXFAT/NT Filesystems
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_PROC_PID_ARCH_STATUS=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+CONFIG_MEMFD_CREATE=y
+# CONFIG_CONFIGFS_FS is not set
+# 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
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UBIFS_FS_ZSTD=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_AUTHENTICATION is not set
+CONFIG_CRAMFS=y
+CONFIG_CRAMFS_BLOCKDEV=y
+CONFIG_CRAMFS_MTD=y
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_FILE_CACHE is not set
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_SINGLE=y
+# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
+CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE=y
+# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set
+# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_ZLIB is not set
+# CONFIG_SQUASHFS_LZ4 is not set
+# CONFIG_SQUASHFS_LZO is not set
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_ZSTD is not set
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=32
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_PSTORE=y
+CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240
+CONFIG_PSTORE_DEFLATE_COMPRESS=y
+# CONFIG_PSTORE_LZO_COMPRESS is not set
+# CONFIG_PSTORE_LZ4_COMPRESS is not set
+# CONFIG_PSTORE_LZ4HC_COMPRESS is not set
+# CONFIG_PSTORE_842_COMPRESS is not set
+# CONFIG_PSTORE_ZSTD_COMPRESS is not set
+CONFIG_PSTORE_COMPRESS=y
+CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y
+CONFIG_PSTORE_COMPRESS_DEFAULT="deflate"
+# CONFIG_PSTORE_CONSOLE is not set
+# CONFIG_PSTORE_PMSG is not set
+CONFIG_PSTORE_RAM=y
+# CONFIG_PSTORE_BLK is not set
+# 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=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+CONFIG_NFS_DISABLE_UDP_SUPPORT=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_SMB_SERVER is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_UNICODE is not set
+# end of File systems
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_REQUEST_CACHE is not set
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_TRUSTED_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_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+# CONFIG_HARDENED_USERCOPY is not set
+# CONFIG_FORTIFY_SOURCE is not set
+# CONFIG_STATIC_USERMODEHELPER is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_LSM="yama,loadpin,safesetid,integrity"
+
+#
+# Kernel hardening options
+#
+
+#
+# Memory initialization
+#
+CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
+CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y
+CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
+CONFIG_INIT_STACK_NONE=y
+# CONFIG_INIT_STACK_ALL_PATTERN is not set
+# CONFIG_INIT_STACK_ALL_ZERO is not set
+# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
+# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
+CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
+# CONFIG_ZERO_CALL_USED_REGS is not set
+# end of Memory initialization
+
+CONFIG_RANDSTRUCT_NONE=y
+# end of Kernel hardening options
+# end of Security options
+
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SKCIPHER=y
+CONFIG_CRYPTO_SKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+# CONFIG_CRYPTO_PCRYPT is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+# end of Crypto core or helper
+
+#
+# Public-key cryptography
+#
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+CONFIG_CRYPTO_ECC=y
+CONFIG_CRYPTO_ECDH=y
+# CONFIG_CRYPTO_ECDSA is not set
+# CONFIG_CRYPTO_ECRDSA is not set
+# CONFIG_CRYPTO_SM2 is not set
+# CONFIG_CRYPTO_CURVE25519 is not set
+# end of Public-key cryptography
+
+#
+# Block ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_AES_TI is not set
+# CONFIG_CRYPTO_ARIA is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_SM4_GENERIC is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# end of Block ciphers
+
+#
+# Length-preserving ciphers and modes
+#
+# CONFIG_CRYPTO_ADIANTUM is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CFB is not set
+CONFIG_CRYPTO_CTR=y
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_HCTR2 is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_OFB is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# end of Length-preserving ciphers and modes
+
+#
+# AEAD (authenticated encryption with associated data) ciphers
+#
+# CONFIG_CRYPTO_AEGIS128 is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_CCM is not set
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=y
+# CONFIG_CRYPTO_ESSIV is not set
+# end of AEAD (authenticated encryption with associated data) ciphers
+
+#
+# Hashes, digests, and MACs
+#
+# CONFIG_CRYPTO_BLAKE2B is not set
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_GHASH=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_SM3_GENERIC is not set
+# CONFIG_CRYPTO_STREEBOG is not set
+# CONFIG_CRYPTO_VMAC is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_XXHASH is not set
+# end of Hashes, digests, and MACs
+
+#
+# CRCs (cyclic redundancy checks)
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# end of CRCs (cyclic redundancy checks)
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+CONFIG_CRYPTO_ZSTD=y
+# end of Compression
+
+#
+# Random number generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+# end of Random number generation
+
+#
+# Userspace interface
+#
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# end of Userspace interface
+
+CONFIG_CRYPTO_HASH_INFO=y
+
+#
+# Accelerated Cryptographic Algorithms for CPU (x86)
+#
+# CONFIG_CRYPTO_AES_NI_INTEL is not set
+# CONFIG_CRYPTO_SERPENT_SSE2_586 is not set
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+# CONFIG_CRYPTO_CRC32_PCLMUL is not set
+# end of Accelerated Cryptographic Algorithms for CPU (x86)
+
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+# CONFIG_CRYPTO_DEV_GEODE is not set
+# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set
+# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set
+# CONFIG_CRYPTO_DEV_CCP 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_SAFEXCEL is not set
+# CONFIG_CRYPTO_DEV_CCREE is not set
+# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
+# end of Certificates for signature checking
+
+#
+# Library routines
+#
+# CONFIG_PACKING is not set
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+# CONFIG_CORDIC is not set
+# CONFIG_PRIME_NUMBERS is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
+
+#
+# Crypto library routines
+#
+CONFIG_CRYPTO_LIB_UTILS=y
+CONFIG_CRYPTO_LIB_AES=y
+CONFIG_CRYPTO_LIB_GF128MUL=y
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+# CONFIG_CRYPTO_LIB_CHACHA is not set
+# CONFIG_CRYPTO_LIB_CURVE25519 is not set
+CONFIG_CRYPTO_LIB_DES=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
+# CONFIG_CRYPTO_LIB_POLY1305 is not set
+# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_LIB_SHA1=y
+CONFIG_CRYPTO_LIB_SHA256=y
+# end of Crypto library routines
+
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC64_ROCKSOFT is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC64 is not set
+# CONFIG_CRC4 is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+CONFIG_XXHASH=y
+CONFIG_AUDIT_GENERIC=y
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_ZSTD_COMMON=y
+CONFIG_ZSTD_COMPRESS=y
+CONFIG_ZSTD_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+# CONFIG_XZ_DEC_MICROLZMA is not set
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_BCH=y
+CONFIG_BCH_CONST_PARAMS=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_DMA_DECLARE_COHERENT=y
+CONFIG_SWIOTLB=y
+# CONFIG_DMA_RESTRICTED_POOL is not set
+# CONFIG_DMA_API_DEBUG is not set
+CONFIG_SGL_ALLOC=y
+# CONFIG_FORCE_NR_CPUS is not set
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_HAVE_GENERIC_VDSO=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_VDSO_32=y
+CONFIG_GENERIC_VDSO_TIME_NS=y
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_SBITMAP=y
+CONFIG_ARCH_HAS_FBXSERIAL=y
+CONFIG_FBXSERIAL=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_BOOT_PRINTK_DELAY is not set
+# 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
+
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_MISC is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_AS_HAS_NON_CONST_LEB128=y
+CONFIG_DEBUG_INFO_NONE=y
+# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
+# CONFIG_DEBUG_INFO_DWARF4 is not set
+# CONFIG_DEBUG_INFO_DWARF5 is not set
+CONFIG_FRAME_WARN=0
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_HEADERS_INSTALL is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_VMLINUX_MAP is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# end of Compile-time checks and compiler options
+
+#
+# Generic Kernel Debugging Instruments
+#
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_MAGIC_SYSRQ_SERIAL=y
+CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
+# CONFIG_DEBUG_FS is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
+# CONFIG_UBSAN is not set
+CONFIG_HAVE_KCSAN_COMPILER=y
+# end of Generic Kernel Debugging Instruments
+
+#
+# Networking Debugging
+#
+# CONFIG_NET_DEV_REFCNT_TRACKER is not set
+# CONFIG_NET_NS_REFCNT_TRACKER is not set
+# CONFIG_DEBUG_NET is not set
+# end of Networking Debugging
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_RODATA_TEST is not set
+CONFIG_ARCH_HAS_DEBUG_WX=y
+# CONFIG_DEBUG_WX is not set
+CONFIG_GENERIC_PTDUMP=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_DEBUG_KMAP_LOCAL is not set
+CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y
+# CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP is not set
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+CONFIG_CC_HAS_KASAN_GENERIC=y
+CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
+CONFIG_HAVE_ARCH_KFENCE=y
+# CONFIG_KFENCE is not set
+# end of Memory Debugging
+
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Oops, Lockups and Hangs
+#
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_ON_OOPS_VALUE=1
+CONFIG_PANIC_TIMEOUT=10
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HARDLOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_TEST_LOCKUP is not set
+# end of Debug Oops, Lockups and Hangs
+
+#
+# Scheduler Debugging
+#
+CONFIG_SCHED_INFO=y
+CONFIG_SCHEDSTATS=y
+# end of Scheduler Debugging
+
+# CONFIG_DEBUG_TIMEKEEPING is not set
+CONFIG_DEBUG_PREEMPT=y
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_WW_MUTEX_SELFTEST is not set
+# CONFIG_SCF_TORTURE_TEST is not set
+# end of Lock Debugging (spinlocks, mutexes, etc...)
+
+# CONFIG_NMI_CHECK_CPU is not set
+# CONFIG_DEBUG_IRQFLAGS is not set
+# CONFIG_STACKTRACE is not set
+# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
+# CONFIG_DEBUG_KOBJECT is not set
+
+#
+# Debug kernel data structures
+#
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PLIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BUG_ON_DATA_CORRUPTION is not set
+# CONFIG_DEBUG_MAPLE_TREE is not set
+# end of Debug kernel data structures
+
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_RCU_SCALE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_REF_SCALE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0
+# CONFIG_RCU_CPU_STALL_CPUTIME is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# end of RCU Debugging
+
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_RETHOOK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=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 is not set
+
+#
+# x86 Debugging
+#
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+# CONFIG_EARLY_PRINTK_USB_XDBC is not set
+# CONFIG_DEBUG_TLBFLUSH is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+# CONFIG_X86_DECODER_SELFTEST is not set
+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_CPA_DEBUG is not set
+# CONFIG_DEBUG_ENTRY is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+# CONFIG_X86_DEBUG_FPU is not set
+# CONFIG_PUNIT_ATOM_DEBUG is not set
+CONFIG_UNWINDER_FRAME_POINTER=y
+# CONFIG_UNWINDER_GUESS is not set
+# end of x86 Debugging
+
+#
+# Kernel Testing and Coverage
+#
+# CONFIG_KUNIT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_CC_HAS_SANCOV_TRACE_PC=y
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_ARCH_USE_MEMTEST=y
+CONFIG_MEMTEST=y
+# end of Kernel Testing and Coverage
+
+#
+# Rust hacking
+#
+# end of Rust hacking
+# end of Kernel hacking
diff -Nruw linux-6.4-fbx/drivers/char/diag./Kconfig linux-6.4-fbx/drivers/char/diag/Kconfig
--- linux-6.4-fbx/drivers/char/diag./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/char/diag/Kconfig	2022-09-02 21:26:05.930083008 +0200
@@ -0,0 +1,38 @@
+menu "Diag Support"
+
+config DIAG_CHAR
+	tristate "char driver interface and diag forwarding to/from modem"
+	select CRC_CCITT
+	help
+	 Char driver interface for diag user space and diag-forwarding to modem ARM and back.
+	 This enables diagchar for maemo usb gadget or android usb gadget based on config selected.
+endmenu
+
+menu "DIAG traffic over USB"
+
+config DIAG_OVER_USB
+	bool "Enable DIAG traffic to go over USB"
+	depends on DIAG_CHAR
+	help
+	 This feature helps segregate code required for DIAG traffic to go over USB.
+endmenu
+
+menu "DIAG traffic over QRTR"
+
+config DIAG_OVER_QRTR
+	bool "Enable DIAG traffic to go over QRTR"
+        depends on QRTR && DIAG_CHAR
+	default n
+	help
+	 This feature helps segregate code required for DIAG traffic to go over QRTR.
+endmenu
+
+menu "HSIC/SMUX support for DIAG"
+
+config DIAGFWD_BRIDGE_CODE
+	bool "Enable QSC/9K DIAG traffic over SMUX/HSIC"
+	depends on DIAG_CHAR
+	depends on USB_QCOM_DIAG_BRIDGE || MHI_BUS
+	help
+	 SMUX/HSIC Transport Layer for DIAG Router
+endmenu
diff -Nruw linux-6.4-fbx/drivers/char/diag./Makefile linux-6.4-fbx/drivers/char/diag/Makefile
--- linux-6.4-fbx/drivers/char/diag./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/char/diag/Makefile	2022-09-02 21:26:05.930083008 +0200
@@ -0,0 +1,19 @@
+obj-$(CONFIG_DIAG_CHAR) := diagchar.o
+obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_hsic.o
+obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE) += diagfwd_smux.o
+diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagfwd_peripheral.o diag_mux.o diag_memorydevice.o diag_usb.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
+
+ifdef CONFIG_DIAG_OVER_QRTR
+diagchar-objs += qcom_diagfwd_socket.o
+else
+diagchar-objs += diagfwd_socket.o
+endif
+
+ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+diagchar-objs += diagfwd_bridge.o
+
+ifdef CONFIG_MHI_BUS
+diagchar-objs += diagfwd_mhi.o
+endif
+
+endif
diff -Nruw linux-6.4-fbx/drivers/fbxgpio./Kconfig linux-6.4-fbx/drivers/fbxgpio/Kconfig
--- linux-6.4-fbx/drivers/fbxgpio./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxgpio/Kconfig	2020-02-08 00:30:17.548463598 +0100
@@ -0,0 +1,7 @@
+config FREEBOX_GPIO
+	tristate "Freebox GPIO control interface"
+	default n
+
+config FREEBOX_GPIO_DT
+	tristate "Freebox GPIO DT binding."
+	default n
diff -Nruw linux-6.4-fbx/drivers/fbxgpio./Makefile linux-6.4-fbx/drivers/fbxgpio/Makefile
--- linux-6.4-fbx/drivers/fbxgpio./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxgpio/Makefile	2020-02-08 00:30:17.548463598 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FREEBOX_GPIO)	+= fbxgpio_core.o
+obj-$(CONFIG_FREEBOX_GPIO_DT)	+= fbxgpio_dt.o
diff -Nruw linux-6.4-fbx/drivers/fbxjtag./Kconfig linux-6.4-fbx/drivers/fbxjtag/Kconfig
--- linux-6.4-fbx/drivers/fbxjtag./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxjtag/Kconfig	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1,3 @@
+config FREEBOX_JTAG
+	tristate "Freebox JTAG control interface"
+	default n
diff -Nruw linux-6.4-fbx/drivers/fbxjtag./Makefile linux-6.4-fbx/drivers/fbxjtag/Makefile
--- linux-6.4-fbx/drivers/fbxjtag./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxjtag/Makefile	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_FREEBOX_JTAG)	+= fbxjtag.o
diff -Nruw linux-6.4-fbx/drivers/fbxprocfs./Kconfig linux-6.4-fbx/drivers/fbxprocfs/Kconfig
--- linux-6.4-fbx/drivers/fbxprocfs./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxprocfs/Kconfig	2010-02-25 15:41:07.519542884 +0100
@@ -0,0 +1,2 @@
+config FREEBOX_PROCFS
+	tristate "Freebox procfs interface"
diff -Nruw linux-6.4-fbx/drivers/fbxprocfs./Makefile linux-6.4-fbx/drivers/fbxprocfs/Makefile
--- linux-6.4-fbx/drivers/fbxprocfs./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxprocfs/Makefile	2010-02-25 15:41:07.519542884 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_FREEBOX_PROCFS) += fbxprocfs.o
diff -Nruw linux-6.4-fbx/drivers/fbxprocfs./fbxprocfs.c linux-6.4-fbx/drivers/fbxprocfs/fbxprocfs.c
--- linux-6.4-fbx/drivers/fbxprocfs./fbxprocfs.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxprocfs/fbxprocfs.c	2023-11-29 17:07:07.764985628 +0100
@@ -0,0 +1,299 @@
+/*
+ * Freebox ProcFs interface
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/sizes.h>
+
+#include <linux/fbxprocfs.h>
+
+#define PFX	"fbxprocfs: "
+
+
+static struct list_head clients;
+static struct mutex clients_mutex;
+
+static struct proc_dir_entry *root;
+
+/*
+ * register  a  fbxprocfs client  with  given  dirname, caller  should
+ * consider returned struct opaque
+ */
+struct fbxprocfs_client *fbxprocfs_add_client(const char *dirname,
+					      struct module *owner)
+{
+	struct fbxprocfs_client *ret, *p;
+
+	ret = NULL;
+	mutex_lock(&clients_mutex);
+
+	/* check for duplicate */
+	list_for_each_entry(p, &clients, list) {
+		if (!strcmp(dirname, p->dirname))
+			goto out;
+	}
+
+	if (!(ret = kmalloc(sizeof (*ret), GFP_KERNEL))) {
+		printk(KERN_ERR PFX "kmalloc failed\n");
+		goto out;
+	}
+
+	/* try to create client directory */
+	if (!(ret->dir = proc_mkdir(dirname, root))) {
+		printk(KERN_ERR PFX "can't create %s dir\n", dirname);
+		kfree(ret);
+		ret = NULL;
+		goto out;
+	}
+
+	atomic_set(&ret->refcount, 1);
+	ret->dirname = dirname;
+	list_add(&ret->list, &clients);
+
+out:
+	mutex_unlock(&clients_mutex);
+	return ret;
+}
+
+/*
+ * unregister  a  fbxprocfs client, make sure usage count is zero
+ */
+int fbxprocfs_remove_client(struct fbxprocfs_client *client)
+{
+	int ret;
+
+	mutex_lock(&clients_mutex);
+
+	ret = 0;
+	if (atomic_read(&client->refcount) > 1) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	remove_proc_entry(client->dirname, root);
+	list_del(&client->list);
+	kfree(client);
+
+out:
+	mutex_unlock(&clients_mutex);
+	return ret;
+}
+
+/*
+ * remove given entries from client directory
+ */
+static int
+__remove_entries(struct fbxprocfs_client *client,
+		 const struct fbxprocfs_desc *ro_desc,
+		 const struct fbxprocfs_desc *rw_desc)
+{
+	int i;
+
+	for (i = 0; ro_desc && ro_desc[i].name; i++) {
+		remove_proc_entry(ro_desc[i].name, client->dir);
+		atomic_dec(&client->refcount);
+	}
+
+	for (i = 0; rw_desc && rw_desc[i].name; i++) {
+		remove_proc_entry(rw_desc[i].name, client->dir);
+		atomic_dec(&client->refcount);
+	}
+
+	return 0;
+}
+
+/*
+ * replacement for NULL rfunc.
+ */
+static int bad_rfunc(struct seq_file *m, void *ptr)
+{
+	return -EACCES;
+}
+
+/*
+ * fbxprocfs write path is now handled by seq_file code. this
+ * simplifies client code greatly.
+ */
+static int fbxprocfs_open(struct inode *inode, struct file *file)
+{
+	const struct fbxprocfs_desc *desc = pde_data(inode);
+
+	return single_open(file, desc->rfunc ? desc->rfunc : bad_rfunc,
+			   (void*)desc->id);
+}
+
+/*
+ * no particular help from kernel in the write path, fetch user buffer
+ * in a kernel buffer and call write func.
+ */
+static ssize_t fbxprocfs_write(struct file *file, const char __user *ubuf,
+			       size_t len, loff_t *off)
+{
+	/*
+	 * get fbxprocfs desc via the proc_dir_entry in file inode
+	 */
+	struct fbxprocfs_desc *d = pde_data(file_inode(file));
+	char *kbuf;
+	int ret;
+
+	/*
+	 * must have a wfunc callback.
+	 */
+	if (!d->wfunc)
+		return -EACCES;
+
+	/*
+	 * allow up to SZ_4K bytes to be written.
+	 */
+	if (len > SZ_4K)
+		return -EOVERFLOW;
+
+	/*
+	 * alloc and fetch kernel buffer containing user data.
+	 */
+	kbuf = kmalloc(SZ_4K, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	ret = -EFAULT;
+	if (copy_from_user(kbuf, ubuf, len))
+		goto kfree;
+
+	ret = d->wfunc(file, kbuf, len, (void*)d->id);
+
+kfree:
+	kfree(kbuf);
+	return ret;
+}
+
+/*
+ * fbxprocfs file operations, read stuff is handled by seq_file code.
+ */
+static const struct proc_ops fbxprocfs_fops = {
+	.proc_open	= fbxprocfs_open,
+	.proc_lseek	= seq_lseek,
+	.proc_read	= seq_read,
+	.proc_release	= single_release,
+	.proc_write	= fbxprocfs_write,
+};
+
+/*
+ * replaces create_proc_read_entry removed in latest kernels.
+ */
+static struct proc_dir_entry *__create_proc_read_entry(
+				       const struct fbxprocfs_desc *desc,
+				       struct proc_dir_entry *base)
+{
+	return proc_create_data(desc->name, 0, base, &fbxprocfs_fops,
+				(void*)desc);
+}
+
+/*
+ * replaces create_proc_entry removed in latest kernels.
+ */
+static struct proc_dir_entry *__create_proc_entry(
+					const struct fbxprocfs_desc *desc,
+					struct proc_dir_entry *base)
+{
+	return proc_create_data(desc->name, S_IFREG | S_IWUSR | S_IRUGO,
+				base, &fbxprocfs_fops, (void*)desc);
+}
+
+/*
+ * create given entries in client directory
+ */
+static int
+__create_entries(struct fbxprocfs_client *client,
+		 const struct fbxprocfs_desc *ro_desc,
+		 const struct fbxprocfs_desc *rw_desc)
+{
+	struct proc_dir_entry	*proc;
+	int			i;
+
+	for (i = 0; ro_desc && ro_desc[i].name; i++) {
+		if (!(proc = __create_proc_read_entry(&ro_desc[i],
+						      client->dir))) {
+			printk(KERN_ERR PFX "can't create %s/%s entry\n",
+			       client->dirname, ro_desc[i].name);
+			goto err;
+		}
+		atomic_inc(&client->refcount);
+	}
+
+	for (i = 0; rw_desc && rw_desc[i].name; i++) {
+		if (!(proc = __create_proc_entry(&rw_desc[i], client->dir))) {
+			printk(KERN_ERR PFX "can't create %s/%s entry\n",
+			       client->dirname, ro_desc[i].name);
+			goto err;
+		}
+		atomic_inc(&client->refcount);
+	}
+
+	return 0;
+
+err:
+	__remove_entries(client, ro_desc, rw_desc);
+	return -1;
+}
+
+int
+fbxprocfs_create_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc)
+{
+	int	ret;
+
+	ret = __create_entries(client, ro_desc, rw_desc);
+	return ret;
+}
+
+int
+fbxprocfs_remove_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc)
+{
+	int	ret;
+
+	ret = __remove_entries(client, ro_desc, rw_desc);
+	return ret;
+}
+
+
+static int __init
+fbxprocfs_init(void)
+{
+	INIT_LIST_HEAD(&clients);
+	mutex_init(&clients_mutex);
+
+	/* create freebox directory */
+	if (!(root = proc_mkdir("freebox", NULL))) {
+		printk(KERN_ERR PFX "can't create freebox/ dir\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static void __exit
+fbxprocfs_exit(void)
+{
+	remove_proc_entry("freebox", NULL);
+}
+
+module_init(fbxprocfs_init);
+module_exit(fbxprocfs_exit);
+
+EXPORT_SYMBOL(fbxprocfs_create_entries);
+EXPORT_SYMBOL(fbxprocfs_remove_entries);
+EXPORT_SYMBOL(fbxprocfs_add_client);
+EXPORT_SYMBOL(fbxprocfs_remove_client);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
+
diff -Nruw linux-6.4-fbx/drivers/fbxwatchdog./Kconfig linux-6.4-fbx/drivers/fbxwatchdog/Kconfig
--- linux-6.4-fbx/drivers/fbxwatchdog./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxwatchdog/Kconfig	2020-02-08 00:30:17.548463598 +0100
@@ -0,0 +1,24 @@
+menuconfig FREEBOX_WATCHDOG
+	tristate "Freebox Watchdog"
+	default n
+
+if FREEBOX_WATCHDOG
+
+config FREEBOX_WATCHDOG_CHAR
+	bool "Freebox Watchdog char device interface."
+	default n
+
+config FREEBOX_WATCHDOG_ORION
+	tristate "Marvell Orion support"
+	depends on PLAT_ORION
+
+config FREEBOX_WATCHDOG_BCM63XX
+	tristate "Broadcom 63xx Freebox Watchdog support"
+	depends on BCM63XX
+	default n
+
+config FREEBOX_WATCHDOG_BCM63XX_OF
+	tristate "Broadcom 63xx Freebox Watchdog support (generic)"
+	depends on OF && !FREEBOX_WATCHDOG_BCM63XX
+
+endif
diff -Nruw linux-6.4-fbx/drivers/fbxwatchdog./Makefile linux-6.4-fbx/drivers/fbxwatchdog/Makefile
--- linux-6.4-fbx/drivers/fbxwatchdog./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/fbxwatchdog/Makefile	2020-02-08 00:30:17.548463598 +0100
@@ -0,0 +1,10 @@
+obj-$(CONFIG_FREEBOX_WATCHDOG) += fbxwatchdog.o
+
+fbxwatchdog-objs = fbxwatchdog_core.o
+ifeq ($(CONFIG_FREEBOX_WATCHDOG_CHAR),y)
+fbxwatchdog-objs += fbxwatchdog_char.o
+endif
+
+obj-$(CONFIG_FREEBOX_WATCHDOG_ORION)	+= fbxwatchdog_orion.o
+obj-$(CONFIG_FREEBOX_WATCHDOG_BCM63XX)	+= fbxwatchdog_bcm63xx.o
+obj-$(CONFIG_FREEBOX_WATCHDOG_BCM63XX_OF)	+= fbxwatchdog_bcm63xx_of.o
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/drivers/media/rc/keymaps/rc-rc6-freebox.c	2020-02-08 00:30:20.024487658 +0100
@@ -0,0 +1,135 @@
+/* rc-rc6-freebox.c - Keytable for Freebox/Alicebox IR controller
+ *
+ * Copyright (c) 2012 by Nicolas Pouillon <npouillon@freebox.fr>
+ *
+ * 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.
+ */
+
+#include <media/rc-map.h>
+#include <linux/module.h>
+
+#define RC6_FREEBOX_TV 0xf2
+#define RC6_FREEBOX_WIDE 0x49
+#define RC6_FREEBOX_POWER 0x0c
+#define RC6_FREEBOX_STOP 0x31
+#define RC6_FREEBOX_REC 0x37
+#define RC6_FREEBOX_REW 0x2f
+#define RC6_FREEBOX_PLAY 0xb8
+#define RC6_FREEBOX_FF 0x2e
+#define RC6_FREEBOX_PREV 0x4d
+#define RC6_FREEBOX_NEXT 0x4c
+#define RC6_FREEBOX_RELOAD 0x83
+#define RC6_FREEBOX_MENU 0xcc
+#define RC6_FREEBOX_UP 0x99
+#define RC6_FREEBOX_LEFT 0x9b
+#define RC6_FREEBOX_RIGHT 0x9c
+#define RC6_FREEBOX_DOWN 0x9a
+#define RC6_FREEBOX_OK 0x5c
+#define RC6_FREEBOX_VOL_INC 0x5b
+#define RC6_FREEBOX_VOL_DEC 0x5a
+#define RC6_FREEBOX_MUTE 0x0d
+#define RC6_FREEBOX_PROG_UP 0x58
+#define RC6_FREEBOX_PROG_DOWN 0x59
+#define RC6_FREEBOX_FREEBOX 0xd7
+#define RC6_FREEBOX_RED 0x6d
+#define RC6_FREEBOX_GREEN 0x6e
+#define RC6_FREEBOX_YELLOW 0x6f
+#define RC6_FREEBOX_BLUE 0x70
+#define RC6_FREEBOX_1 0x01
+#define RC6_FREEBOX_2 0x02
+#define RC6_FREEBOX_3 0x03
+#define RC6_FREEBOX_4 0x04
+#define RC6_FREEBOX_5 0x05
+#define RC6_FREEBOX_6 0x06
+#define RC6_FREEBOX_7 0x07
+#define RC6_FREEBOX_8 0x08
+#define RC6_FREEBOX_9 0x09
+#define RC6_FREEBOX_BACK 0x9e
+#define RC6_FREEBOX_0 0x00
+#define RC6_FREEBOX_SWAP 0x0a
+#define RC6_FREEBOX_HELP 0x81
+#define RC6_FREEBOX_INFO 0x0f
+#define RC6_FREEBOX_GUIDE 0x97
+#define RC6_FREEBOX_OPTIONS 0x54
+
+#define MAP(x,y) { 0x80382600 + RC6_FREEBOX_##x, KEY_##y }
+
+static struct rc_map_table rc6_freebox[] = {
+	MAP(0, NUMERIC_0),
+	MAP(1, NUMERIC_1),
+	MAP(2, NUMERIC_2),
+	MAP(3, NUMERIC_3),
+	MAP(4, NUMERIC_4),
+	MAP(5, NUMERIC_5),
+	MAP(6, NUMERIC_6),
+	MAP(7, NUMERIC_7),
+	MAP(8, NUMERIC_8),
+	MAP(9, NUMERIC_9),
+	MAP(SWAP, BACK),
+	MAP(POWER, POWER),
+	MAP(MUTE, MUTE),
+	MAP(INFO, INFO),
+
+	MAP(FF, FASTFORWARD),
+	MAP(REW, REWIND),
+	MAP(STOP, STOP),
+	MAP(REC, RECORD),
+	MAP(WIDE, ZOOM),
+	MAP(PREV, PREVIOUS),
+	MAP(NEXT, NEXT),
+
+	MAP(OPTIONS, OPTION),
+	MAP(PROG_UP, CHANNELUP),
+	MAP(PROG_DOWN, CHANNELDOWN),
+	MAP(VOL_DEC, VOLUMEDOWN),
+	MAP(VOL_INC, VOLUMEUP),
+	MAP(OK, OK),
+
+	MAP(RED, RED),
+	MAP(GREEN, GREEN),
+	MAP(YELLOW, YELLOW),
+	MAP(BLUE, BLUE),
+
+	MAP(HELP, HELP),
+	MAP(RELOAD, REFRESH),
+
+	MAP(GUIDE, PROGRAM),
+	MAP(UP, UP),
+	MAP(DOWN, DOWN),
+	MAP(LEFT, LEFT),
+	MAP(RIGHT, RIGHT),
+	MAP(BACK, BACKSPACE),
+	MAP(PLAY, PLAY),
+
+	MAP(MENU, LIST),
+	MAP(FREEBOX, HOME),
+	MAP(TV, SCREEN),
+};
+
+static struct rc_map_list rc6_freebox_map = {
+	.map = {
+		.scan    = rc6_freebox,
+		.size    = ARRAY_SIZE(rc6_freebox),
+		.rc_proto = RC_PROTO_RC6_MCE,
+		.name    = "rc-rc6-freebox",
+	}
+};
+
+static int __init init_rc_map_rc6_freebox(void)
+{
+	return rc_map_register(&rc6_freebox_map);
+}
+
+static void __exit exit_rc_map_rc6_freebox(void)
+{
+	rc_map_unregister(&rc6_freebox_map);
+}
+
+module_init(init_rc_map_rc6_freebox)
+module_exit(exit_rc_map_rc6_freebox)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nicolas Pouillon <npouillon@freebox.fr>");
diff -Nruw linux-6.4-fbx/drivers/misc/hdmi-cec./Kconfig linux-6.4-fbx/drivers/misc/hdmi-cec/Kconfig
--- linux-6.4-fbx/drivers/misc/hdmi-cec./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/hdmi-cec/Kconfig	2022-08-30 19:20:26.087577968 +0200
@@ -0,0 +1,15 @@
+menu "HDMI CEC support"
+
+config HDMI_CEC
+	tristate "HDMI CEC (Consumer Electronics Control) support"
+	help
+	   HDMI Consumer Electronics Control support.
+
+config HDMI_CEC_REMOTI
+	tristate "RemoTI CEC driver"
+	depends on HDMI_CEC
+	select REMOTI
+	help
+	   HDMI CEC driver using RemoTI IPCs.
+
+endmenu
diff -Nruw linux-6.4-fbx/drivers/misc/hdmi-cec./Makefile linux-6.4-fbx/drivers/misc/hdmi-cec/Makefile
--- linux-6.4-fbx/drivers/misc/hdmi-cec./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/hdmi-cec/Makefile	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,6 @@
+obj-$(CONFIG_HDMI_CEC)		+= hdmi-cec.o
+hdmi-cec-objs			+= core.o dev.o
+
+# drivers
+obj-$(CONFIG_HDMI_CEC_REMOTI)	+= remoti-cec.o
+remoti-cec-objs			:= remoti.o
diff -Nruw linux-6.4-fbx/drivers/misc/hdmi-cec./core.c linux-6.4-fbx/drivers/misc/hdmi-cec/core.c
--- linux-6.4-fbx/drivers/misc/hdmi-cec./core.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/hdmi-cec/core.c	2020-02-08 00:30:20.232489679 +0100
@@ -0,0 +1,607 @@
+/*
+ * HDMI Consumer Electronics Control, core module
+ *
+ * Copyright (C) 2011, Florian Fainelli <ffainelli@freebox;fr>
+ *
+ * This file is subject to the GPLv2 licensing terms.
+ *
+ */
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+
+#include <linux/hdmi-cec/hdmi-cec.h>
+#include <linux/hdmi-cec/dev.h>
+
+#include "hdmi-cec-priv.h"
+
+static unsigned cec_adapter_count;
+
+#define CEC_RX_QUEUE_MAX_LEN	(20)
+
+/**
+ * cec_set_logical_address() - sets the cec logical address
+ * @adapter:	adapter pointer
+ * @addr:	logical address
+ *
+ * calls the adapter specific set_logical_address callback
+ */
+int cec_set_logical_address(struct cec_adapter *adapter, const u8 addr)
+{
+	int ret;
+
+	if (addr > CEC_ADDR_MAX)
+		return -EINVAL;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->set_logical_address(adapter, addr);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ *  __cec_rx_queue_len() - returns the lenght of a cec driver rx queue
+ * @adapter:	adapter pointer
+ */
+unsigned __cec_rx_queue_len(struct cec_adapter *adapter)
+{
+	unsigned qlen;
+
+	spin_lock(&adapter->rx_msg_list_lock);
+	qlen = adapter->rx_msg_len;
+	spin_unlock(&adapter->rx_msg_list_lock);
+
+	return qlen;
+}
+
+/**
+ * adapter_rx_done() - called by an adapter when message is received
+ * @adapter:	adapter pointer
+ * @data:	message blob
+ * @len:	message length
+ */
+int adapter_rx_done(struct cec_adapter *adapter,
+		    const u8 *data, const u8 len,
+		    bool valid, u8 rx_flags)
+{
+	struct cec_rx_kmsg *kmsg;
+	struct cec_rx_msg *msg;
+	int ret = 0;
+
+	if (!len || len > CEC_MAX_MSG_LEN)
+		return -EINVAL;
+
+	if (!adapter->attached) {
+		pr_debug("%s: no client attached, dropping", adapter->name);
+		goto out;
+	}
+
+	spin_lock(&adapter->rx_msg_list_lock);
+	if (adapter->rx_msg_len >= CEC_RX_QUEUE_MAX_LEN) {
+		pr_debug("%s: queue full!\n", adapter->name);
+		ret = -ENOSPC;
+		goto out_unlock;
+	}
+
+	kmsg = kzalloc(sizeof(*kmsg), GFP_ATOMIC);
+	if (!kmsg) {
+		ret = ENOMEM;
+		goto out_unlock;
+	}
+
+	msg = &kmsg->msg;
+	memcpy(&msg->data, data, len);
+	msg->len = len;
+	msg->valid = valid;
+	msg->flags = rx_flags;
+	list_add_tail(&kmsg->next, &adapter->rx_msg_list);
+	adapter->rx_msg_len++;
+
+out_unlock:
+	spin_unlock(&adapter->rx_msg_list_lock);
+
+	/* wake up clients, they can dequeue a buffer now */
+	wake_up_interruptible(&adapter->wait);
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(adapter_rx_done);
+
+/**
+ * cec_read_message() - reads a cec message from the adapter's rx queue
+ * @adapter:	adapter pointer
+ * @msg:	cec user-space exposed message pointer
+ *
+ * Reads a CEC message from the adapter's RX queue in blocking mode with
+ * either a finite or inifinite timeout
+ */
+int cec_read_message(struct cec_adapter *adapter,
+		     struct cec_rx_msg *msg,
+		     bool non_block)
+{
+	struct cec_rx_kmsg *kmsg;
+	int ret = 0;
+
+	if (!non_block) {
+		ret = wait_event_interruptible(adapter->wait,
+					       __cec_rx_queue_len(adapter) != 0 ||
+					       adapter->dead);
+		if (ret)
+			return ret;
+	}
+
+	if (adapter->dead)
+		return -ENODEV;
+
+	spin_lock(&adapter->rx_msg_list_lock);
+	if (list_empty(&adapter->rx_msg_list)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	kmsg = list_first_entry(&adapter->rx_msg_list,
+				struct cec_rx_kmsg, next);
+	memcpy(msg, &kmsg->msg, sizeof (*msg));
+	list_del(&kmsg->next);
+	kfree(kmsg);
+	adapter->rx_msg_len--;
+
+out:
+	spin_unlock(&adapter->rx_msg_list_lock);
+	return ret;
+}
+
+/**
+ * cec_send_message() - sends an user fed cec message
+ * @adapter:	adapter pointer
+ * @msg:	user-exposed cec message pointer
+ *
+ * Send a message using the specific adapter
+ */
+int cec_send_message(struct cec_adapter *adapter, struct cec_tx_msg *msg)
+{
+	unsigned long flags;
+	int ret;
+
+	if (!msg->len || msg->len > CEC_MAX_MSG_LEN)
+		return -EINVAL;
+
+	mutex_lock(&adapter->lock);
+
+	if (adapter->dead) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* prevent queuing more than one message */
+	if (test_bit(0, &adapter->tx_pending)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* default to 1 retransmit for polling messages, otherwise 3 */
+	if (!msg->tries)
+		msg->tries = msg->len == 1 ? 2 : 4;
+
+	/* try to send it */
+	set_bit(0, &adapter->tx_pending);
+	ret = adapter->ops->send(adapter, msg->expire_ms, msg->tries,
+				 msg->data, msg->len);
+
+	if (ret)
+		clear_bit(0, &adapter->tx_pending);
+	else {
+		spin_lock_irqsave(&adapter->tx_done_lock, flags);
+		if (test_bit(0, &adapter->tx_pending)) {
+			adapter->tx_timeout_timer.expires = jiffies + HZ * 5;
+			add_timer(&adapter->tx_timeout_timer);
+		}
+		spin_unlock_irqrestore(&adapter->tx_done_lock, flags);
+	}
+
+out:
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+/**
+ * adapter_tx_done() - called by adapter when tx is complete
+ * @adapter:	adapter pointer
+ *
+ */
+static void __adapter_tx_done(struct cec_adapter *adapter, bool success,
+			      u8 flags, u8 tries)
+{
+	if (!test_bit(0, &adapter->tx_pending)) {
+		WARN(1, "__adapter_tx_done called with no tx pending");
+		return;
+	}
+	adapter->last_tx_success = success;
+	adapter->last_tx_flags = flags;
+	adapter->last_tx_tries = tries;
+	clear_bit(0, &adapter->tx_pending);
+	wake_up_interruptible(&adapter->wait);
+}
+
+void adapter_tx_done(struct cec_adapter *adapter, bool success,
+		     u8 flags, u8 tries)
+{
+	spin_lock(&adapter->tx_done_lock);
+	del_timer_sync(&adapter->tx_timeout_timer);
+	__adapter_tx_done(adapter, success, flags, tries);
+	spin_unlock(&adapter->tx_done_lock);
+}
+
+EXPORT_SYMBOL(adapter_tx_done);
+
+/*
+ *
+ */
+static void adapter_tx_timeout(struct timer_list *t)
+{
+	struct cec_adapter *adapter = from_timer(adapter, t, tx_timeout_timer);
+	unsigned long flags;
+
+	dev_err(&adapter->dev, "tx timeout\n");
+
+	spin_lock_irqsave(&adapter->tx_done_lock, flags);
+	__adapter_tx_done(adapter, false, CEC_TX_F_UNKNOWN_ERROR, 0);
+	spin_unlock_irqrestore(&adapter->tx_done_lock, flags);
+}
+
+/**
+ * cec_reset_device() - resets a cec adapter
+ * @adapter:	adapter pointer
+ *
+ * Resets a CEC device to a sane state
+ */
+int cec_reset_device(struct cec_adapter *adapter)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->reset(adapter);
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+/**
+ * cec_get_counters() - gets counters from a cec adapter
+ * @adapter:	adapter pointer
+ * @cnt:	struct cec_counters pointer
+ *
+ * Get counters from the CEC adapter if supported, adapter should advertise
+ * CEC_HW_HAS_COUNTERS flag
+ */
+int cec_get_counters(struct cec_adapter *adapter, struct cec_counters *cnt)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (!(adapter->flags & CEC_HW_HAS_COUNTERS))
+		ret = -ENOTSUPP;
+	else if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->get_counters(adapter, cnt);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ * cec_set_detached_config() - send detached config to adapter
+ * @adapter:	adapter pointer
+ * @config:	config
+ *
+ */
+int cec_set_detached_config(struct cec_adapter *adapter,
+			    const struct cec_detached_config *config)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->set_detached_config(adapter, config);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ * cec_set_rx_mode() - sets the adapter receive mode
+ * @adapter:	adapter pointer
+ * @mode:	receive mode (accept all, unicast only)
+ *
+ * Set the receive mode filter of the adapter
+ */
+int cec_set_rx_mode(struct cec_adapter *adapter, enum cec_rx_mode mode)
+{
+	int ret;
+
+	if (~adapter->flags & CEC_HW_HAS_RX_FILTER)
+		return -ENOTSUPP;
+
+	if (mode >= CEC_RX_MODE_MAX)
+		return -EINVAL;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->set_rx_mode(adapter, mode);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ * cec_attach_host - attaches a host to the adapter
+ * @adapter:	adapter pointer
+ *
+ * Attaches the host to the adapter. In case the hardware is able
+ * to process CEC messages itself, it should now send them to the
+ * host for processing
+ */
+int cec_attach_host(struct cec_adapter *adapter)
+{
+	int ret = 0;
+
+	if (adapter->attached)
+		return -EBUSY;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else {
+		if (adapter->ops->attach)
+			ret = adapter->ops->attach(adapter);
+		if (!ret)
+			adapter->attached = true;
+	}
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+/**
+ * cec_detach_host - detaches a host from the adapter
+ * @adapter:	adapter pointer
+ *
+ * Detaches the host from the adapter. In case the hardware is able
+ * to process CEC messages itself, it should now keep the messages for
+ * itself and no longer send them to the host
+ */
+int cec_detach_host(struct cec_adapter *adapter)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else {
+		if (adapter->ops->detach(adapter))
+			adapter->ops->detach(adapter);
+		adapter->attached = false;
+	}
+	mutex_unlock(&adapter->lock);
+
+	return 0;
+}
+
+/**
+ * alloc_cec_adapter() - allocate a new cec adapter
+ * @priv_size:	sizeof of adapter private date
+ */
+struct cec_adapter *alloc_cec_adapter(size_t priv_size)
+{
+	size_t size;
+
+	size = sizeof (struct cec_adapter) + priv_size + CECDEV_PRIV_ALIGN;
+	return kzalloc(size, GFP_KERNEL);
+}
+EXPORT_SYMBOL(alloc_cec_adapter);
+
+/**
+ * cec_flush_queues() - flushes a cec adapter queues
+ * @adapter:	adapter pointer
+ */
+void cec_flush_queues(struct cec_adapter *adapter)
+{
+	struct cec_rx_kmsg *cur, *next;
+
+	spin_lock(&adapter->rx_msg_list_lock);
+
+	list_for_each_entry_safe(cur, next, &adapter->rx_msg_list, next)
+		kfree(cur);
+	INIT_LIST_HEAD(&adapter->rx_msg_list);
+	adapter->rx_msg_len = 0;
+
+	spin_unlock(&adapter->rx_msg_list_lock);
+}
+
+/*
+ * device refcounting
+ */
+int cec_get_adapter(struct cec_adapter *adapter)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	ret = adapter->dead;
+	if (!ret)
+		atomic_inc(&adapter->users);
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+void cec_put_adapter(struct cec_adapter *adapter)
+{
+	if (atomic_dec_and_test(&adapter->users))
+		kfree(adapter);
+}
+
+/**
+ * free_cec_adapter() - free cec adapter
+ */
+void free_cec_adapter(struct cec_adapter *adapter)
+{
+	cec_put_adapter(adapter);
+}
+EXPORT_SYMBOL(free_cec_adapter);
+
+/*
+ * called by sysfs when all device references have been dropped
+ */
+static void cec_adapter_sysfs_release(struct device *dev)
+{
+	struct cec_adapter *adapter = to_cec_adapter(dev);
+	free_cec_adapter(adapter);
+}
+
+/*
+ * cec device sysfs class
+ */
+static struct class cec_class = {
+	.name		= "cec",
+	.dev_release	= cec_adapter_sysfs_release,
+};
+
+/**
+ * register_cec_adapter() - registers a new cec adapter
+ * @cec_adapter:	cec_adapter pointer
+ */
+int register_cec_adapter(struct cec_adapter *adapter, struct device *parent)
+{
+	struct device *dev = &adapter->dev;
+	int ret;
+
+	if (!parent)
+		return -EINVAL;
+
+	memset(dev, 0, sizeof (*dev));
+
+	adapter->attached = false;
+	mutex_init(&adapter->lock);
+
+	adapter->tx_pending = 0;
+	spin_lock_init(&adapter->tx_done_lock);
+	init_waitqueue_head(&adapter->wait);
+
+	spin_lock_init(&adapter->rx_msg_list_lock);
+	INIT_LIST_HEAD(&adapter->rx_msg_list);
+	adapter->rx_msg_len = 0;
+
+	timer_setup(&adapter->tx_timeout_timer, adapter_tx_timeout, 0);
+
+	snprintf(adapter->name, sizeof (adapter->name),
+		 "%s%d", adapter->driver_name,
+		 cec_adapter_count++);
+
+	/* register to sysfs */
+	dev_set_name(dev, adapter->name);
+	dev->class = &cec_class;
+	dev->parent = parent;
+	device_initialize(dev);
+
+	/* create char device */
+	ret = cec_create_adapter_node(adapter);
+	if (ret < 0)
+		return ret;
+
+	ret = device_add(dev);
+	if (ret < 0) {
+		cec_remove_adapter_node(adapter);
+		return ret;
+	}
+
+	/* 2 users, driver itself + sysfs */
+	atomic_set(&adapter->users, 2);
+	dev_info(dev, "registered cec adapter\n");
+	return 0;
+}
+EXPORT_SYMBOL(register_cec_adapter);
+
+/**
+ * unregister_cec_adapter() - unregisters a cec adapter
+ * @cec_adapter:	cec_adapter pointer
+ */
+void unregister_cec_adapter(struct cec_adapter *adapter)
+{
+	/* mark as dead */
+	mutex_lock(&adapter->lock);
+	adapter->dead = true;
+	mutex_unlock(&adapter->lock);
+
+	/* from this point, no adapter ops can be called again */
+
+	/* unregister char dev openers */
+	cec_remove_adapter_node(adapter);
+
+	del_timer_sync(&adapter->tx_timeout_timer);
+
+	/* wake up any sleeper */
+	adapter->last_tx_success = false;
+	adapter->last_tx_flags = 0;
+	adapter->tx_pending = 0;
+	wake_up_all(&adapter->wait);
+
+	cec_detach_host(adapter);
+	cec_flush_queues(adapter);
+	/* let sysfs release the device */
+	dev_info(&adapter->dev, "unregistering cec adapter\n");
+	device_unregister(&adapter->dev);
+}
+
+EXPORT_SYMBOL(unregister_cec_adapter);
+
+static int __init cec_init(void)
+{
+	int ret;
+
+	ret = class_register(&cec_class);
+	if (ret) {
+		pr_err("failed to create cec device class\n");
+		return ret;
+	}
+
+	ret = cec_cdev_init();
+	if (ret) {
+		pr_err("failed to create devices\n");
+		goto failed_class;
+	}
+
+	return 0;
+
+failed_class:
+	class_unregister(&cec_class);
+	return 1;
+}
+
+static void __exit cec_exit(void)
+{
+	cec_cdev_exit();
+	class_unregister(&cec_class);
+}
+
+subsys_initcall(cec_init);
+module_exit(cec_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("HDMI CEC core driver");
+MODULE_LICENSE("GPL");
diff -Nruw linux-6.4-fbx/drivers/misc/hdmi-cec./dev.c linux-6.4-fbx/drivers/misc/hdmi-cec/dev.c
--- linux-6.4-fbx/drivers/misc/hdmi-cec./dev.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/hdmi-cec/dev.c	2017-02-23 16:14:36.426018848 +0100
@@ -0,0 +1,294 @@
+/*
+ * HDMI CEC character device code
+ *
+ * Copyright (C), 2011 Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the GPLv2 licensing terms
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#include <linux/hdmi-cec/hdmi-cec.h>
+#include <linux/hdmi-cec/dev.h>
+
+#include "hdmi-cec-priv.h"
+
+static int cec_major;
+
+static DEFINE_MUTEX(cec_minors_lock);
+static bool cec_minors[256];
+
+static int cec_dev_open(struct inode *i, struct file *f)
+{
+	struct cdev *cdev = i->i_cdev;
+	struct cec_adapter *adapter =
+			container_of(cdev, struct cec_adapter, cdev);
+
+	if (f->private_data)
+		return -EBUSY;
+
+	if (cec_get_adapter(adapter))
+		return -ENODEV;
+
+	f->private_data = adapter;
+	return cec_attach_host(adapter);
+}
+
+static int cec_dev_close(struct inode *i, struct file *f)
+{
+	struct cec_adapter *adapter = f->private_data;
+
+	cec_detach_host(adapter);
+	cec_flush_queues(adapter);
+	f->private_data = NULL;
+	cec_put_adapter(adapter);
+	return 0;
+}
+
+static int wait_tx_done(struct cec_adapter *adapter)
+{
+	int ret;
+
+	ret = wait_event_interruptible(adapter->wait,
+				       !test_bit(0, &adapter->tx_pending) ||
+				       adapter->dead);
+	if (ret)
+		return ret;
+
+	if (adapter->dead)
+		return -ENODEV;
+
+	return 0;
+}
+
+static long cec_dev_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct cec_adapter *adapter;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int val, ret;
+	struct cec_counters cnt;
+	struct cec_tx_status tx_status;
+	struct cec_detached_config config;
+
+	if (!f->private_data)
+		return -EINVAL;
+
+	adapter = f->private_data;
+
+	ret = -ENOTTY;
+	switch (cmd) {
+	case CEC_SET_LOGICAL_ADDRESS:
+		if (get_user(val, p))
+			return -EFAULT;
+
+		ret = cec_set_logical_address(adapter, (u8)val);
+		break;
+
+	case CEC_RESET_DEVICE:
+		ret = cec_reset_device(adapter);
+		break;
+
+	case CEC_GET_COUNTERS:
+		memset(&cnt, 0, sizeof(cnt));
+
+		ret = cec_get_counters(adapter, &cnt);
+		if (ret)
+			return ret;
+
+		if (copy_to_user(argp, &cnt, sizeof(cnt)))
+			return -EFAULT;
+		break;
+
+	case CEC_GET_TX_STATUS:
+		tx_status.sent = !test_bit(0, &adapter->tx_pending);
+		tx_status.success = adapter->last_tx_success;
+		tx_status.flags = adapter->last_tx_flags;
+		tx_status.tries = adapter->last_tx_tries;
+
+		if (copy_to_user(argp, &tx_status, sizeof(tx_status)))
+			return -EFAULT;
+
+		ret = 0;
+		break;
+
+	case CEC_SET_RX_MODE:
+		if (get_user(val, p))
+			return -EFAULT;
+
+		ret = cec_set_rx_mode(adapter, (enum cec_rx_mode)val);
+		break;
+
+	case CEC_SET_DETACHED_CONFIG:
+		if (copy_from_user(&config, argp, sizeof (config)))
+			return -EFAULT;
+
+		ret = cec_set_detached_config(adapter, &config);
+		break;
+
+	default:
+		dev_err(&adapter->dev, "unsupported ioctl: %08x\n", cmd);
+		break;
+	}
+
+	return ret;
+}
+
+static int cec_dev_write(struct file *f, const char __user *buf,
+			size_t count, loff_t *pos)
+{
+	struct cec_adapter *adapter = f->private_data;
+	struct cec_tx_msg msg;
+	int ret;
+
+	if (count != sizeof (struct cec_tx_msg))
+		return -EINVAL;
+
+	if (copy_from_user(&msg, buf, sizeof (msg)))
+		return -EFAULT;
+
+	ret = cec_send_message(adapter, &msg);
+	if (ret)
+		return ret;
+
+	if (!(f->f_flags & O_NONBLOCK)) {
+		ret = wait_tx_done(adapter);
+		if (ret)
+			return ret;
+
+		/* update status */
+		msg.success = adapter->last_tx_success;
+		msg.flags = adapter->last_tx_flags;
+		msg.tries = adapter->last_tx_tries;
+	}
+
+	if (copy_to_user((char __user *)buf, &msg, sizeof (msg)))
+		return -EFAULT;
+
+	return count;
+}
+
+static int cec_dev_read(struct file *f, char __user *buf,
+			size_t count, loff_t *pos)
+{
+	struct cec_adapter *adapter = f->private_data;
+	int ret;
+	struct cec_rx_msg msg;
+
+	if (count != sizeof (struct cec_rx_msg))
+		return -EINVAL;
+
+	ret = cec_read_message(adapter, &msg, f->f_flags & O_NONBLOCK);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(buf, &msg, sizeof (msg)))
+		return -EFAULT;
+
+	return sizeof (msg);
+}
+
+static unsigned int cec_dev_poll(struct file *f, poll_table *wait)
+{
+	struct cec_adapter *adapter = f->private_data;
+	unsigned int flags;
+
+	if (adapter->dead)
+		return POLLERR | POLLHUP;
+
+	poll_wait(f, &adapter->wait, wait);
+
+	flags = 0;
+	if (__cec_rx_queue_len(adapter))
+		flags |= POLLIN;
+
+	if (!test_bit(0, &adapter->tx_pending))
+		flags |= POLLOUT;
+
+	return flags;
+}
+
+static const struct file_operations cec_adapter_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.open		= cec_dev_open,
+	.release	= cec_dev_close,
+	.unlocked_ioctl	= cec_dev_ioctl,
+	.read		= cec_dev_read,
+	.write		= cec_dev_write,
+	.poll		= cec_dev_poll,
+};
+
+int cec_create_adapter_node(struct cec_adapter *adapter)
+{
+	size_t i;
+	dev_t devno;
+	int ret;
+
+	cdev_init(&adapter->cdev, &cec_adapter_fops);
+	adapter->cdev.kobj.parent = &adapter->dev.kobj;
+	adapter->cdev.owner = adapter->module;
+
+	/* allocate minor */
+	mutex_lock(&cec_minors_lock);
+	for (i = 0; i < ARRAY_SIZE(cec_minors); i++) {
+		if (!cec_minors[i])
+			break;
+	}
+	mutex_unlock(&cec_minors_lock);
+
+	if (i == ARRAY_SIZE(cec_minors)) {
+		dev_err(&adapter->dev, "no minor available\n");
+		return 1;
+	}
+
+	devno = MKDEV(cec_major, i);
+	ret = cdev_add(&adapter->cdev, devno, 1);
+	if (ret) {
+		dev_err(&adapter->dev, "failed to add char device\n");
+		return ret;
+	}
+
+	adapter->dev.devt = devno;
+	return 0;
+}
+
+void cec_remove_adapter_node(struct cec_adapter *adapter)
+{
+	mutex_lock(&cec_minors_lock);
+	cec_minors[MINOR(adapter->cdev.dev)] = false;
+	mutex_unlock(&cec_minors_lock);
+	cdev_del(&adapter->cdev);
+}
+
+int __init cec_cdev_init(void)
+{
+	dev_t dev = 0;
+	int ret;
+
+	ret = alloc_chrdev_region(&dev, 0, CEC_MAX_DEVS, "cec");
+	if (ret < 0) {
+		printk(KERN_ERR "alloc_chrdev_region() failed for cec\n");
+		goto out;
+	}
+
+	cec_major = MAJOR(dev);
+	return 0;
+
+out:
+	unregister_chrdev_region(MKDEV(cec_major, 0), CEC_MAX_DEVS);
+	return ret;
+}
+
+void __exit cec_cdev_exit(void)
+{
+	unregister_chrdev_region(MKDEV(cec_major, 0), CEC_MAX_DEVS);
+}
+
diff -Nruw linux-6.4-fbx/drivers/misc/hdmi-cec./hdmi-cec-priv.h linux-6.4-fbx/drivers/misc/hdmi-cec/hdmi-cec-priv.h
--- linux-6.4-fbx/drivers/misc/hdmi-cec./hdmi-cec-priv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/hdmi-cec/hdmi-cec-priv.h	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,34 @@
+#ifndef __HDMI_CEC_PRIV_H
+#define __HDMI_CEC_PRIV_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/**
+ * struct cec_rx_kmsg - kernel-side cec message cookie
+ * @msg:	user-side cec message cookie
+ * @next:	list pointer to next message
+ */
+struct cec_rx_kmsg {
+	struct cec_rx_msg	msg;
+	struct list_head	next;
+};
+
+int cec_get_adapter(struct cec_adapter *);
+void cec_put_adapter(struct cec_adapter *);
+int cec_read_message(struct cec_adapter *, struct cec_rx_msg *msg,
+		     bool non_block);
+int cec_send_message(struct cec_adapter *, struct cec_tx_msg *msg);
+int cec_reset_device(struct cec_adapter *);
+int cec_get_counters(struct cec_adapter *, struct cec_counters *cnt);
+int cec_set_logical_address(struct cec_adapter *, const u8 addr);
+int cec_set_rx_mode(struct cec_adapter *, enum cec_rx_mode mode);
+void cec_flush_queues(struct cec_adapter *);
+unsigned __cec_rx_queue_len(struct cec_adapter *);
+int cec_attach_host(struct cec_adapter *);
+int cec_detach_host(struct cec_adapter *);
+int cec_set_detached_config(struct cec_adapter *,
+			    const struct cec_detached_config *);
+
+#endif /* __HDMI_CEC_PRIV_H */
+
diff -Nruw linux-6.4-fbx/drivers/misc/hdmi-cec./remoti.c linux-6.4-fbx/drivers/misc/hdmi-cec/remoti.c
--- linux-6.4-fbx/drivers/misc/hdmi-cec./remoti.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/hdmi-cec/remoti.c	2017-02-23 16:14:36.426018848 +0100
@@ -0,0 +1,638 @@
+/*
+ * HDMI CEC driver using RemoTI IPCs
+ *
+ * Copyright (C) Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the GPLv2 licensing terms
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/remoti/remoti.h>
+#include <linux/of.h>
+
+#include <linux/hdmi-cec/hdmi-cec.h>
+
+/* HDMI CEC command (util subsystem) */
+#define RTI_CEC_SET_LADDR		0x20
+#define RTI_CEC_GET_CNT			0x21
+#define RTI_CEC_RST			0x22
+#define RTI_CEC_MODE			0x23
+#define RTI_CEC_ATTACH			0x24
+#define RTI_CEC_DETACH			0x25
+#define RTI_CEC_RECV_MSG_IND		0x26
+
+#define RTI_CEC_SEND_MSG_REQ		0x28
+#define RTI_CEC_SEND_MSG_CNF		0x29
+
+#define RTI_CEC_RECV_RAW_IND		0x2a
+#define RTI_CEC_SET_DETACHED_CONFIG	0x2b
+
+
+/*
+ * Exposed return status codes
+ */
+enum {
+	RTI_CEC_SUCCESS = 0,
+	RTI_CEC_INVALID,
+	RTI_CEC_TX_BUSY,
+	RTI_CEC_TX_FAIL,
+};
+
+/*
+ * Exposed modes
+ */
+enum {
+	RTI_CEC_MODE_DISABLED = 0,
+	RTI_CEC_MODE_NORMAL,
+	RTI_CEC_MODE_RAW,
+};
+
+/*
+ * rx filtering (normal mode)
+ */
+enum {
+	RTI_CEC_RX_FILTER_DEFAULT = 0,
+	RTI_CEC_RX_FILTER_PROMISC,
+};
+
+/*
+ * RTI data for rx message
+ *
+ * we send this as-is to host (no memcpy to create a message) so don't
+ * change field order
+ */
+enum rti_cec_rx_msg_flags {
+	/* global valid bit for all message (got eom & ack) */
+	RTI_CEC_RX_FLAG_VALID		= (1 << 0),
+
+	/* true if this is a complete message (else its truncated) */
+	RTI_CEC_RX_FLAG_GOT_EOM		= (1 << 1),
+
+	/* true if the message has been acked */
+	RTI_CEC_RX_FLAG_ACKED		= (1 << 2),
+};
+
+struct rti_cec_rx_msg {
+	/* bitmask of rti_cec_rx_msg_flags */
+	uint8_t	flags;
+
+	/* number of bits in data */
+	uint8_t	len;
+
+	/* all message data (no eom/ack bit here), we only send "len"
+	 * bytes of this array */
+	uint8_t	data[16];
+};
+
+#define RTI_CEC_RX_MSG_CONSTANT_LEN         \
+		offsetof(struct rti_cec_rx_msg, data)
+
+
+/*
+ * RTI data for tx completion
+ */
+enum rti_cec_tx_flags  {
+	/*
+	 * message was nacked at some point
+	 */
+	RTI_CEC_TX_F_NACK		= (1 << 0),
+
+	/*
+	 * abort sending because total time to send was elapsed
+	 */
+	RTI_CEC_TX_F_TIMEOUT		= (1 << 1),
+
+	/*
+	 * abort sending because maximum number of retry has passed
+	 */
+	RTI_CEC_TX_F_MAX_RETRIES	= (1 << 2),
+
+	/*
+	 * abort sending because of arbitration loss
+	 */
+	RTI_CEC_TX_F_ARBITRATION_LOST	= (1 << 3),
+
+	/*
+	 * abort sending because we failed to respect timings
+	 */
+	RTI_CEC_TX_F_MISSED_DEADLINE	= (1 << 4),
+};
+
+struct rti_cec_tx_status {
+	uint8_t	status;
+
+	uint8_t	flags;
+
+	/* number of tx tries we did (0 = no try done because of busy
+	 * bus) */
+	uint8_t	tries;
+};
+
+
+static inline int remoti_cec_map_error(const u8 ret)
+{
+	switch (ret) {
+	case RTI_CEC_SUCCESS:
+		return 0;
+	default:
+		return -EINVAL;
+	case RTI_CEC_TX_BUSY:
+		return -EBUSY;
+	case RTI_CEC_TX_FAIL:
+		return -EIO;
+	}
+}
+
+static DEFINE_MUTEX(remoti_cec_list_mutex);
+static struct list_head remoti_cec_list;
+
+/*
+ * Driver private context
+ */
+struct remoti_cec_priv {
+	struct platform_device	*pdev;
+	unsigned int		rti_dev_id;
+
+	struct rti_udev		*udev;
+	struct cec_adapter	*adapter;
+	struct list_head	next;
+};
+
+struct remoti_cec_adapter_priv {
+	struct remoti_cec_priv	*priv;
+};
+
+static int remoti_cec_send(struct cec_adapter *adapter,
+			   u16 expire_ms,
+			   u8 tries,
+			   const u8 *data,
+			   const u8 len)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_SEND_MSG_REQ;
+
+	msg.data[0] = expire_ms & 0xff;
+	msg.data[1] = (expire_ms >> 8) & 0xff;
+	memcpy(msg.data + 2, data, len);
+	msg.data_len = len + 2;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	if (msg.reply[0] != RTI_CEC_SUCCESS)
+		return remoti_cec_map_error(msg.reply[0]);
+
+	return 0;
+}
+
+
+static int remoti_cec_set_logical_address(struct cec_adapter *adapter,
+					  const u8 logical_address)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_SET_LADDR;
+
+	memcpy(msg.data, &logical_address, 1);
+	msg.data_len = sizeof (logical_address);
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static int remoti_cec_get_counters(struct cec_adapter *adapter,
+				   struct cec_counters *cnt)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_GET_CNT;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != sizeof (*cnt)) {
+		printk(KERN_ERR "invalid cec counters size\n");
+		return -EIO;
+	}
+
+	memcpy(cnt, msg.reply, msg.reply_len);
+	return 0;
+}
+
+static int remoti_cec_reset(struct cec_adapter *adapter)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_RST;
+
+	return rti_send_sync_msg(priv->udev, &msg);
+}
+
+static int remoti_cec_set_detached_config(struct cec_adapter *adapter,
+					  const struct cec_detached_config *cfg)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_SET_DETACHED_CONFIG;
+
+	msg.data_len = 4;
+	msg.data[0] = cfg->phys_addr_valid ? 1 : 0;
+	msg.data[1] = cfg->phys_addr[0];
+	msg.data[2] = cfg->phys_addr[1];
+	msg.data[3] = cfg->flags;
+
+	return rti_send_sync_msg(priv->udev, &msg);
+}
+
+static int remoti_cec_set_rx_mode(struct cec_adapter *adapter,
+				  enum cec_rx_mode rx_mode)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_MODE;
+
+	msg.data_len = 2;
+	if (rx_mode == CEC_RX_MODE_DISABLED)
+		msg.data[0] = RTI_CEC_MODE_DISABLED;
+	else {
+		msg.data[0] = RTI_CEC_MODE_NORMAL;
+		if (rx_mode == CEC_RX_MODE_ACCEPT_ALL)
+			msg.data[1] = RTI_CEC_RX_FILTER_PROMISC;
+		else
+			msg.data[1] = RTI_CEC_RX_FILTER_DEFAULT;
+	}
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static int remoti_cec_attach(struct cec_adapter *adapter)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_ATTACH;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static int remoti_cec_detach(struct cec_adapter *adapter)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_DETACH;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static void remoti_cec_recv_ind(void *cb_data,
+				const struct rti_msg *msg)
+{
+	struct remoti_cec_priv *priv = (struct remoti_cec_priv *)cb_data;
+	const struct rti_cec_rx_msg *rti_rx_msg;
+	u8 rx_flags;
+
+	if (msg->data_len < RTI_CEC_RX_MSG_CONSTANT_LEN) {
+		printk(KERN_ERR "invalid recv message size\n");
+		return;
+	}
+
+	rti_rx_msg = (const struct rti_cec_rx_msg *)msg->data;
+
+	/* ignore message with non full bytes */
+	if (rti_rx_msg->len % 8)
+		return;
+
+	/* send message to upper layers */
+	rx_flags = 0;
+	if (rti_rx_msg->flags & RTI_CEC_RX_FLAG_ACKED)
+		rx_flags |= CEC_RX_F_ACKED;
+	if (rti_rx_msg->flags & RTI_CEC_RX_FLAG_GOT_EOM)
+		rx_flags |= CEC_RX_F_COMPLETE;
+
+	adapter_rx_done(priv->adapter,
+			rti_rx_msg->data,
+			rti_rx_msg->len / 8,
+			rti_rx_msg->flags & RTI_CEC_RX_FLAG_VALID,
+			rx_flags);
+}
+
+static void remoti_cec_send_cnf(void *cb_data,
+				const struct rti_msg *msg)
+{
+	struct remoti_cec_priv *priv = (struct remoti_cec_priv *)cb_data;
+	const struct rti_cec_tx_status *rti_tx_status;
+	bool tx_success;
+	u8 tx_flags, tx_tries;
+
+	if (msg->data_len < sizeof (*rti_tx_status)) {
+		printk(KERN_ERR "bad completion status\n");
+		tx_success = false;
+		tx_flags = CEC_TX_F_UNKNOWN_ERROR;
+		tx_tries = 0;
+	} else {
+		rti_tx_status = (const struct rti_cec_tx_status *)msg->data;
+		tx_success = (rti_tx_status->status == RTI_CEC_SUCCESS);
+		tx_flags = 0;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_NACK)
+			tx_flags |= CEC_TX_F_NACK;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_TIMEOUT)
+			tx_flags |= CEC_TX_F_TIMEOUT;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_MAX_RETRIES)
+			tx_flags |= CEC_TX_F_MAX_RETRIES;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_ARBITRATION_LOST)
+			tx_flags |= CEC_TX_F_ARBITRATION_LOST;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_MISSED_DEADLINE)
+			tx_flags |= CEC_TX_F_UNKNOWN_ERROR;
+		tx_tries = rti_tx_status->tries;
+	}
+	adapter_tx_done(priv->adapter, tx_success, tx_flags, tx_tries);
+}
+
+static const struct rti_kcallback callbacks[] = {
+	{
+		.subsys		= NPI_SYS_UTIL,
+		.cmd		= RTI_CEC_RECV_MSG_IND,
+		.cb		= remoti_cec_recv_ind,
+	},
+
+	{
+		.subsys		= NPI_SYS_UTIL,
+		.cmd		= RTI_CEC_SEND_MSG_CNF,
+		.cb		= remoti_cec_send_cnf,
+	},
+};
+
+static const struct cec_adapter_ops remoti_cec_ops = {
+	.set_logical_address	= remoti_cec_set_logical_address,
+	.send			= remoti_cec_send,
+	.reset			= remoti_cec_reset,
+	.get_counters		= remoti_cec_get_counters,
+	.set_rx_mode		= remoti_cec_set_rx_mode,
+	.attach			= remoti_cec_attach,
+	.detach			= remoti_cec_detach,
+	.set_detached_config	= remoti_cec_set_detached_config,
+};
+
+static int try_register_cec_adapter(struct remoti_cec_priv *priv)
+{
+	struct cec_adapter *adapter;
+	struct remoti_cec_adapter_priv *apriv;
+	int ret;
+
+	BUG_ON(priv->udev);
+
+	priv->udev = rti_get_udevice(priv->rti_dev_id);
+	if (!priv->udev)
+		return 0;
+
+	adapter = alloc_cec_adapter(sizeof (*apriv));
+	if (!adapter) {
+		dev_err(&priv->pdev->dev, "failed to allocate memory\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* setup adapter */
+	adapter->driver_name = "remoti-cec";
+	adapter->ops = &remoti_cec_ops;
+	adapter->module = THIS_MODULE;
+	adapter->flags = CEC_HW_HAS_COUNTERS | CEC_HW_HAS_RX_FILTER;
+
+	/* setup adapter private data */
+	apriv = cec_adapter_priv(adapter);
+	apriv->priv = priv;
+
+	ret = register_cec_adapter(adapter, &priv->pdev->dev);
+	if (ret) {
+		dev_err(&priv->pdev->dev, "unable to register cec adapter\n");
+		goto fail_free;
+	}
+
+	priv->adapter = adapter;
+
+	ret = rti_register_cmds_callback(priv->udev,
+					 callbacks, ARRAY_SIZE(callbacks),
+					 priv);
+	if (ret) {
+		dev_err(&priv->pdev->dev, "unable to register rti callback\n");
+		goto fail_unregister;
+	}
+
+	return 0;
+
+fail_unregister:
+	unregister_cec_adapter(adapter);
+
+fail_free:
+	free_cec_adapter(adapter);
+	priv->adapter = NULL;
+
+fail:
+	rti_release_udevice(priv->udev);
+	priv->udev = NULL;
+	return ret;
+}
+
+static int rti_udev_notifier_cb(struct notifier_block *n,
+				unsigned long id, void *data)
+{
+	struct remoti_cec_priv *priv;
+	enum rti_udev_state *st = (enum rti_udev_state *)data;
+
+	mutex_lock(&remoti_cec_list_mutex);
+
+	list_for_each_entry(priv, &remoti_cec_list, next) {
+
+		if (priv->rti_dev_id != id)
+			continue;
+
+		switch (*st) {
+		case RTI_UDEV_UP:
+			if (priv->udev)
+				continue;
+
+			try_register_cec_adapter(priv);
+			break;
+
+		case RTI_UDEV_GOING_DOWN:
+			if (!priv->udev)
+				continue;
+
+			unregister_cec_adapter(priv->adapter);
+			free_cec_adapter(priv->adapter);
+			rti_release_udevice(priv->udev);
+			priv->udev = NULL;
+			break;
+		}
+	}
+
+	mutex_unlock(&remoti_cec_list_mutex);
+	return 0;
+}
+
+static struct notifier_block rti_udev_notifier_block = {
+	.notifier_call = rti_udev_notifier_cb,
+};
+
+
+static int remoti_cec_probe(struct platform_device *pdev)
+{
+	struct remoti_cec_priv *priv;
+
+	priv = kzalloc(sizeof (*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	priv->pdev = pdev;
+	platform_set_drvdata(pdev, priv);
+
+	mutex_lock(&remoti_cec_list_mutex);
+	try_register_cec_adapter(priv);
+	list_add_tail(&priv->next, &remoti_cec_list);
+	mutex_unlock(&remoti_cec_list_mutex);
+	return 0;
+}
+
+static int remoti_cec_remove(struct platform_device *pdev)
+{
+	struct remoti_cec_priv *priv = platform_get_drvdata(pdev);
+
+	mutex_lock(&remoti_cec_list_mutex);
+	if (priv->udev) {
+		rti_unregister_cmds_callback(priv->udev,
+					     callbacks, ARRAY_SIZE(callbacks));
+		unregister_cec_adapter(priv->adapter);
+		free_cec_adapter(priv->adapter);
+		rti_release_udevice(priv->udev);
+	}
+	mutex_unlock(&remoti_cec_list_mutex);
+	kfree(priv);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct of_device_id remoti_cec_of_ids[] = {
+	{ .compatible = "ti,remoti-cec" },
+	{ /* sentinel*/ },
+};
+MODULE_DEVICE_TABLE(of, remoti_cec_of_ids);
+
+static struct platform_driver remoti_cec_driver = {
+	.driver	= {
+		.name	= "remoti-cec",
+		.owner	= THIS_MODULE,
+		.of_match_table = remoti_cec_of_ids,
+	},
+	.probe	= remoti_cec_probe,
+	.remove	= remoti_cec_remove,
+};
+
+static int __init remoti_cec_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_cec_list);
+
+	ret = platform_driver_register(&remoti_cec_driver);
+	if (ret)
+		return ret;
+
+	rti_register_udevice_notifier(&rti_udev_notifier_block);
+	return 0;
+}
+
+static void __exit remoti_cec_exit(void)
+{
+	rti_unregister_udevice_notifier(&rti_udev_notifier_block);
+	platform_driver_unregister(&remoti_cec_driver);
+}
+
+module_init(remoti_cec_init);
+module_exit(remoti_cec_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("CEC transport over RemoTI");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:remoti-cec");
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/drivers/misc/pic16-pmu.c	2023-11-29 17:07:10.431656439 +0100
@@ -0,0 +1,699 @@
+/*
+ * PIC16F72x PMU / LED / button driver
+ *
+ * Copyright (C) 2010, Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the GPLv2 licensing terms
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/input.h>
+#include <linux/input-event-codes.h>
+#include <linux/slab.h>
+#include <linux/gpio/driver.h>
+
+#define PIC16_PMU_LED_COUNT		3
+#define PIC16_PMU_PWR_COUNT		3
+#define PIC16_PMU_BTN_COUNT		3
+#define PIC16_PMU_RST_COUNT		1
+
+/*
+ * Per LED private structure
+ */
+struct pic16_pmu_led_data {
+	u8 id;
+	u8 status:1;
+	u8 blink:1;
+	struct led_classdev ldev;
+	struct i2c_client *client;
+	struct work_struct work;
+};
+
+struct pic16_pmu_input_data {
+	struct i2c_client *client;
+	struct input_dev  *input_dev;
+	unsigned short keymap[PIC16_PMU_BTN_COUNT];
+};
+
+static unsigned short default_map[PIC16_PMU_BTN_COUNT] = {
+	BTN_0,
+	BTN_1,
+	BTN_2,
+};
+
+/*
+ * Global device structure
+ */
+struct pic16_pmu_data {
+	struct device *hwmon_dev;
+	struct attribute_group attrs;
+	struct mutex lock;
+	unsigned long last_updated;
+	struct i2c_client *client;
+	struct pic16_pmu_led_data leds[PIC16_PMU_LED_COUNT];
+	struct pic16_pmu_input_data btns;
+	u8 model;
+	u8 revision;
+	u8 power;
+	u8 buttons;
+	u8 resets;
+	u8 hw_revision;
+	struct gpio_chip chip;
+};
+
+static const unsigned short normal_i2c[] = { 0x60, I2C_CLIENT_END };
+
+static const struct i2c_device_id pic16_pmu_idtable[] = {
+	{ "pic16-pmu", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, pic16_pmu_idtable);
+
+/*
+ * device registers
+ */
+#define PIC16_PMU_REG_DEV	0x00
+#define  PIC16_PMU_16F722	0x22
+
+#define PIC16_PMU_REG_REV	0x01
+#define PIC16_PMU_REG_LED	0x02
+#define PIC16_PMU_REG_PWR	0x03
+#define  PIC16_PMU_REG_PWR_MSK	0x1f
+#define PIC16_PMU_REG_BTN	0x04
+#define PIC16_PMU_REG_RST	0x05
+#define  PIC16_PMU_REG_RST_MSK	0x05
+#define PIC16_PMU_REG_CTL	0x06
+#define PIC16_PMU_REG_BLINK	0x07
+#define PIC16_PMU_REG_HW_REV	0x08
+
+#define PIC16_PMU_REFRESH	(60 * HZ)	/* 1 minute */
+
+static inline int pic16_pmu_reg_read(struct i2c_client *client, u8 reg, u8 *value)
+{
+	int tmp;
+
+	tmp = i2c_smbus_read_byte_data(client, reg);
+	if (tmp < 0) {
+		tmp = i2c_smbus_read_byte_data(client, reg);
+		if (tmp < 0)
+			return -EINVAL;
+	}
+
+	*value = tmp;
+
+	return 0;
+}
+
+static inline int pic16_pmu_reg_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static struct pic16_pmu_data *pic16_pmu_update(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+	u8 val;
+	int ret;
+	unsigned long local_jiffies = jiffies;
+
+	mutex_lock(&data->lock);
+	if (time_before(local_jiffies, data->last_updated +
+			PIC16_PMU_REFRESH))
+		goto exit;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_DEV, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading device model\n");
+		goto exit;
+	}
+	data->model = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_REV, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading revision\n");
+		goto exit;
+	}
+	data->revision = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_PWR, &val);
+	if (ret) {
+		dev_err(&client->dev, "erorr reading power status\n");
+		goto exit;
+	}
+	data->power = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_BTN, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading button status\n");
+		goto exit;
+	}
+	data->buttons = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_RST, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading reset status\n");
+		goto exit;
+	}
+	data->resets = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_HW_REV, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading hw revision\n");
+		goto exit;
+	}
+	data->hw_revision = val;
+
+	data->last_updated = local_jiffies;
+exit:
+	mutex_unlock(&data->lock);
+	return data;
+}
+
+static ssize_t show_pwr(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	int val;
+
+	val = (((data->power & PIC16_PMU_REG_PWR_MSK) &
+					(1 << attr->index)) >> attr->index);
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t show_model(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	return sprintf(buf, "Microchip PIC16F%02x\n", data->model);
+}
+
+static ssize_t show_revision(struct device *dev,
+			struct device_attribute *devattrr,
+			char *buf)
+{
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	return sprintf(buf, "%02x\n", data->revision);
+}
+
+static ssize_t show_hw_revision(struct device *dev,
+			struct device_attribute *devattrr,
+			char *buf)
+{
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	return sprintf(buf, "%02x\n", data->hw_revision);
+}
+
+static ssize_t show_rst(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	int val;
+
+	val = (((data->resets & PIC16_PMU_REG_RST_MSK) &
+					(1 << attr->index)) >> attr->index);
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static int pic16_pmu_set_reset(struct i2c_client *client,
+				struct pic16_pmu_data *data,
+				unsigned int index, long value)
+{
+	int ret;
+	u8 val = data->resets;
+
+	if (value)
+		val |= (1 << index);
+	else
+		val &= ~(1 << index);
+
+	data->resets = val;
+
+	mutex_lock(&data->lock);
+	ret = pic16_pmu_reg_write(client, PIC16_PMU_REG_RST, val);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t set_rst(struct device *dev,
+			struct device_attribute *devattr,
+			const char *buf,
+			size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	long temp;
+
+	if (kstrtol(buf, 10, &temp))
+		return -EINVAL;
+
+	pic16_pmu_set_reset(client, data, attr->index, temp);
+
+	return count;
+}
+
+static ssize_t show_btn(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+	u8 val = 0;
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_BTN, &val);
+	if (ret) {
+		dev_err(&client->dev, "unable to read status\n");
+		goto out_unlock;
+	}
+
+	val = (val & (1 << attr->index)) >> attr->index;
+
+out_unlock:
+	mutex_unlock(&data->lock);
+	return sprintf(buf, "%u\n", 1 - val);
+}
+
+/*
+ * Power attributes
+ */
+static SENSOR_DEVICE_ATTR(pwrgd_ps, S_IRUGO, show_pwr, NULL, 0);
+static SENSOR_DEVICE_ATTR(vcc1p5_ddr_pg, S_IRUGO, show_pwr, NULL, 1);
+static SENSOR_DEVICE_ATTR(vcc0p95_core_ok, S_IRUGO, show_pwr, NULL, 2);
+static SENSOR_DEVICE_ATTR(power_state, S_IRUGO, show_pwr, NULL, 3);
+static SENSOR_DEVICE_ATTR(standby_state, S_IRUGO, show_pwr, NULL, 4);
+
+/*
+ * Device revision attributes
+ */
+static SENSOR_DEVICE_ATTR(revision, S_IRUGO, show_revision, NULL, 0);
+static SENSOR_DEVICE_ATTR(model, S_IRUGO, show_model, NULL, 0);
+static SENSOR_DEVICE_ATTR(hw_revision, S_IRUGO, show_hw_revision, NULL, 0);
+
+/*
+ * Reset control attributes
+ */
+static SENSOR_DEVICE_ATTR(rf_rst, S_IWUSR | S_IRUGO, show_rst, set_rst, 0);
+static SENSOR_DEVICE_ATTR(cold_rst, S_IWUSR | S_IRUGO, show_rst, set_rst, 1);
+static SENSOR_DEVICE_ATTR(dvd_en, S_IWUSR | S_IRUGO, show_rst, set_rst, 2);
+
+/*
+ * Button attributes
+ */
+static SENSOR_DEVICE_ATTR(bank0_btn, S_IRUGO, show_btn, NULL, 0);
+static SENSOR_DEVICE_ATTR(reset_btn, S_IRUGO, show_btn, NULL, 1);
+static SENSOR_DEVICE_ATTR(power_btn, S_IRUGO, show_btn, NULL, 2);
+
+static struct attribute *pic16_pmu_attr[] = {
+	&sensor_dev_attr_pwrgd_ps.dev_attr.attr,
+	&sensor_dev_attr_vcc1p5_ddr_pg.dev_attr.attr,
+	&sensor_dev_attr_vcc0p95_core_ok.dev_attr.attr,
+	&sensor_dev_attr_power_state.dev_attr.attr,
+	&sensor_dev_attr_standby_state.dev_attr.attr,
+	&sensor_dev_attr_revision.dev_attr.attr,
+	&sensor_dev_attr_model.dev_attr.attr,
+	&sensor_dev_attr_rf_rst.dev_attr.attr,
+	&sensor_dev_attr_cold_rst.dev_attr.attr,
+	&sensor_dev_attr_dvd_en.dev_attr.attr,
+	&sensor_dev_attr_hw_revision.dev_attr.attr,
+	&sensor_dev_attr_bank0_btn.dev_attr.attr,
+	&sensor_dev_attr_reset_btn.dev_attr.attr,
+	&sensor_dev_attr_power_btn.dev_attr.attr,
+	NULL
+};
+
+static void pic16_pmu_set_brightness(struct led_classdev *led_cdev,
+				enum led_brightness brightness)
+{
+	struct pic16_pmu_led_data *led;
+
+	led = container_of(led_cdev, struct pic16_pmu_led_data, ldev);
+	led->status = brightness;
+	schedule_work(&led->work);
+}
+
+static int pic16_pmu_set_blink(struct led_classdev *led_cdev,
+				unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct pic16_pmu_led_data *led;
+
+	led = container_of(led_cdev, struct pic16_pmu_led_data, ldev);
+	led->blink = !led->blink;
+	schedule_work(&led->work);
+
+	return 0;
+}
+
+static int pic16_pmu_led_set(struct pic16_pmu_led_data *led, u8 status, u8 blink)
+{
+	struct pic16_pmu_data *data = i2c_get_clientdata(led->client);
+	int ret;
+	u8 val = 0;
+
+	mutex_lock(&data->lock);
+
+	ret = pic16_pmu_reg_read(led->client, PIC16_PMU_REG_BLINK, &val);
+	if( ret) {
+		dev_err(&led->client->dev, "error reading BLINK reg for %d\n",
+								led->id);
+		goto exit;
+	}
+
+	if (blink)
+		val |= (1 << led->id);
+	else
+		val &= ~(1 << led->id);
+
+	ret = pic16_pmu_reg_write(led->client, PIC16_PMU_REG_BLINK, val);
+	if (ret) {
+		dev_err(&led->client->dev, "error writing back to BLINK reg value"
+							" for %d\n", led->id);
+		goto exit;
+	}
+
+	val = (1 << (led->id + 4));
+	if (status)
+		val |= (1 << led->id);
+
+	ret = pic16_pmu_reg_write(led->client, PIC16_PMU_REG_LED, val);
+	if (ret) {
+		dev_err(&led->client->dev, "error writing back to LED reg value"
+			" for %d\n", led->id);
+		goto exit;
+	}
+
+exit:
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static void pic16_pmu_led_work(struct work_struct *work)
+{
+	struct pic16_pmu_led_data *led;
+
+	led = container_of(work, struct pic16_pmu_led_data, work);
+	pic16_pmu_led_set(led, led->status, led->blink);
+}
+
+static struct led_classdev pic16_pmu_leds[] = {
+	{	.name			= "power:red", },
+	{ 	.name			= "power:blue", },
+	{	.name			= "error:red",},
+};
+
+static int pic16_pmu_led_configure(struct i2c_client *client)
+{
+	int i, err = 0;
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+	u8 val;
+
+	mutex_lock(&data->lock);
+	err = pic16_pmu_reg_read(client, PIC16_PMU_REG_LED, &val);
+	mutex_unlock(&data->lock);
+
+	if (err)
+		return err;
+
+	data->last_updated = jiffies - PIC16_PMU_REFRESH - 1;
+
+	for (i = 0; i < PIC16_PMU_LED_COUNT; i++) {
+		struct pic16_pmu_led_data *led = &data->leds[i];
+
+		led->id = i;
+		led->client = client;
+
+		led->status = val & (1 << i);
+		memcpy(&led->ldev, &pic16_pmu_leds[i], sizeof(struct led_classdev));
+
+		led->ldev.max_brightness = 1;
+		led->ldev.brightness_set = pic16_pmu_set_brightness;
+		led->ldev.blink_set = pic16_pmu_set_blink;
+		led->ldev.flags	= LED_CORE_SUSPENDRESUME;
+
+		INIT_WORK(&led->work, pic16_pmu_led_work);
+		err = led_classdev_register(&client->dev, &led->ldev);
+		if (err < 0) {
+			dev_err(&client->dev, "cannot register LED %s\n",
+				led->ldev.name);
+			goto exit;
+		}
+	}
+
+	return err;
+exit:
+	if (i > 0) {
+		for (i = i - 1; i >= 0; i--) {
+			led_classdev_unregister(&data->leds[i].ldev);
+			cancel_work_sync(&data->leds[i].work);
+		}
+	}
+	return err;
+}
+
+static int pic16_pmu_detect(struct i2c_client *client,
+			    struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int device, revision;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	device = i2c_smbus_read_byte_data(client, PIC16_PMU_REG_DEV);
+	if (device != PIC16_PMU_16F722)
+		return -ENODEV;
+
+	revision = i2c_smbus_read_byte_data(client, PIC16_PMU_REG_REV);
+	dev_info(&client->dev, "device: PIC16F%02x rev: %02x\n",
+		 device, revision);
+
+	strlcpy(info->type, "pic16-pmu", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+/*
+ * input callbacks
+ */
+static void pic16_pmu_input_poll(struct input_dev *input)
+{
+	struct pic16_pmu_data *data = input_get_drvdata(input);
+	struct pic16_pmu_input_data *priv = &data->btns;
+	u8 val;
+	int ret, i;
+
+	mutex_lock(&data->lock);
+	ret = pic16_pmu_reg_read(priv->client, PIC16_PMU_REG_BTN, &val);
+	if (ret) {
+		dev_err(&input->dev, "unable to read status\n");
+		goto out_unlock;
+	}
+
+	for (i = 0; i < PIC16_PMU_BTN_COUNT; i++)
+		input_report_key(input, priv->keymap[i],
+				(val & (1 << i)) ? 0 : 1);
+	input_sync(input);
+
+out_unlock:
+	mutex_unlock(&data->lock);
+}
+
+/*
+ * gpiolib callbacks
+ */
+static void pic16_pmu_gpio_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	struct pic16_pmu_data *data;
+
+	data = container_of(chip, struct pic16_pmu_data, chip);
+
+	pic16_pmu_set_reset(data->client, data, offset, value);
+}
+
+static int pic16_pmu_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct pic16_pmu_data *data;
+
+	data = container_of(chip, struct pic16_pmu_data, chip);
+
+	return data->resets & (1 << offset);
+}
+
+static int pic16_pmu_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return 0;
+}
+
+static int pic16_pmu_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	return 0;
+}
+
+static int pic16_pmu_probe(struct i2c_client *client)
+{
+	struct pic16_pmu_data *data;
+	struct input_dev *input;
+	int err, i;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->lock);
+
+	dev_info(&client->dev, "%s chip found\n", client->name);
+
+	data->attrs.attrs = pic16_pmu_attr;
+	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
+	if (err)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	input = input_allocate_device();
+	if (!input) {
+		err = -ENOMEM;
+		goto exit_hwmon;
+	}
+
+	data->btns.client = client;
+	data->btns.input_dev = input;
+	memcpy(data->btns.keymap, default_map, sizeof(default_map));
+	input_set_drvdata(input, data);
+
+	err = input_setup_polling(input, pic16_pmu_input_poll);
+	if (err)
+		goto exit_input;
+	input_set_poll_interval(input, 200 /* ms */);
+
+	input->name = "pic16-pmu";
+	input->phys = "pic16-pmu/input0";
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+	input->keycode = data->btns.keymap;
+	input->keycodemax = ARRAY_SIZE(data->btns.keymap);
+	input->keycodesize = sizeof(unsigned short);
+
+	set_bit(EV_KEY, input->evbit);
+	for (i = 0; i < ARRAY_SIZE(data->btns.keymap); i++)
+		set_bit(data->btns.keymap[i], input->keybit);
+
+	err = input_register_device(input);
+	if (err)
+		goto exit_input;
+
+	/*
+	 * update device on startup to provide consistent
+	 * informations
+	 */
+	pic16_pmu_update(&client->dev);
+
+	/* Register gpiochip driver */
+	data->chip.label = "pic16-pmu";
+	data->chip.set = pic16_pmu_gpio_set;
+	data->chip.get = pic16_pmu_gpio_get;
+	data->chip.direction_input = pic16_pmu_gpio_direction_input;
+	data->chip.direction_output = pic16_pmu_gpio_direction_output;
+	data->chip.base = 100;
+	data->chip.ngpio = PIC16_PMU_RST_COUNT;
+
+	err = gpiochip_add(&data->chip);
+	if (err)
+		goto exit_input;
+
+	return pic16_pmu_led_configure(client);
+
+exit_input:
+	input_free_device(input);
+exit_hwmon:
+	hwmon_device_unregister(data->hwmon_dev);
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &data->attrs);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static void pic16_pmu_remove(struct i2c_client *client)
+{
+	int i;
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+
+	gpiochip_remove(&data->chip);
+
+	for (i = 0; i < PIC16_PMU_LED_COUNT; i++) {
+		led_classdev_unregister(&data->leds[i].ldev);
+		cancel_work_sync(&data->leds[i].work);
+	}
+
+	input_unregister_device(data->btns.input_dev);
+	input_free_device(data->btns.input_dev);
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &data->attrs);
+	kfree(data);
+	i2c_set_clientdata(client, NULL);
+}
+
+static struct i2c_driver pic16_pmu_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver	= {
+		.name	= "pic16-pmu",
+	},
+	.id_table	= pic16_pmu_idtable,
+	.probe		= pic16_pmu_probe,
+	.remove		= pic16_pmu_remove,
+	.detect		= pic16_pmu_detect,
+};
+
+static int __init pic16_pmu_init(void)
+{
+	return i2c_add_driver(&pic16_pmu_driver);
+}
+
+static void __exit pic16_pmu_exit(void)
+{
+	i2c_del_driver(&pic16_pmu_driver);
+}
+
+module_init(pic16_pmu_init);
+module_exit(pic16_pmu_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("PIC16F7xx PMU / LED i2c driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pic16-pmu");
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./Kconfig linux-6.4-fbx/drivers/misc/remoti/Kconfig
--- linux-6.4-fbx/drivers/misc/remoti./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/Kconfig	2022-08-30 19:20:26.103578149 +0200
@@ -0,0 +1,26 @@
+menu "RemoTI support"
+
+config REMOTI
+	tristate "RemoTI support"
+	depends on FBX6HD
+	help
+	  Texas Instruments RemoTI stack.
+
+config REMOTI_LEDS
+	tristate "RemoTI LEDS support"
+	depends on REMOTI
+	depends on LEDS_CLASS
+	help
+	  RemoTI LEDS class driver support.
+
+config REMOTI_GPIO
+	tristate "RemoTI gpio support"
+	depends on REMOTI
+	help
+	  gpiochip driver for the RemoTI RNP
+
+config REMOTI_USER
+	tristate "RemoTI userspace access"
+	depends on REMOTI
+
+endmenu
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./Makefile linux-6.4-fbx/drivers/misc/remoti/Makefile
--- linux-6.4-fbx/drivers/misc/remoti./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/Makefile	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,9 @@
+obj-$(CONFIG_REMOTI)		+= remoti.o
+obj-$(CONFIG_REMOTI_GPIO)	+= remoti-gpio.o
+obj-$(CONFIG_REMOTI_LEDS)	+= remoti-leds.o
+obj-$(CONFIG_REMOTI_USER)	+= remoti-user.o
+
+remoti-objs			:= core.o core-sysfs.o
+remoti-gpio-objs		:= gpio.o
+remoti-leds-objs		:= leds.o
+remoti-user-objs		:= user.o
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./core-priv.h linux-6.4-fbx/drivers/misc/remoti/core-priv.h
--- linux-6.4-fbx/drivers/misc/remoti./core-priv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/core-priv.h	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,229 @@
+#ifndef __REMOTI_PRIV_H
+#define __REMOTI_PRIV_H
+
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/remoti/remoti.h>
+
+/*
+ * firmware related
+ */
+#define RTI_FW_HDR_OFFSET	0xc0
+
+struct remoti_fw_header {
+        __le32		enable_op;
+        __le16		start_addr;
+        __le32		version;
+} __packed;
+
+/*
+ * RCAF RPCs used during boot
+ */
+#define RTI_READ_ITEM		0x01
+#define RTI_SB_RELOAD		0x10
+
+#define RTI_INIT_CNF		0x01
+
+struct rti_rcaf_read_item_req {
+	u8		item;
+	u8		item_len;
+};
+
+struct rti_rcaf_read_item_resp {
+	u8		status;
+	u8		value[0];
+};
+
+#define RTI_ITEM_FW_VER		0xc4
+
+
+/*
+ * Serial bootloader RPCs
+ */
+#define RTI_SB_HSK_REQ		0x04
+#define RTI_SB_WRITE_REQ	0x01
+#define RTI_SB_READ_REQ		0x02
+#define RTI_SB_ENABLE_REQ	0x03
+
+#define RTI_SB_FLASH_WORD	4
+#define SB_SUCCESS		0
+#define SB_DATA_SIZE		64
+
+struct rti_sb_write_req {
+	__le16	addr;
+	u8	data[SB_DATA_SIZE];
+} __packed;
+
+struct rti_sb_read_req {
+	__le16 addr;
+} __packed;
+
+struct rti_sb_read_resp {
+	u8 status;
+	__le16 addr;
+	u8 data[SB_DATA_SIZE];
+} __packed;
+
+/*
+ * util RPC used
+ */
+#define RTI_DBG_PRINT_IND		0x30
+#define RTI_DBG_ASSERT_IND		0x31
+
+/*
+ * uart protocol
+ */
+#define RTI_UART_CHR_WAKEUP		0x00
+#define RTI_UART_CHR_SOF		0xFE
+
+/*
+ * len (1 byte) + subsystem (1 bytes) + command (1 byte) + data (variable)
+ */
+#define RTI_MAX_FRAME_LEN		(3 + NPI_MAX_DATA_LEN)
+
+enum remoti_tty_fsm_state {
+	RTI_TTY_FSM_SOF = 0,
+	RTI_TTY_FSM_LEN,
+	RTI_TTY_FSM_DATA,
+	RTI_TTY_FSM_FCS
+};
+
+/*
+ * message list
+ */
+enum remoti_tx_msg_state {
+	RTI_TX_MSG_S_WAITING = 0,
+	RTI_TX_MSG_S_SOF_SENT,
+	RTI_TX_MSG_S_HDR_SENT,
+	RTI_TX_MSG_S_DATA_SENT,
+	RTI_TX_MSG_S_SENT,
+	RTI_TX_MSG_S_WAIT_RX_ACK,
+};
+
+struct remoti_tx_msg {
+	struct rti_msg			*msg;
+	bool				need_rx_ack;
+	enum remoti_tx_msg_state	tx_state;
+	unsigned int			tx_data_sent;
+	u8				fcs;
+	atomic_t			users;
+	bool				canceled;
+	struct completion		complete;
+	struct list_head		next;
+};
+
+struct remoti_rx_msg {
+	struct rti_msg			msg;
+	struct list_head		next;
+};
+
+/*
+ * callback list
+ */
+struct remoti_cmd_callback {
+	u8				subsys;
+	u8				cmd;
+	/* this callback cannot sleep */
+	void				(*cb)(void *cb_priv,
+					      const struct rti_msg *msg);
+	void				*cb_priv;
+
+	struct list_head		next;
+};
+
+/*
+ * device context
+ */
+struct remoti_device {
+	struct platform_device		*pdev;
+	struct remoti_dev_pdata		pdata;
+	enum rti_dev_state		state;
+	spinlock_t			state_lock;
+	struct rti_dev_stats		stats;
+	u32				fw_version;
+	bool				timeout;
+
+	struct tty_struct		*tty;
+	enum remoti_tty_fsm_state	tty_fsm_state;
+
+	spinlock_t			callback_list_lock;
+	struct list_head		callback_list;
+
+	struct workqueue_struct		*io_workqueue;
+	struct work_struct		tx_work;
+	bool				tx_need_send_wakeup;
+	struct list_head		tx_msg_list;
+	spinlock_t			tx_msg_list_lock;
+
+	struct work_struct		rx_work;
+	u8				rx_buf[RTI_MAX_FRAME_LEN];
+	u8				rx_buf_len;
+	struct list_head		rx_msg_list;
+	spinlock_t			rx_msg_list_lock;
+
+	/* asserted when we receive WAKEUP char on uart */
+	struct completion		wakeup_complete;
+
+	/* asserted when we receive INIT_CNF on uart */
+	struct completion		init_cnf_complete;
+
+	/* device fsm manager */
+	struct workqueue_struct		*fsm_workqueue;
+	struct work_struct		hw_fsm_work;
+	u32				boot_flags;
+	struct mutex			req_state_mutex;
+	bool				req_state;
+	bool				req_state_changed;
+
+	/* high level users */
+	struct device			dev;
+	atomic_t			user_count;
+	struct list_head		next;
+};
+
+/*
+ *
+ */
+static inline bool dev_is_operational(struct remoti_device *rd)
+{
+	bool res;
+
+	spin_lock(&rd->state_lock);
+	res = (rd->state == RTI_DEV_S_OPERATIONAL);
+	spin_unlock(&rd->state_lock);
+
+	return res;
+}
+
+static inline bool dev_is_stopping(struct remoti_device *rd)
+{
+	bool res;
+
+	spin_lock(&rd->state_lock);
+	res = (rd->state == RTI_DEV_S_STOPPING);
+	spin_unlock(&rd->state_lock);
+
+	return res;
+}
+
+/*
+ * core-sysfs.c
+ */
+void remoti_dev_change_sysfs(struct remoti_device *rd);
+
+int remoti_register_dev_sysfs(struct remoti_device *rd);
+
+void remoti_unregister_dev_sysfs(struct remoti_device *rd);
+
+void __remoti_free_device(struct remoti_device *rd);
+
+int __init remoti_sysfs_init(void);
+
+void remoti_sysfs_exit(void);
+
+#endif /* !__REMOTI_PRIV_H */
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./core-sysfs.c linux-6.4-fbx/drivers/misc/remoti/core-sysfs.c
--- linux-6.4-fbx/drivers/misc/remoti./core-sysfs.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/core-sysfs.c	2023-11-29 17:07:10.431656439 +0100
@@ -0,0 +1,114 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/stat.h>
+#include "core-priv.h"
+
+#define to_remoti_dev(cldev) container_of(cldev, struct remoti_device, dev)
+
+static ssize_t show_dev_id(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct remoti_device *rd = to_remoti_dev(dev);
+	return sprintf(buf, "%d\n", rd->pdata.id);
+}
+
+static ssize_t show_dev_state(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct remoti_device *rd = to_remoti_dev(dev);
+	return sprintf(buf, "%i\n",
+		       dev_is_operational(rd) ? 1 : 0);
+}
+
+static DEVICE_ATTR(id, S_IRUGO, show_dev_id, NULL);
+static DEVICE_ATTR(state, S_IRUGO, show_dev_state, NULL);
+
+static struct device_attribute *remoti_attrs[] = {
+	&dev_attr_id,
+	&dev_attr_state,
+	/* FIXME: export stats too */
+};
+
+static int remoti_uevent(const struct device *dev, struct kobj_uevent_env *env)
+{
+	struct remoti_device *rd;
+
+	if (!dev)
+		return -ENODEV;
+
+	rd = to_remoti_dev(dev);
+	if (!rd)
+		return -ENODEV;
+
+	if (add_uevent_var(env, "STATE=%u",
+			   dev_is_operational(rd) ? 1 : 0))
+		return -ENOMEM;
+
+	if (add_uevent_var(env, "ID=%u", rd->pdata.id))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void remoti_release(struct device *dev)
+{
+	struct remoti_device *rd = to_remoti_dev(dev);
+	__remoti_free_device(rd);
+}
+
+static struct class remoti_class = {
+	.name		= "remoti",
+	.dev_release	= remoti_release,
+	.dev_uevent	= remoti_uevent,
+};
+
+void remoti_dev_change_sysfs(struct remoti_device *rd)
+{
+	struct device *dev = &rd->dev;
+
+	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, NULL);
+}
+
+int remoti_register_dev_sysfs(struct remoti_device *rd)
+{
+	struct device *dev = &rd->dev;
+	int i, j, ret;
+
+	dev->class = &remoti_class;
+	dev_set_name(dev, "remoti%u", rd->pdata.id);
+	ret = device_register(dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(remoti_attrs); i++) {
+		ret = device_create_file(dev, remoti_attrs[i]);
+		if (ret)
+			goto err;
+	}
+	return 0;
+
+err:
+	for (j = 0; j < i; j++)
+		device_remove_file(dev, remoti_attrs[j]);
+	device_del(dev);
+	return ret;
+}
+
+void remoti_unregister_dev_sysfs(struct remoti_device *rd)
+{
+	struct device *dev = &rd->dev;
+
+	device_unregister(dev);
+}
+
+int __init remoti_sysfs_init(void)
+{
+	return class_register(&remoti_class);
+}
+
+void remoti_sysfs_exit(void)
+{
+	class_unregister(&remoti_class);
+}
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./core.c linux-6.4-fbx/drivers/misc/remoti/core.c
--- linux-6.4-fbx/drivers/misc/remoti./core.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/core.c	2023-11-29 17:07:10.431656439 +0100
@@ -0,0 +1,1930 @@
+/*
+ * Copyright (C) 2010 Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * RemoTI core module driver.
+ *
+ * This file is subject to the GPLv2 licensing terms.
+ */
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/gpio.h>
+#include <linux/tty.h>
+#include <linux/of.h>
+
+#include "core-priv.h"
+
+#define REMOTI_FW_NAME		"rnp_cc2530.bin"
+#define REMOTI_FW_MAX_SIZE	((256 - 2) * 1024)
+#define REMOTI_MSG_TIMEOUT	(5 * HZ)
+
+/* list of remoti devices */
+static DEFINE_SPINLOCK(remoti_devs_list_lock);
+static struct list_head remoti_devs_list;
+
+static BLOCKING_NOTIFIER_HEAD(udev_notifier);
+
+/*
+ * toggle device hw reset gpio
+ */
+static void dev_hw_reset_set(struct remoti_device *rd, int value)
+{
+	int ret;
+
+	ret = gpio_request(rd->pdata.reset_gpio, rd->pdev->name);
+	if (ret) {
+		dev_err(&rd->pdev->dev, "failed to request reset gpio: %d\n",
+			ret);
+		return;
+	}
+
+	gpio_direction_output(rd->pdata.reset_gpio, value);
+	gpio_set_value(rd->pdata.reset_gpio, value);
+	gpio_free(rd->pdata.reset_gpio);
+}
+
+static void dev_hw_reset_hold(struct remoti_device *rd)
+{
+	dev_hw_reset_set(rd, 1);
+}
+
+static void dev_hw_reset_release(struct remoti_device *rd)
+{
+	dev_hw_reset_set(rd, 0);
+}
+
+static void dev_hw_reset_cycle(struct remoti_device *rd)
+{
+	dev_hw_reset_hold(rd);
+	msleep(1);
+	dev_hw_reset_release(rd);
+	msleep(1);
+}
+
+/*
+ *
+ */
+static void release_tx_msg(struct remoti_tx_msg *tx_msg)
+{
+	if (!atomic_dec_and_test(&tx_msg->users))
+		return;
+	kfree(tx_msg);
+}
+
+/*
+ *
+ */
+static void handle_rx_msg(struct remoti_device *rd,
+			  struct remoti_rx_msg *rx_msg)
+{
+	struct remoti_tx_msg *tx_msg;
+	const struct rti_msg *msg;
+
+	rd->stats.rx_packets++;
+	msg = &rx_msg->msg;
+
+	/* sanity check */
+	if (msg->subsys >= NPI_SYS_MAX) {
+		dev_err(&rd->pdev->dev, "received message with "
+			"unknown subsys: %u\n", msg->subsys);
+		rd->stats.rx_subsys_errors++;
+		goto release_msg;
+	}
+
+	if (msg->type >= NPI_TYPE_MAX) {
+		dev_err(&rd->pdev->dev, "received message with "
+			"unknown type: %u\n", msg->type);
+		rd->stats.rx_type_errors++;
+		goto release_msg;
+	}
+
+	switch (msg->subsys) {
+	case NPI_SYS_RCAF:
+		rd->stats.rx_rcaf_packets++;
+		break;
+	case NPI_SYS_BOOT:
+		rd->stats.rx_boot_packets++;
+		break;
+	case NPI_SYS_UTIL:
+		rd->stats.rx_util_packets++;
+		break;
+	default:
+		rd->stats.rx_other_packets++;
+		break;
+	}
+
+	switch (msg->type) {
+	case NPI_AREQ:
+	{
+		struct remoti_cmd_callback *cb;
+		bool found;
+
+		/* async message, deliver to all listeners */
+		found = false;
+		spin_lock(&rd->callback_list_lock);
+		list_for_each_entry(cb, &rd->callback_list, next) {
+			if (msg->subsys == cb->subsys &&
+			    msg->cmd == cb->cmd) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			spin_unlock(&rd->callback_list_lock);
+			if (printk_ratelimit())
+				dev_warn(&rd->pdev->dev,
+					 "no callback for async "
+					 "message type:%u subsys:%u "
+					 "cmd:0x%02x data_len:%u\n",
+					 msg->type, msg->subsys,
+					 msg->cmd, msg->data_len);
+			rd->stats.rx_no_callback++;
+			break;
+		}
+
+		cb->cb(cb->cb_priv, msg);
+		spin_unlock(&rd->callback_list_lock);
+		break;
+	}
+
+	case NPI_SREQ:
+		dev_warn(&rd->pdev->dev, "received unexpected sync "
+			 "request type:%u subsys:%u cmd:0x%02x "
+			 "data_len:%u\n",
+			 msg->type, msg->subsys,
+			 msg->cmd, msg->data_len);
+		break;
+
+	case NPI_POLL:
+	case NPI_SRSP:
+		/*
+		 * check if it is a synchronous reply to the currently
+		 * pending tx message, note that we are serialized wrt
+		 * tx_work since we run in the same workqueue
+		 *
+		 * note that we handle NPI_POLL like a response
+		 * because the serial bootloader does not use any
+		 * type, but still behave like synchronous
+		 */
+		tx_msg = NULL;
+		spin_lock(&rd->tx_msg_list_lock);
+		if (!list_empty(&rd->tx_msg_list)) {
+			tx_msg = list_first_entry(&rd->tx_msg_list,
+						  struct remoti_tx_msg, next);
+			if (tx_msg->tx_state != RTI_TX_MSG_S_WAIT_RX_ACK)
+				tx_msg = NULL;
+		}
+		spin_unlock(&rd->tx_msg_list_lock);
+
+		if (!tx_msg) {
+			dev_warn(&rd->pdev->dev, "received unexpected sync "
+				 "response type:%u subsys:%u cmd:0x%02x\n",
+				 msg->type, msg->subsys, msg->cmd);
+			goto release_msg;
+		}
+
+		if (tx_msg &&
+		    (tx_msg->msg->subsys != msg->subsys ||
+		     tx_msg->msg->reply_cmd != msg->cmd)) {
+			/* can't find any corresponding synchronous
+			 * request */
+			dev_warn(&rd->pdev->dev, "received unexpected sync "
+				 "response type:%u subsys:%u cmd:0x%02x - "
+				 "pending subsys:%u cmd:0x%02x\n",
+				 msg->type, msg->subsys, msg->cmd,
+				 tx_msg->msg->subsys,
+				 tx_msg->msg->reply_cmd);
+			goto release_msg;
+		}
+
+		/* copy message data inside tx message and complete
+		 * its transmission */
+		memcpy(tx_msg->msg->reply, msg->data, msg->data_len);
+		tx_msg->msg->reply_len = msg->data_len;
+
+		spin_lock(&rd->tx_msg_list_lock);
+		list_del(&tx_msg->next);
+		complete(&tx_msg->complete);
+		release_tx_msg(tx_msg);
+		spin_unlock(&rd->tx_msg_list_lock);
+
+		/* kick tx work now that message is complete */
+		queue_work(rd->io_workqueue, &rd->tx_work);
+		break;
+	}
+
+release_msg:
+	kfree(rx_msg);
+}
+
+/*
+ * workqueue used to handle rx commands
+ */
+static void remoti_rx_work(struct work_struct *work)
+{
+	struct remoti_device *rd =
+		container_of(work, struct remoti_device, rx_work);
+
+	/* stop_tty() locking seems unreliable, make sure rx seems
+	 * stopped when we set stopping state */
+	if (dev_is_stopping(rd))
+		return;
+
+	/* dequeue all pending messages */
+	do {
+		struct remoti_rx_msg *rx_msg;
+		unsigned long flags;
+
+		/* tty recv can run from irq context */
+		rx_msg = NULL;
+		spin_lock_irqsave(&rd->rx_msg_list_lock, flags);
+		if (!list_empty(&rd->rx_msg_list)) {
+			rx_msg = list_first_entry(&rd->rx_msg_list,
+						  struct remoti_rx_msg, next);
+			list_del(&rx_msg->next);
+		}
+		spin_unlock_irqrestore(&rd->rx_msg_list_lock, flags);
+
+		if (!rx_msg)
+			break;
+
+		handle_rx_msg(rd, rx_msg);
+
+	} while (1);
+}
+
+/*
+ * generate fcs for uart rti frames
+ */
+static u8 remoti_calc_fcs(const u8 *data, int len, u8 fcs)
+{
+	while (len--)
+		fcs ^= *data++;
+
+	return fcs;
+}
+
+/*
+ * handle valid char received on UART
+ */
+static void remoti_tty_recv_char(struct remoti_device *rd, const u8 c)
+{
+	switch (rd->tty_fsm_state) {
+	case RTI_TTY_FSM_SOF:
+		switch (c) {
+		case RTI_UART_CHR_WAKEUP:
+			complete(&rd->wakeup_complete);
+			break;
+		case RTI_UART_CHR_SOF:
+			rd->tty_fsm_state = RTI_TTY_FSM_LEN;
+			break;
+		default:
+			rd->stats.rx_bad_sof++;
+			break;
+		}
+		break;
+
+	case RTI_TTY_FSM_LEN:
+		if (c == RTI_UART_CHR_SOF)
+			break;
+
+		/* Guard against malformed frames */
+		if (c > NPI_MAX_DATA_LEN) {
+			dev_err(&rd->pdev->dev, "ignoring too big "
+				"frame: len: %u\n", c);
+			rd->stats.rx_len_errors++;
+			rd->tty_fsm_state = RTI_TTY_FSM_SOF;
+			break;
+		}
+
+		rd->rx_buf[0] = c;
+		rd->rx_buf_len = 1;
+		rd->tty_fsm_state = RTI_TTY_FSM_DATA;
+		break;
+
+	case RTI_TTY_FSM_DATA:
+	{
+		size_t total_len;
+
+		rd->rx_buf[rd->rx_buf_len++] = c;
+
+		/* total bytes to read is hdr_size (len + subsys + cmd) +
+		 * data_len */
+		total_len = 3 + rd->rx_buf[0];
+		if (rd->rx_buf_len == total_len)
+			rd->tty_fsm_state = RTI_TTY_FSM_FCS;
+		break;
+	}
+
+	case RTI_TTY_FSM_FCS:
+	{
+		struct remoti_rx_msg *rx_msg;
+		struct rti_msg *msg;
+		u8 fcs;
+
+		rd->tty_fsm_state = RTI_TTY_FSM_SOF;
+
+		fcs = remoti_calc_fcs(rd->rx_buf, rd->rx_buf_len, 0);
+		if (fcs != c) {
+			rd->stats.rx_fcs_errors++;
+			dev_err(&rd->pdev->dev, "got fcs error "
+				"on rx message\n");
+			break;
+		}
+
+
+		rx_msg = kmalloc(sizeof (*rx_msg), GFP_ATOMIC);
+		if (!rx_msg) {
+			rd->stats.rx_full_errors++;
+			break;
+		}
+
+		msg = &rx_msg->msg;
+		msg->type = (rd->rx_buf[1] >> NPI_TYPE_SHIFT) & NPI_TYPE_MASK;
+		msg->subsys = rd->rx_buf[1] & NPI_SYS_MASK;
+		msg->cmd = rd->rx_buf[2];
+		msg->data_len = rd->rx_buf[0];
+		memcpy(msg->data, rd->rx_buf + 3, msg->data_len);
+
+		/* add message to rx queue & schedule work */
+		spin_lock(&rd->rx_msg_list_lock);
+		list_add_tail(&rx_msg->next, &rd->rx_msg_list);
+		spin_unlock(&rd->rx_msg_list_lock);
+		queue_work(rd->io_workqueue, &rd->rx_work);
+		break;
+	}
+	}
+}
+
+/*
+ * kernel callback when there are data to read on uart
+ */
+static void remoti_tty_recv_buf(struct tty_struct *tty, const u8 *data,
+				const char *flags, int count)
+{
+	struct remoti_device *rd;
+	int i;
+
+	/* if line is not yet attached to any device, just ignore */
+	rd = (struct remoti_device *)tty->disc_data;
+	if (!rd)
+		return;
+
+	/* Walk the received buffer in inverse order */
+	for (i = 0; i < count; i++) {
+		if (!flags) {
+			remoti_tty_recv_char(rd, data[i]);
+			continue;
+		}
+
+		switch (flags[i]) {
+		case TTY_OVERRUN:
+		case TTY_BREAK:
+		case TTY_PARITY:
+		case TTY_FRAME:
+			rd->tty_fsm_state = RTI_TTY_FSM_SOF;
+			rd->stats.rx_tty_errors++;
+			break;
+
+		case TTY_NORMAL:
+			remoti_tty_recv_char(rd, data[i]);
+			break;
+
+		default:
+			pr_err("%s: unknown tty flag %d\n", tty->name, flags[i]);
+			break;
+		}
+	}
+	rd->stats.rx_bytes += count;
+}
+
+/*
+ * workqueue used to dequeue and push command into tx buf and wait for
+ * completion
+ */
+static void remoti_tx_work(struct work_struct *work)
+{
+	struct remoti_device *rd =
+		container_of(work, struct remoti_device, tx_work);
+	struct remoti_tx_msg *tx_msg;
+	u8 buf[RTI_MAX_FRAME_LEN + 1]; /* +1 is for the wakeup char */
+	unsigned int buf_len;
+	int room, sent;
+
+	/* don't handle with tx message list when we try to stop
+	 * device, we will force complete them from another place */
+	if (dev_is_stopping(rd))
+		return;
+
+	tx_msg = NULL;
+	spin_lock(&rd->tx_msg_list_lock);
+	if (!list_empty(&rd->tx_msg_list))
+		tx_msg = list_first_entry(&rd->tx_msg_list,
+					  struct remoti_tx_msg, next);
+	spin_unlock(&rd->tx_msg_list_lock);
+
+
+	if (!tx_msg) {
+		/* no message to send, send wakeup if requested */
+		if (rd->tx_need_send_wakeup) {
+			buf[0] = RTI_UART_CHR_WAKEUP;
+			sent = rd->tty->ops->write(rd->tty, buf, 1);
+			if (sent)
+				rd->tx_need_send_wakeup = false;
+		}
+		return;
+	}
+
+	if (tx_msg->tx_state == RTI_TX_MSG_S_WAIT_RX_ACK) {
+		/* we are waiting for an rx ack for this message,
+		 * don't send anything */
+		return;
+	}
+
+	room = tty_write_room(rd->tty);
+	if (room == 0) {
+		/* no room, tty resume callback will reschedule tx
+		 * later */
+		return;
+	}
+
+	buf_len = 0;
+	switch (tx_msg->tx_state) {
+	case RTI_TX_MSG_S_WAITING:
+		if (room && rd->tx_need_send_wakeup) {
+			buf[buf_len++] = RTI_UART_CHR_WAKEUP;
+			room--;
+			rd->tx_need_send_wakeup = false;
+		}
+
+		if (!room)
+			break;
+
+		buf[buf_len++] = RTI_UART_CHR_SOF;
+		room--;
+		tx_msg->tx_state = RTI_TX_MSG_S_SOF_SENT;
+		fallthrough;
+
+	case RTI_TX_MSG_S_SOF_SENT:
+		/* send all header at once */
+		if (room < 3)
+			break;
+
+		buf[buf_len] = tx_msg->msg->data_len;
+		buf[buf_len + 1] = (tx_msg->msg->type << NPI_TYPE_SHIFT) |
+			(tx_msg->msg->subsys & NPI_SYS_MASK);
+		buf[buf_len + 2] = tx_msg->msg->cmd;
+		tx_msg->fcs = remoti_calc_fcs(buf + buf_len, 3, tx_msg->fcs);
+
+		buf_len += 3;
+		room -= 3;
+		tx_msg->tx_state = RTI_TX_MSG_S_HDR_SENT;
+		fallthrough;
+
+	case RTI_TX_MSG_S_HDR_SENT:
+	{
+		size_t to_send;
+
+		/* send as many data as possible */
+		to_send = tx_msg->msg->data_len - tx_msg->tx_data_sent;
+		if (to_send > room)
+			to_send = room;
+
+		memcpy(buf + buf_len,
+		       tx_msg->msg->data + tx_msg->tx_data_sent,
+		       to_send);
+
+		tx_msg->fcs = remoti_calc_fcs(buf + buf_len, to_send,
+					      tx_msg->fcs);
+		buf_len += to_send;
+		tx_msg->tx_data_sent += to_send;
+		room -= to_send;
+
+		if (tx_msg->tx_data_sent != tx_msg->msg->data_len)
+			break;
+
+		tx_msg->tx_state = RTI_TX_MSG_S_DATA_SENT;
+	}
+	fallthrough;
+
+	case RTI_TX_MSG_S_DATA_SENT:
+		if (!room)
+			break;
+
+		buf[buf_len++] = tx_msg->fcs;
+		tx_msg->tx_state = RTI_TX_MSG_S_SENT;
+		break;
+
+	default:
+		break;
+	}
+
+	if (!buf_len)
+		return;
+
+#if 0
+	printk("remoti_tx_work: sending buf_len %u\n", buf_len);
+	{
+		size_t i;
+
+		for (i = 0; i < buf_len; i++) {
+			printk("%02x ", buf[i]);
+		}
+		printk("\n");
+	}
+#endif
+
+	sent = rd->tty->ops->write(rd->tty, buf, buf_len);
+	if (unlikely(sent < 0)) {
+		pr_err("tty->ops->write failed with %d\n", sent);
+		return;
+	}
+
+	if (unlikely(sent < buf_len)) {
+		/* since we check available room before calling write,
+		 * this only happen when tty is closing */
+		spin_lock(&rd->tx_msg_list_lock);
+		tx_msg->canceled = true;
+		list_del(&tx_msg->next);
+		complete(&tx_msg->complete);
+		release_tx_msg(tx_msg);
+		spin_unlock(&rd->tx_msg_list_lock);
+		return;
+	}
+
+	rd->stats.tx_bytes += sent;
+
+	if (tx_msg->tx_state == RTI_TX_MSG_S_SENT) {
+
+		/* actually wait for data to be written it hw fifo,
+		 * not just in tty buffer, before we complete message
+		 * sending */
+		rd->tty->ops->wait_until_sent(rd->tty, 0);
+
+		/* send complete, update counters */
+		rd->stats.tx_packets++;
+		switch (tx_msg->msg->subsys) {
+		case NPI_SYS_RCAF:
+			rd->stats.tx_rcaf_packets++;
+			break;
+		case NPI_SYS_UTIL:
+			rd->stats.tx_util_packets++;
+			break;
+		case NPI_SYS_BOOT:
+			rd->stats.tx_boot_packets++;
+			break;
+		default:
+			rd->stats.tx_other_packets++;
+			break;
+		}
+
+		if (tx_msg->need_rx_ack) {
+			/* rx work will complete the message, note
+			 * that we cannot race with rx work since we
+			 * run in the same workqueue */
+			tx_msg->tx_state = RTI_TX_MSG_S_WAIT_RX_ACK;
+			return;
+		}
+
+		spin_lock(&rd->tx_msg_list_lock);
+		list_del(&tx_msg->next);
+		complete(&tx_msg->complete);
+		release_tx_msg(tx_msg);
+		spin_unlock(&rd->tx_msg_list_lock);
+	}
+}
+
+/*
+ * kernel callback when there is room in send buffer
+ */
+static void remoti_tty_write_resume(struct tty_struct *tty)
+{
+	struct remoti_device *rd = (struct remoti_device *)tty->disc_data;
+
+	/* can be called from irq context, defer to userspace to be
+	 * safe */
+	queue_work(rd->io_workqueue, &rd->tx_work);
+}
+
+/*
+ *
+ */
+static int __remoti_send_msg(struct remoti_device *rd,
+			     struct rti_msg *msg, bool async)
+{
+	struct remoti_tx_msg *tx_msg;
+	unsigned int timeout;
+	int ret;
+
+	if (msg->data_len > NPI_MAX_DATA_LEN)
+		return -EFBIG;
+
+	/* alloc & queue message */
+	tx_msg = kzalloc(sizeof (*tx_msg), GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	if (!msg->custom_reply_cmd)
+		msg->reply_cmd = msg->cmd;
+	msg->reply_len = 0;
+
+	tx_msg->msg = msg;
+	tx_msg->need_rx_ack = !async;
+	atomic_set(&tx_msg->users, 1);
+	init_completion(&tx_msg->complete);
+
+	spin_lock(&rd->tx_msg_list_lock);
+	atomic_inc(&tx_msg->users);
+	list_add_tail(&tx_msg->next, &rd->tx_msg_list);
+	spin_unlock(&rd->tx_msg_list_lock);
+
+	/* kick tx queue */
+	queue_work(rd->io_workqueue, &rd->tx_work);
+
+	/* wait for message to be sent */
+	ret = 0;
+	timeout = wait_for_completion_timeout(&tx_msg->complete,
+					      REMOTI_MSG_TIMEOUT);
+	if (!timeout) {
+		dev_err(&rd->pdev->dev, "timeout sending message "
+			"type:%u subsys:%u cmd:0x%02x data_len:%u\n",
+			msg->type, msg->subsys, msg->cmd, msg->data_len);
+		ret = -ETIMEDOUT;
+	}
+
+	if (tx_msg->canceled)
+		ret = -EIO;
+
+	release_tx_msg(tx_msg);
+	return ret;
+}
+
+static int remoti_send_sync_msg(struct remoti_device *rd,
+				struct rti_msg *msg)
+{
+	return __remoti_send_msg(rd, msg, false);
+}
+
+static int remoti_send_async_msg(struct remoti_device *rd,
+				 struct rti_msg *msg)
+{
+	return __remoti_send_msg(rd, msg, true);
+}
+
+/*
+ * high level api to access device
+ */
+struct rti_udev *rti_get_udevice(unsigned int id)
+{
+	struct remoti_device *rd;
+	bool found;
+
+	found = false;
+	spin_lock(&remoti_devs_list_lock);
+	list_for_each_entry(rd, &remoti_devs_list, next) {
+		if (rd->pdata.id == id) {
+			found = true;
+			break;
+		}
+	}
+	spin_unlock(&remoti_devs_list_lock);
+
+	if (!found)
+		return NULL;
+
+	spin_lock(&rd->state_lock);
+	if (rd->state != RTI_DEV_S_OPERATIONAL) {
+		spin_unlock(&rd->state_lock);
+		return NULL;
+	}
+
+	atomic_inc(&rd->user_count);
+	spin_unlock(&rd->state_lock);
+	return (struct rti_udev *)rd;
+}
+
+EXPORT_SYMBOL(rti_get_udevice);
+
+/*
+ *
+ */
+void rti_release_udevice(struct rti_udev *udev)
+{
+	struct remoti_device *rd = (struct remoti_device *)udev;
+	atomic_dec(&rd->user_count);
+}
+
+EXPORT_SYMBOL(rti_release_udevice);
+
+/*
+ *
+ */
+static int __rti_send_msg(struct rti_udev *udev, struct rti_msg *msg,
+			  bool async)
+{
+	struct remoti_device *rd = (struct remoti_device *)udev;
+	int ret;
+
+	if (!dev_is_operational(rd))
+		return -EIO;
+
+	ret = __remoti_send_msg(rd, msg, async);
+	if (ret == -ETIMEDOUT) {
+		/* catch any timeout, assume device is dead and mark
+		 * it as such */
+		rd->timeout = true;
+		queue_work(rd->fsm_workqueue, &rd->hw_fsm_work);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/*
+ *
+ */
+int rti_send_sync_msg(struct rti_udev *udev, struct rti_msg *msg)
+{
+	return __rti_send_msg(udev, msg, false);
+}
+
+EXPORT_SYMBOL(rti_send_sync_msg);
+
+/*
+ *
+ */
+int rti_send_async_msg(struct rti_udev *udev, struct rti_msg *msg)
+{
+	return __rti_send_msg(udev, msg, true);
+}
+
+EXPORT_SYMBOL(rti_send_async_msg);
+
+/*
+ *
+ */
+static int remoti_register_cmd_callback(struct remoti_device *rd,
+					u8 subsys, u8 cmd,
+					void (*cb)(void *cb_priv,
+						   const struct rti_msg *msg),
+					void *cb_priv)
+{
+	struct remoti_cmd_callback *cb_elem, *new_cb_elem;
+	bool found;
+
+	new_cb_elem = kmalloc(sizeof (*cb_elem), GFP_KERNEL);
+	if (!new_cb_elem)
+		return -ENOMEM;
+	new_cb_elem->subsys = subsys;
+	new_cb_elem->cmd = cmd;
+	new_cb_elem->cb = cb;
+	new_cb_elem->cb_priv = cb_priv;
+
+	found = false;
+	spin_lock(&rd->callback_list_lock);
+	list_for_each_entry(cb_elem, &rd->callback_list, next) {
+		if (new_cb_elem->subsys == cb_elem->subsys &&
+		    new_cb_elem->cmd == cb_elem->cmd) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found) {
+		spin_unlock(&rd->callback_list_lock);
+		kfree(new_cb_elem);
+		dev_warn(&rd->pdev->dev, "refuse to register a second "
+			 "callback for subsys:%u cmd:0x%02x\n", subsys, cmd);
+		return -EEXIST;
+	}
+
+	list_add_tail(&new_cb_elem->next, &rd->callback_list);
+	spin_unlock(&rd->callback_list_lock);
+
+	return 0;
+}
+
+static void remoti_unregister_cmd_callback(struct remoti_device *rd,
+					   u8 subsys, u8 cmd)
+{
+	struct remoti_cmd_callback *cb_elem;
+	bool found;
+
+	found = false;
+	spin_lock(&rd->callback_list_lock);
+	list_for_each_entry(cb_elem, &rd->callback_list, next) {
+		if (subsys == cb_elem->subsys &&
+		    cmd == cb_elem->cmd) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found)
+		list_del(&cb_elem->next);
+	else
+		cb_elem = NULL;
+
+	spin_unlock(&rd->callback_list_lock);
+
+	kfree(cb_elem);
+}
+
+/*
+ *
+ */
+int rti_register_cmd_callback(struct rti_udev *udev,
+			      u8 subsys, u8 cmd,
+			      void (*cb)(void *cb_priv,
+					 const struct rti_msg *msg),
+			      void *cb_priv)
+{
+	struct remoti_device *rd = (struct remoti_device *)udev;
+
+	if (!dev_is_operational(rd))
+		return -EIO;
+
+	return remoti_register_cmd_callback(rd, subsys, cmd, cb, cb_priv);
+}
+
+EXPORT_SYMBOL(rti_register_cmd_callback);
+
+void rti_unregister_cmd_callback(struct rti_udev *udev, u8 subsys, u8 cmd)
+{
+	return remoti_unregister_cmd_callback((struct remoti_device *)udev,
+					      subsys, cmd);
+}
+
+EXPORT_SYMBOL(rti_unregister_cmd_callback);
+
+int rti_register_cmds_callback(struct rti_udev *udev,
+			       const struct rti_kcallback *cbs,
+			       size_t cb_count,
+			       void *cb_priv)
+{
+	size_t i, j;
+	int ret;
+
+	for (i = 0; i < cb_count; i++) {
+		ret = rti_register_cmd_callback(udev,
+						cbs[i].subsys,
+						cbs[i].cmd,
+						cbs[i].cb,
+						cb_priv);
+		if (ret)
+			goto fail;
+	}
+
+	return 0;
+
+fail:
+	for (j = 0; j < i; j++)
+		rti_unregister_cmd_callback(udev, cbs[j].subsys, cbs[j].cmd);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(rti_register_cmds_callback);
+
+void rti_unregister_cmds_callback(struct rti_udev *udev,
+				  const struct rti_kcallback *cbs,
+				  size_t cb_count)
+{
+	size_t i;
+
+	for (i = 0; i < cb_count; i++)
+		rti_unregister_cmd_callback(udev, cbs[i].subsys, cbs[i].cmd);
+}
+
+EXPORT_SYMBOL(rti_unregister_cmds_callback);
+
+/*
+ *
+ */
+static void remoti_call_udev_notifier(struct remoti_device *rd)
+{
+	enum rti_udev_state st;
+
+	switch (rd->state) {
+	case RTI_DEV_S_OPERATIONAL:
+		st = RTI_UDEV_UP;
+		break;
+
+	case RTI_DEV_S_STOPPING:
+		st = RTI_UDEV_GOING_DOWN;
+		break;
+
+	default:
+		return;
+	}
+	blocking_notifier_call_chain(&udev_notifier, rd->pdata.id, &st);
+}
+
+/*
+ *
+ */
+void rti_register_udevice_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_register(&udev_notifier, nb);
+}
+
+EXPORT_SYMBOL(rti_register_udevice_notifier);
+
+/*
+ *
+ */
+void rti_unregister_udevice_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&udev_notifier, nb);
+}
+
+EXPORT_SYMBOL(rti_unregister_udevice_notifier);
+
+/*
+ *
+ */
+static int send_read_fw_version(struct remoti_device *rd,
+				uint32_t *version)
+{
+	struct rti_msg msg;
+	struct rti_rcaf_read_item_req *req;
+	struct rti_rcaf_read_item_resp *resp;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_RCAF;
+	msg.cmd = RTI_READ_ITEM;
+	msg.data_len = sizeof (*req);
+
+	req = (struct rti_rcaf_read_item_req *)msg.data;
+	req->item = RTI_ITEM_FW_VER;
+	req->item_len = sizeof (*version);
+
+	ret = remoti_send_sync_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	resp = (struct rti_rcaf_read_item_resp *)msg.reply;
+
+	if (msg.reply_len != sizeof (*resp) + sizeof (*version) ||
+	    resp->status != RTI_SUCCESS) {
+		dev_err(&rd->pdev->dev, "invalid read item "
+			"version response\n");
+		return 1;
+	}
+
+	memcpy(version, msg.reply + sizeof (*resp), sizeof (*version));
+	*version = __le32_to_cpu(*version);
+	return 0;
+}
+
+/*
+ *
+ */
+static int send_fw_erase(struct remoti_device *rd)
+{
+	struct rti_msg msg;
+	int ret;
+
+	/* send a boot subsystem message to the operational firmware,
+	 * it will erase itself and trigger watchdog to reboot */
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_AREQ;
+	msg.subsys = NPI_SYS_BOOT;
+	msg.cmd = RTI_SB_RELOAD;
+
+	ret = remoti_send_async_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int serial_boot_send_firmware(struct remoti_device *rd,
+				     const struct firmware *fw)
+{
+	struct rti_msg msg;
+	struct rti_sb_write_req *wr_req;
+	int frame, num_frames;
+	int ret;
+	u8 *p;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_POLL;
+	msg.subsys = NPI_SYS_BOOT;
+	msg.cmd = RTI_SB_WRITE_REQ;
+	msg.custom_reply_cmd = true;
+	msg.reply_cmd = (1 << 7) | msg.cmd;
+	msg.data_len = sizeof (*wr_req);
+	wr_req = (struct rti_sb_write_req *)msg.data;
+
+	/* Round-up to the right number of frames */
+	num_frames = DIV_ROUND_UP(fw->size, SB_DATA_SIZE);
+
+	for (frame = 0; frame < num_frames; frame++) {
+		unsigned int flash_offset;
+
+		p = (u8 *)(fw->data + (SB_DATA_SIZE * frame));
+
+		flash_offset = frame * (SB_DATA_SIZE / RTI_SB_FLASH_WORD);
+		wr_req->addr = cpu_to_le16(flash_offset);
+		memcpy(wr_req->data, p, SB_DATA_SIZE);
+
+		ret = remoti_send_sync_msg(rd, &msg);
+		if (ret)
+			return ret;
+
+		if (msg.reply_len != 1 || msg.reply[0] != SB_SUCCESS) {
+			dev_err(&rd->pdev->dev, "flash write failed at "
+				"offset 0x%04x\n", flash_offset);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int serial_boot_enable_image(struct remoti_device *rd)
+{
+	struct rti_msg msg;
+	int ret;
+
+        /* Try to enable this image */
+	memset(&msg, 0, sizeof(msg));
+	/* the serial boot loader does not use type */
+	msg.subsys = NPI_SYS_BOOT;
+        msg.cmd = RTI_SB_ENABLE_REQ;
+	msg.custom_reply_cmd = true;
+	msg.reply_cmd = (1 << 7) | msg.cmd;
+
+	ret = remoti_send_sync_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1 || msg.reply[0] != SB_SUCCESS) {
+		dev_err(&rd->pdev->dev, "invalid serial enable image reply\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int serial_boot_do_handshake(struct remoti_device *rd)
+{
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	/* the serial boot loader does not use type */
+	msg.subsys = NPI_SYS_BOOT;
+	msg.cmd = RTI_SB_HSK_REQ;
+	msg.custom_reply_cmd = true;
+	msg.reply_cmd = (1 << 7) | msg.cmd;
+
+	ret = remoti_send_sync_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1 || msg.reply[0] != SB_SUCCESS) {
+		dev_err(&rd->pdev->dev, "invalid serial handshake reply\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * check firmware image and extract its version
+ */
+static int fw_extract_version(const struct firmware *fw, u32 *version)
+{
+	struct remoti_fw_header *hdr;
+
+        if (fw->size < sizeof (*hdr) + RTI_FW_HDR_OFFSET) {
+		pr_err("firmware size is too small\n");
+                return 1;
+	}
+
+        if (fw->size >= REMOTI_FW_MAX_SIZE) {
+		pr_err("firmware size is too big\n");
+                return 1;
+	}
+
+        hdr = (struct remoti_fw_header *)(fw->data + RTI_FW_HDR_OFFSET);
+        if (hdr->enable_op != (uint32_t)~0) {
+		pr_err("firmware enable_op is invalid\n");
+		return 1;
+	}
+
+        *version = le32_to_cpu(hdr->version);
+	return 0;
+}
+
+/*
+ * callback when we receive assertion failed message
+ */
+static void handle_assert_ind(void *cb_priv, const struct rti_msg *msg)
+{
+	struct remoti_device *rd = (struct remoti_device *)cb_priv;
+	if (printk_ratelimit())
+		dev_err(&rd->pdev->dev, "got assertion FAILED message\n");
+}
+
+/*
+ * callback when we receive printk message
+ */
+static void handle_printk_ind(void *cb_priv, const struct rti_msg *msg)
+{
+	struct remoti_device *rd = (struct remoti_device *)cb_priv;
+	char buf[NPI_MAX_DATA_LEN + 1];
+	size_t i;
+
+	/* sanitize string */
+	memcpy(buf, msg->data, msg->data_len);
+	buf[NPI_MAX_DATA_LEN] = 0;
+
+	/* replace non printable char */
+        for (i = 0; i < sizeof (buf); i++) {
+		if (!buf[i])
+			break;
+		else if (buf[i] == '\r' || buf[i] == '\n')
+			buf[i] = ' ';
+                else if (buf[i] < ' ' || buf[i] > 127)
+                        buf[i] = '?';
+	}
+
+	dev_info(&rd->pdev->dev, "printk: %s\n", buf);
+}
+
+/*
+ * callback when we receive INIT_CNF message
+ */
+static void handle_init_cnf(void *cb_priv, const struct rti_msg *msg)
+{
+	struct remoti_device *rd = (struct remoti_device *)cb_priv;
+	complete(&rd->init_cnf_complete);
+}
+
+/*
+ *
+ */
+static const char *dev_states_str[] = {
+	[RTI_DEV_S_STOPPED]		= "stopped",
+	[RTI_DEV_S_BOOTING]		= "booting",
+	[RTI_DEV_S_BOOT_FAILED]		= "boot failed",
+	[RTI_DEV_S_OPERATIONAL]		= "operational",
+	[RTI_DEV_S_STOPPING]		= "stopping",
+	[RTI_DEV_S_DEAD]		= "dead",
+};
+
+static void __dev_set_state(struct remoti_device *rd,
+			    enum rti_dev_state state, bool silent)
+{
+	spin_lock(&rd->state_lock);
+	rd->state = state;
+	spin_unlock(&rd->state_lock);
+
+	if (!silent) {
+		dev_info(&rd->pdev->dev, "RNP state: %s\n",
+			 dev_states_str[state]);
+		remoti_call_udev_notifier(rd);
+		remoti_dev_change_sysfs(rd);
+	}
+}
+
+static void dev_set_state(struct remoti_device *rd, enum rti_dev_state state)
+{
+	return __dev_set_state(rd, state, false);
+}
+
+static void dev_set_state_silent(struct remoti_device *rd,
+				 enum rti_dev_state state)
+{
+	return __dev_set_state(rd, state, true);
+}
+
+/*
+ *
+ */
+static int boot_device(struct remoti_device *rd)
+{
+        const struct firmware *fw;
+	unsigned int timeout;
+	u32 user_fw_version, dev_fw_version, boot_flags;
+
+	/* get the firmware we are supposed to boot the RNP with from
+	 * userspace */
+	if (request_firmware(&fw, REMOTI_FW_NAME, &rd->pdev->dev)) {
+		dev_err(&rd->pdev->dev, "failed to request firmware\n");
+		return 1;
+	}
+
+	/* sanity check on this firmware & extract its version */
+	if (fw_extract_version(fw, &user_fw_version))
+		goto fail;
+
+	dev_info(&rd->pdev->dev, "required firmware version %08x\n",
+		 user_fw_version);
+
+	/* first try to boot it with its current firmare */
+	boot_flags = rd->boot_flags;
+	rd->boot_flags = 0;
+	reinit_completion(&rd->wakeup_complete);
+	reinit_completion(&rd->init_cnf_complete);
+	dev_hw_reset_cycle(rd);
+
+	/* get rnp out of sleep */
+	rd->tx_need_send_wakeup = true;
+	queue_work(rd->io_workqueue, &rd->tx_work);
+
+	/* wait a bit for wakeup char to be received, it won't be sent
+	 * if only a serial bootloader is present and we will wait for
+	 * nothing, but it's not the common case */
+	timeout = wait_for_completion_timeout(&rd->wakeup_complete,
+					      HZ * 2);
+	if (timeout != 0) {
+		dev_info(&rd->pdev->dev, "got RNP wakeup\n");
+
+		/* we got a wakeup; a firmware is running, check its
+		 * version */
+		if (send_read_fw_version(rd, &dev_fw_version)) {
+			dev_err(&rd->pdev->dev, "fail to read "
+				"current fw version\n");
+			goto fail;
+		}
+
+		/* wait for init confirm after we sent first
+		 * command */
+		timeout = wait_for_completion_timeout(&rd->init_cnf_complete,
+						      HZ * 10);
+		if (timeout == 0) {
+			dev_err(&rd->pdev->dev, "timeout waiting for RNP "
+				"init confirm\n");
+			goto fail;
+		}
+
+		/* compare with version we want to run */
+		if (!(boot_flags & RTI_BOOT_FLAGS_FORCE_UPDATE) &&
+		    dev_fw_version == user_fw_version) {
+			/* match, done */
+			rd->fw_version = dev_fw_version;
+			release_firmware(fw);
+			return 0;
+		}
+
+		if ((boot_flags & RTI_BOOT_FLAGS_FORCE_UPDATE))
+			dev_info(&rd->pdev->dev,
+				 "device fw version is %08x, "
+				 "but forcing erase as requested\n",
+				 dev_fw_version);
+		else
+			dev_info(&rd->pdev->dev,
+				 "device fw version is %08x, "
+				 "required %08x, erase\n",
+				 dev_fw_version, user_fw_version);
+
+		/* erase the current firmware and force a reboot */
+		if (send_fw_erase(rd))
+			return 1;
+
+		/* give it some time */
+		msleep(2000);
+
+	} else
+		dev_info(&rd->pdev->dev, "did not get RNP wakeup, "
+			 "assuming serial bootloader\n");
+
+	dev_info(&rd->pdev->dev, "doing serial bootloader handshake\n");
+
+	/* send handshake */
+	if (serial_boot_do_handshake(rd)) {
+		dev_err(&rd->pdev->dev, "failed to get "
+			"bootloader handshake\n");
+		goto fail;
+	}
+
+	dev_info(&rd->pdev->dev, "sending firmware...\n");
+
+	/* upgrade firmware */
+	if (serial_boot_send_firmware(rd, fw))
+		goto fail;
+
+	/* enable image */
+	dev_info(&rd->pdev->dev, "enabling image...\n");
+
+	reinit_completion(&rd->wakeup_complete);
+	reinit_completion(&rd->init_cnf_complete);
+	if (serial_boot_enable_image(rd))
+		goto fail;
+
+	/* wait for wakeup char again */
+	timeout = wait_for_completion_timeout(&rd->wakeup_complete,
+					      HZ * 2);
+	if (timeout == 0) {
+		dev_err(&rd->pdev->dev, "timeout waiting for RNP wakeup\n");
+		goto fail;
+	}
+
+	/* read version and compare  */
+	if (send_read_fw_version(rd, &dev_fw_version))
+		goto fail;
+
+	if (dev_fw_version != user_fw_version) {
+		dev_err(&rd->pdev->dev, "unexpected fw version (%08x) "
+			"should be %08x\n", dev_fw_version, user_fw_version);
+		goto fail;
+	}
+
+	timeout = wait_for_completion_timeout(&rd->init_cnf_complete,
+					      HZ * 10);
+	if (timeout == 0) {
+		dev_err(&rd->pdev->dev, "timeout waiting for RNP "
+			"init confirm\n");
+		goto fail;
+	}
+
+	/* done */
+	rd->fw_version = dev_fw_version;
+	release_firmware(fw);
+	return 0;
+
+fail:
+	dev_hw_reset_hold(rd);
+	release_firmware(fw);
+	return 1;
+}
+
+/*
+ *
+ */
+static void stop_device(struct remoti_device *rd)
+{
+	struct remoti_rx_msg *rx_msg, *rx_tmp;
+	struct remoti_cmd_callback *cb_elem, *cb_tmp;
+	unsigned int users;
+
+	/* make device as stopping, don't tell the world
+	 * yet */
+	dev_set_state_silent(rd, RTI_DEV_S_STOPPING);
+
+	/* stop tty rx */
+	stop_tty(rd->tty);
+	clear_bit(TTY_DO_WRITE_WAKEUP, &rd->tty->flags);
+	cancel_work_sync(&rd->rx_work);
+
+	/* discard all pending rx messages */
+	list_for_each_entry_safe(rx_msg, rx_tmp, &rd->rx_msg_list, next)
+		kfree(rx_msg);
+	INIT_LIST_HEAD(&rd->rx_msg_list);
+
+	/* stop current tx work, it may still be scheduled afterwards
+	 * but will return immediatly since we set stopping state,
+	 * just finish the current run */
+	cancel_work_sync(&rd->tx_work);
+
+	/* any new sendmsg call will be rejected from now on, flush
+	 * pending tx message and wakeup all senders */
+	do {
+		struct remoti_tx_msg *tx_msg, *tx_tmp;
+		bool done;
+
+		spin_lock(&rd->tx_msg_list_lock);
+		list_for_each_entry_safe(tx_msg, tx_tmp,
+					 &rd->tx_msg_list, next) {
+
+			if (atomic_read(&tx_msg->users) == 1) {
+				/* no more users */
+				list_del(&tx_msg->next);
+				kfree(tx_msg);
+			} else {
+				tx_msg->canceled = true;
+				complete(&tx_msg->complete);
+			}
+		}
+
+		done = list_empty(&rd->tx_msg_list);
+
+		spin_unlock(&rd->tx_msg_list_lock);
+		if (done)
+			break;
+
+		dev_set_state(rd, RTI_DEV_S_STOPPING);
+		msleep(100);
+
+	} while (1);
+
+	/* now wait for all users */
+	users = atomic_read(&rd->user_count);
+	if (users)
+		dev_info(&rd->pdev->dev, "waiting for %u users "
+			 "to detach\n", users);
+	do {
+		if (!atomic_read(&rd->user_count))
+			break;
+
+		/* tell the world */
+		dev_set_state(rd, RTI_DEV_S_STOPPING);
+
+		msleep(100);
+
+	} while (1);
+
+	/* flush callback list */
+	list_for_each_entry_safe(cb_elem, cb_tmp,
+				 &rd->callback_list, next)
+		kfree(cb_elem);
+	INIT_LIST_HEAD(&rd->callback_list);
+}
+
+/*
+ *
+ */
+static int fsm_need_change(struct remoti_device *rd, bool *req_state)
+{
+	mutex_lock(&rd->req_state_mutex);
+	if (!rd->req_state_changed) {
+		mutex_unlock(&rd->req_state_mutex);
+		return 0;
+	}
+
+	rd->req_state_changed = false;
+	*req_state = rd->req_state;
+	mutex_unlock(&rd->req_state_mutex);
+	return 1;
+}
+
+/*
+ * state machine for device start/booting/stop, run in private
+ * workqueue
+ */
+static void remoti_hw_fsm_work(struct work_struct *work)
+{
+	struct remoti_device *rd =
+		container_of(work, struct remoti_device, hw_fsm_work);
+	bool req_state;
+
+again:
+	switch (rd->state) {
+	case RTI_DEV_S_STOPPED:
+	case RTI_DEV_S_DEAD:
+		/* do nothing unless we have a start order */
+		if (!fsm_need_change(rd, &req_state) || !req_state)
+			break;
+
+		/* start booting device */
+		dev_set_state(rd, RTI_DEV_S_BOOTING);
+		goto again;
+
+	case RTI_DEV_S_BOOTING:
+		start_tty(rd->tty);
+		set_bit(TTY_DO_WRITE_WAKEUP, &rd->tty->flags);
+
+		/* register debug stuffs */
+		remoti_register_cmd_callback(rd, NPI_SYS_UTIL,
+					     RTI_DBG_PRINT_IND,
+					     handle_printk_ind, rd);
+		remoti_register_cmd_callback(rd, NPI_SYS_UTIL,
+					     RTI_DBG_ASSERT_IND,
+					     handle_assert_ind, rd);
+
+		/* keep init_cnf for us */
+		remoti_register_cmd_callback(rd, NPI_SYS_RCAF, RTI_INIT_CNF,
+					     handle_init_cnf, rd);
+
+		if (boot_device(rd)) {
+			stop_device(rd);
+			dev_set_state(rd, RTI_DEV_S_BOOT_FAILED);
+			dev_err(&rd->pdev->dev, "failed to boot device\n");
+			return;
+		}
+
+		dev_info(&rd->pdev->dev, "RNP firmware version: %08x\n",
+			 rd->fw_version);
+		dev_set_state(rd, RTI_DEV_S_OPERATIONAL);
+		break;
+
+	case RTI_DEV_S_BOOT_FAILED:
+		/* a start command will make us retry booting */
+		if (!fsm_need_change(rd, &req_state))
+			break;
+
+		if (req_state)
+			dev_set_state(rd, RTI_DEV_S_BOOTING);
+		else
+			dev_set_state(rd, RTI_DEV_S_STOPPED);
+		goto again;
+
+	case RTI_DEV_S_OPERATIONAL:
+		/* a stop command or a pending hw error will make stop
+		 * the device */
+		if ((!fsm_need_change(rd, &req_state) || req_state) &&
+		    !rd->timeout)
+			break;
+
+		if (rd->timeout)
+			dev_warn(&rd->pdev->dev, "stopping device after "
+				 "command timeout");
+
+		stop_device(rd);
+
+		if (rd->timeout)
+			dev_set_state(rd, RTI_DEV_S_DEAD);
+		else
+			dev_set_state(rd, RTI_DEV_S_STOPPED);
+		break;
+
+	case RTI_DEV_S_STOPPING:
+		/* transient state */
+		break;
+	}
+}
+
+
+/*
+ * called when userspace issue an ioctl on serial port using remoti
+ * ldisc
+ */
+static int remoti_tty_ioctl(struct tty_struct *tty,
+			    unsigned int cmd, unsigned long arg)
+{
+	struct remoti_device *rd;
+	void __user *useraddr = (void *)arg;
+
+	rd = (struct remoti_device *)tty->disc_data;
+
+	switch (cmd) {
+	case RTI_ATTACH_DEVICE:
+	{
+		bool found;
+		__u32 id;
+
+		/* make sure we are not already attached */
+		if (rd)
+			return -EBUSY;
+
+		if (copy_from_user(&id, useraddr, sizeof (id)))
+			return -EFAULT;
+
+		/* lookup device */
+		found = false;
+		spin_lock(&remoti_devs_list_lock);
+		list_for_each_entry(rd, &remoti_devs_list, next) {
+			if (rd->pdata.id == id) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			spin_unlock(&remoti_devs_list_lock);
+			return -ENODEV;
+		}
+
+		rd->tty = tty;
+		tty->disc_data = rd;
+		spin_unlock(&remoti_devs_list_lock);
+
+		/* hack: force release of any gpio export done by
+		 * userspace */
+		gpio_free(rd->pdata.reset_gpio);
+
+		/* hold device reset and set its initial state */
+		dev_hw_reset_hold(rd);
+		rd->state = RTI_DEV_S_STOPPED;
+		break;
+	}
+
+	case RTI_GET_STATUS:
+	{
+		struct rti_dev_status st;
+
+		/* need to be attached */
+		if (!rd)
+			return -ENODEV;
+
+		memset(&st, 0, sizeof (st));
+		st.dev_state = rd->state;
+		st.fw_version = rd->fw_version;
+
+		if (copy_to_user(useraddr,&st, sizeof (st)))
+			return -EFAULT;
+
+		break;
+	}
+
+	case RTI_GET_STATS:
+		/* need to be attached */
+		if (!rd)
+			return -ENODEV;
+
+		rd = (struct remoti_device *)tty->disc_data;
+		if (copy_to_user(useraddr, &rd->stats, sizeof (rd->stats)))
+			return -EFAULT;
+		break;
+
+	case RTI_START_DEVICE:
+	case RTI_STOP_DEVICE:
+		/* need to be attached */
+		if (!rd)
+			return -ENODEV;
+
+		if (cmd == RTI_START_DEVICE) {
+			u32 boot_flags;
+
+			if (copy_from_user(&boot_flags, useraddr,
+					   sizeof (boot_flags)))
+				return -EFAULT;
+			rd->boot_flags = boot_flags;
+		}
+
+		mutex_lock(&rd->req_state_mutex);
+		rd->req_state = (cmd == RTI_START_DEVICE) ? true : false;
+		rd->req_state_changed = true;
+		mutex_unlock(&rd->req_state_mutex);
+		queue_work(rd->fsm_workqueue, &rd->hw_fsm_work);
+		break;
+
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
+/*
+ * callback when userspace set the remoti ldisc on tty device
+ */
+static int remoti_tty_open(struct tty_struct *tty)
+{
+	/* leave unattached for now, ioctl will do it */
+	tty->disc_data = NULL;
+	tty->receive_room = 65536;
+	stop_tty(tty);
+	return 0;
+}
+
+/*
+ *
+ */
+static void remoti_tty_close(struct tty_struct *tty)
+{
+	struct remoti_device *rd;
+
+	rd = (struct remoti_device *)tty->disc_data;
+	if (!rd)
+		return;
+
+	dev_info(&rd->pdev->dev, "tty closing...\n");
+
+	/* no more ioctl possible, so we have control over device fsm,
+	 * ask it to stop device */
+	mutex_lock(&rd->req_state_mutex);
+	rd->req_state = false;
+	rd->req_state_changed = true;
+	mutex_unlock(&rd->req_state_mutex);
+	queue_work(rd->fsm_workqueue, &rd->hw_fsm_work);
+
+	while (rd->state != RTI_DEV_S_STOPPED &&
+	       rd->state != RTI_DEV_S_DEAD)
+		msleep(10);
+
+	dev_info(&rd->pdev->dev, "tty released\n");
+}
+
+static struct tty_ldisc_ops remoti_ldisc = {
+	.owner		= THIS_MODULE,
+	.num		= N_REMOTI,
+	.name		= "n_remoti",
+	.open		= remoti_tty_open,
+	.close		= remoti_tty_close,
+	.ioctl		= remoti_tty_ioctl,
+	.receive_buf	= remoti_tty_recv_buf,
+	.write_wakeup	= remoti_tty_write_resume,
+};
+
+/*
+ *
+ */
+static int remoti_probe(struct platform_device *pdev)
+{
+	struct remoti_device *rd;
+	const unsigned int *gpio_prop, *id_prop;
+	char wq_name[32];
+	int proplen;
+	int err;
+
+	/* allocated device & mark it as unattached  */
+	rd = kzalloc(sizeof (*rd), GFP_KERNEL);
+	if (!rd) {
+		dev_err(&pdev->dev, "unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	id_prop = of_get_property(pdev->dev.of_node, "id", &proplen);
+	if (!id_prop || proplen < 4) {
+		dev_err(&pdev->dev, "unable to get id property\n");
+		err = -ENODEV;
+		goto out_free;
+	}
+
+	gpio_prop = of_get_property(pdev->dev.of_node, "reset-gpio", &proplen);
+	if (!gpio_prop || proplen < 8) {
+		dev_err(&pdev->dev, "unable to get reset-gpio property\n");
+		err = -ENODEV;
+		goto out_free;
+	}
+
+	rd->pdata.id = be32_to_cpup(id_prop);
+	rd->pdata.reset_gpio = be32_to_cpup(gpio_prop);
+	rd->pdata.reset_polarity = be32_to_cpup(gpio_prop + 1);
+	BUG_ON(rd->pdata.reset_gpio != 100);
+	rd->pdev = pdev;
+
+	scnprintf(wq_name, sizeof (wq_name), "%s-fsm", pdev->name);
+	rd->fsm_workqueue = create_singlethread_workqueue(wq_name);
+	if (!rd->fsm_workqueue) {
+		dev_err(&pdev->dev, "unable to create workqueue\n");
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	scnprintf(wq_name, sizeof (wq_name), "%s-io", pdev->name);
+	rd->io_workqueue = create_singlethread_workqueue(wq_name);
+	if (!rd->io_workqueue) {
+		dev_err(&pdev->dev, "unable to create workqueue\n");
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	spin_lock_init(&rd->state_lock);
+
+	INIT_LIST_HEAD(&rd->tx_msg_list);
+	spin_lock_init(&rd->tx_msg_list_lock);
+
+	INIT_LIST_HEAD(&rd->rx_msg_list);
+	spin_lock_init(&rd->rx_msg_list_lock);
+
+	INIT_LIST_HEAD(&rd->callback_list);
+	spin_lock_init(&rd->callback_list_lock);
+
+	INIT_WORK(&rd->hw_fsm_work, remoti_hw_fsm_work);
+	INIT_WORK(&rd->tx_work, remoti_tx_work);
+	INIT_WORK(&rd->rx_work, remoti_rx_work);
+	init_completion(&rd->wakeup_complete);
+	init_completion(&rd->init_cnf_complete);
+	mutex_init(&rd->req_state_mutex);
+
+	platform_set_drvdata(pdev, rd);
+
+	/* create sysfs entries */
+	err = remoti_register_dev_sysfs(rd);
+	if (err)
+		goto out_free;
+
+	spin_lock(&remoti_devs_list_lock);
+	list_add_tail(&rd->next, &remoti_devs_list);
+	spin_unlock(&remoti_devs_list_lock);
+
+	err = of_platform_populate(pdev->dev.of_node,
+				   NULL, NULL,
+				   &pdev->dev);
+	if (err)
+		dev_err(&pdev->dev,
+			"failed to probe remoti subnodes: %d\n",
+			err);
+	return 0;
+
+out_free:
+	if (rd->fsm_workqueue)
+		destroy_workqueue(rd->fsm_workqueue);
+
+	if (rd->io_workqueue)
+		destroy_workqueue(rd->io_workqueue);
+
+	kfree(rd);
+	return err;
+}
+
+/*
+ *
+ */
+void __remoti_free_device(struct remoti_device *rd)
+{
+	destroy_workqueue(rd->fsm_workqueue);
+	destroy_workqueue(rd->io_workqueue);
+	kfree(rd);
+}
+
+/*
+ *
+ */
+static int remoti_remove(struct platform_device *pdev)
+{
+	struct remoti_device *rd = platform_get_drvdata(pdev);
+
+	spin_lock(&remoti_devs_list_lock);
+	list_del(&rd->next);
+	spin_unlock(&remoti_devs_list_lock);
+	platform_set_drvdata(pdev, NULL);
+
+	remoti_unregister_dev_sysfs(rd);
+	/* actual free is done from sysfs */
+	return 0;
+}
+
+static const struct of_device_id remoti_of_ids[] = {
+	{ .compatible = "ti,remoti" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, remoti_of_ids);
+
+static struct platform_driver remoti_driver = {
+	.driver = {
+		.name	= "remoti",
+		.owner	= THIS_MODULE,
+		.of_match_table = remoti_of_ids,
+	},
+	.probe		= remoti_probe,
+	.remove		= remoti_remove,
+};
+
+/*
+ *
+ */
+static int __init remoti_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_devs_list);
+
+	ret = remoti_sysfs_init();
+	if (ret) {
+		pr_err("failed to register sysfs class\n");
+		goto out;
+	}
+
+	ret = platform_driver_register(&remoti_driver);
+	if (ret) {
+		pr_err("failed to register platform driver\n");
+		goto out_sysfs;
+	}
+
+	ret = tty_register_ldisc(&remoti_ldisc);
+	if (ret) {
+		pr_err("failed to register line discipline\n");
+		goto out_pdev;
+	}
+
+	return 0;
+
+out_sysfs:
+	remoti_sysfs_exit();
+
+out_pdev:
+	platform_driver_unregister(&remoti_driver);
+
+out:
+	return ret;
+}
+
+/*
+ *
+ */
+static void __exit remoti_exit(void)
+{
+	platform_driver_unregister(&remoti_driver);
+	tty_unregister_ldisc(&remoti_ldisc);
+	remoti_sysfs_exit();
+}
+
+module_init(remoti_init);
+module_exit(remoti_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("RemoTI core driver");
+MODULE_ALIAS("platform:remoti");
+MODULE_FIRMWARE(REMOTI_FW_NAME);
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./leds.c linux-6.4-fbx/drivers/misc/remoti/leds.c
--- linux-6.4-fbx/drivers/misc/remoti./leds.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/leds.c	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,249 @@
+/*
+ * LEDs support over RemoTI IPCs
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/sysfs.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <linux/remoti/remoti.h>
+#include <linux/remoti/leds.h>
+#include <linux/of.h>
+
+#define PFX	KBUILD_MODNAME ": "
+
+/* list of remoti gpio devices */
+static DEFINE_MUTEX(remoti_leds_list_mutex);
+static struct list_head remoti_leds_list;
+
+/*
+ * Util RPCs subsystem
+ */
+#define RTI_LEDS_SET		0x00
+#define RTI_LEDS_GET		0x01
+
+#define RTI_LEDS_MODE_MAX	0x01
+
+struct remoti_led_data {
+	unsigned int		rti_dev_id;
+	u8			hw_id;
+	struct led_classdev	ldev;
+	struct rti_udev		*udev;
+	struct platform_device	*pdev;
+	struct list_head	next;
+};
+
+static int send_led_set(struct remoti_led_data *led, u8 status)
+{
+	struct rti_msg msg;
+	u8 *command;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_LEDS_SET;
+
+	command = msg.data;
+	command[0] = led->hw_id;
+	command[1] = status;
+	msg.data_len = 2;
+
+	return rti_send_sync_msg(led->udev, &msg);
+}
+
+/*
+ * LED stuff
+ */
+static void remoti_set_brightness(struct led_classdev *led_cdev,
+				  enum led_brightness brightness)
+{
+	struct remoti_led_data *led;
+
+	led = container_of(led_cdev, struct remoti_led_data, ldev);
+	send_led_set(led, brightness);
+}
+
+/*
+ * We support hardware blinking and flashing
+ */
+static int remoti_set_blink(struct led_classdev *led_cdev,
+			unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct remoti_led_data *led;
+
+	led = container_of(led_cdev, struct remoti_led_data, ldev);
+	return send_led_set(led, 0x04);
+}
+
+static int try_register_led(struct remoti_led_data *led)
+{
+	int ret;
+
+	led->udev = rti_get_udevice(led->rti_dev_id);
+	if (!led->udev)
+		return 0;
+
+	/* register kernel led */
+	ret = led_classdev_register(&led->pdev->dev, &led->ldev);
+	if (ret) {
+		dev_err(&led->pdev->dev, "cannot register LED: %s\n",
+			led->ldev.name);
+		rti_release_udevice(led->udev);
+		led->udev = NULL;
+		return ret;
+	}
+
+	dev_info(&led->pdev->dev, "registered LED %s\n",
+		 led->ldev.name);
+	return 0;
+}
+
+
+static int rti_udev_notifier_cb(struct notifier_block *n,
+				unsigned long id, void *data)
+{
+	struct remoti_led_data *led;
+	enum rti_udev_state *st = (enum rti_udev_state *)data;
+
+	mutex_lock(&remoti_leds_list_mutex);
+
+	list_for_each_entry(led, &remoti_leds_list, next) {
+
+		if (led->rti_dev_id != id)
+			continue;
+
+		switch (*st) {
+		case RTI_UDEV_UP:
+			if (led->udev)
+				continue;
+
+			try_register_led(led);
+			break;
+
+		case RTI_UDEV_GOING_DOWN:
+			if (!led->udev)
+				continue;
+
+			led_classdev_unregister(&led->ldev);
+			rti_release_udevice(led->udev);
+			led->udev = NULL;
+			break;
+		}
+	}
+
+	mutex_unlock(&remoti_leds_list_mutex);
+	return 0;
+}
+
+static struct notifier_block rti_udev_notifier_block = {
+	.notifier_call = rti_udev_notifier_cb,
+};
+
+static int remoti_leds_probe(struct platform_device *pdev)
+{
+	struct device_node *child;
+	struct remoti_led_data *leds_data;
+	const char *leds_name[REMOTI_LEDS_COUNT];
+	unsigned int num_leds = 0;
+	int i;
+
+	for_each_child_of_node(pdev->dev.of_node, child) {
+		leds_name[num_leds] = of_get_property(child, "label", NULL);
+		if (!leds_name[num_leds])
+			continue;
+		num_leds++;
+	};
+
+	leds_data = kzalloc(num_leds * sizeof(*leds_data), GFP_KERNEL);
+	if (!leds_data) {
+		dev_err(&pdev->dev, "no memory for leds\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_leds; i++) {
+		struct remoti_led_data *led = &leds_data[i];
+
+		led->pdev = pdev;
+		led->hw_id = i;
+		memset(&led->ldev, 0, sizeof (led->ldev));
+		led->ldev.name = leds_name[i];
+		led->ldev.max_brightness = 1;
+		led->ldev.brightness_set = remoti_set_brightness;
+		led->ldev.blink_set = remoti_set_blink;
+		led->ldev.flags = LED_CORE_SUSPENDRESUME;
+
+		mutex_lock(&remoti_leds_list_mutex);
+		try_register_led(led);
+		list_add_tail(&led->next, &remoti_leds_list);
+		mutex_unlock(&remoti_leds_list_mutex);
+	}
+
+	platform_set_drvdata(pdev, leds_data);
+	return 0;
+}
+
+static int remoti_leds_remove(struct platform_device *pdev)
+{
+	struct remoti_led_data *leds_data =
+				platform_get_drvdata(pdev);
+	struct remoti_led_data *led;
+
+	mutex_lock(&remoti_leds_list_mutex);
+	list_for_each_entry(led, &remoti_leds_list, next) {
+		if (led->udev) {
+			led_classdev_unregister(&led->ldev);
+			rti_release_udevice(led->udev);
+		}
+	}
+	kfree(leds_data);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct of_device_id remoti_leds_of_ids[] = {
+	{ .compatible = "ti,remoti-leds" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, remoti_leds_of_ids);
+
+static struct platform_driver remoti_leds_driver = {
+	.driver	= {
+		.name	= "remoti-leds",
+		.owner	= THIS_MODULE,
+		.of_match_table = remoti_leds_of_ids,
+	},
+	.probe	= remoti_leds_probe,
+	.remove = remoti_leds_remove,
+};
+
+static int __init remoti_leds_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_leds_list);
+
+	ret = platform_driver_register(&remoti_leds_driver);
+	if (ret)
+		return ret;
+
+	rti_register_udevice_notifier(&rti_udev_notifier_block);
+	return 0;
+}
+
+static void __exit remoti_leds_exit(void)
+{
+	rti_unregister_udevice_notifier(&rti_udev_notifier_block);
+	platform_driver_unregister(&remoti_leds_driver);
+}
+
+module_init(remoti_leds_init);
+module_exit(remoti_leds_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("RemoTI LEDS class support");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:remoti-leds");
diff -Nruw linux-6.4-fbx/drivers/misc/remoti./user.c linux-6.4-fbx/drivers/misc/remoti/user.c
--- linux-6.4-fbx/drivers/misc/remoti./user.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/misc/remoti/user.c	2023-11-29 17:07:10.431656439 +0100
@@ -0,0 +1,545 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/sched/signal.h>
+#include <net/sock.h>
+#include <linux/remoti/remoti.h>
+
+struct rti_rx_msg {
+	struct rti_msg		msg;
+	struct list_head	next;
+};
+
+struct rti_sock_callback {
+	struct rti_callback	cb;
+	struct list_head	next;
+};
+
+struct rti_sock {
+	struct sock		sk;
+	unsigned int		rti_dev_id;
+
+	struct mutex		udev_mutex;
+	struct rti_udev		*udev;
+
+	struct list_head	rx_queue;
+	unsigned int		rx_queue_len;
+	spinlock_t		rx_queue_lock;
+
+	struct list_head	callback_list;
+	struct list_head	next;
+};
+
+#define RX_QUEUE_MAX_LEN	128
+
+static DEFINE_MUTEX(remoti_socks_list_mutex);
+static struct list_head remoti_socks_list;
+
+/*
+ *
+ */
+static inline struct rti_sock *to_rti_sock(const struct sock *sk)
+{
+	return container_of(sk, struct rti_sock, sk);
+}
+
+/*
+ *
+ */
+static void remoti_sock_deliver(void *cb_data, const struct rti_msg *msg)
+{
+	struct rti_sock *rti_sk = (struct rti_sock *)cb_data;
+	struct rti_rx_msg *rx_msg;
+
+	if (rti_sk->rx_queue_len > RX_QUEUE_MAX_LEN) {
+		if (printk_ratelimit())
+			printk(KERN_ERR "rti_sock: socket queue rx "
+			       "overflow, dropping\n");
+		return;
+	}
+
+	rx_msg = kmalloc(sizeof (*rx_msg), GFP_ATOMIC);
+	if (!rx_msg)
+		return;
+
+	memcpy(&rx_msg->msg, msg, sizeof (*msg));
+
+	spin_lock(&rti_sk->rx_queue_lock);
+	list_add_tail(&rx_msg->next, &rti_sk->rx_queue);
+	rti_sk->rx_queue_len++;
+	spin_unlock(&rti_sk->rx_queue_lock);
+
+	wake_up(sk_sleep(&rti_sk->sk));
+}
+
+/*
+ *
+ */
+static int remoti_sock_connect(struct socket *sock,
+			       struct sockaddr *vaddr,
+			       int sockaddr_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sk);
+	struct sockaddr_rti *rti_addr;
+	int ret;
+
+	lock_sock(sk);
+	ret = 0;
+
+	if (sock->state != SS_UNCONNECTED) {
+		ret = -EISCONN;
+		goto out;
+	}
+
+	if (sockaddr_len != sizeof (struct sockaddr_rti)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	rti_addr = (struct sockaddr_rti *)vaddr;
+
+	mutex_lock(&rti_sk->udev_mutex);
+	rti_sk->udev = rti_get_udevice(rti_addr->device_id);
+	if (!rti_sk->udev) {
+		mutex_unlock(&rti_sk->udev_mutex);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	rti_sk->rti_dev_id = rti_addr->device_id;
+	sock->state = SS_CONNECTED;
+	mutex_unlock(&rti_sk->udev_mutex);
+
+out:
+	release_sock(sk);
+	return ret;
+}
+
+/*
+ *
+ */
+static int remoti_sock_sendmsg(struct socket *sock, struct msghdr *m,
+			       size_t total_len)
+{
+	struct rti_sock *rti_sk = to_rti_sock(sock->sk);
+	struct rti_msg msg;
+	bool async;
+	int ret;
+	struct iov_iter iter;
+
+	ret = 0;
+	mutex_lock(&rti_sk->udev_mutex);
+
+	if (sock->state != SS_CONNECTED) {
+		ret = -ENOTCONN;
+		goto out;
+	}
+
+	if (!rti_sk->udev) {
+		ret = -ECONNRESET;
+		goto out;
+	}
+
+	if (m->msg_name) {
+		ret = -EISCONN;
+		goto out;
+	}
+
+	if (total_len != sizeof (struct rti_msg)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	iter = m->msg_iter;
+	if (memcpy_from_msg(&msg, m, sizeof (msg))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	/* use message type to know if we need to do a sync or async
+	 * send */
+	async = (msg.type == NPI_AREQ);
+
+	if (async)
+		ret = rti_send_async_msg(rti_sk->udev, &msg);
+	else
+		ret = rti_send_sync_msg(rti_sk->udev, &msg);
+
+	if (ret)
+		goto out;
+
+	if (!async) {
+		m->msg_iter = iter;
+		m->msg_iter.data_source = false;
+		/* transfer reply to userspace */
+		if (memcpy_to_msg(m, &msg, sizeof (msg))) {
+			ret = -EFAULT;
+			goto out;
+		}
+	}
+	ret = sizeof (msg);
+
+out:
+	mutex_unlock(&rti_sk->udev_mutex);
+	return ret;
+}
+
+/*
+ *
+ */
+static unsigned int remoti_sock_poll(struct file *file, struct socket *sock,
+				     poll_table *wait)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sock->sk);
+	unsigned int mask = 0;
+
+	poll_wait(file, sk_sleep(sk), wait);
+
+	mutex_lock(&rti_sk->udev_mutex);
+	if (!rti_sk->udev)
+		mask |= POLLRDHUP | POLLERR;
+	mutex_unlock(&rti_sk->udev_mutex);
+
+	if (!list_empty(&rti_sk->rx_queue))
+		mask |= POLLIN;
+
+	return mask;
+}
+
+/*
+ *
+ */
+static int remoti_sock_recvmsg(struct socket *sock, struct msghdr *m,
+			       size_t total_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sk);
+	int nonblock = flags & MSG_DONTWAIT;
+	struct rti_rx_msg *rx_msg;
+	long timeout;
+	size_t ret;
+
+	if (sock->state != SS_CONNECTED)
+		return -ENOTCONN;
+
+	do {
+		/* make sure device is still here */
+		mutex_lock(&rti_sk->udev_mutex);
+		if (!rti_sk->udev) {
+			mutex_unlock(&rti_sk->udev_mutex);
+			return -ECONNRESET;
+		}
+		mutex_unlock(&rti_sk->udev_mutex);
+
+		/* wait for any packet */
+		timeout = sock_rcvtimeo(sk, nonblock);
+		timeout = wait_event_interruptible_timeout(
+			*sk_sleep(sk),
+			!list_empty(&rti_sk->rx_queue) ||
+			!rti_sk->udev,
+			timeout);
+
+		if (list_empty(&rti_sk->rx_queue) && timeout == 0) {
+			/* timeout elapsed */
+			return -EAGAIN;
+		}
+
+		if (signal_pending(current))
+			return -EINTR;
+
+		/* dequeue one message */
+		rx_msg = NULL;
+		spin_lock(&rti_sk->rx_queue_lock);
+		if (!list_empty(&rti_sk->rx_queue)) {
+			rx_msg = list_first_entry(&rti_sk->rx_queue,
+						  struct rti_rx_msg, next);
+			if (!(flags & MSG_PEEK)) {
+				list_del(&rx_msg->next);
+				rti_sk->rx_queue_len--;
+			}
+
+		}
+		spin_unlock(&rti_sk->rx_queue_lock);
+
+		if (!rx_msg) {
+			/* someone took it before us, resleep */
+			continue;
+		}
+
+		ret = sizeof (struct rti_msg);
+		if (total_len < sizeof (struct rti_msg)) {
+			ret = total_len;
+			m->msg_flags |= MSG_TRUNC;
+		}
+
+		/* transfer reply to userspace */
+		if (memcpy_to_msg(m, &rx_msg->msg, ret))
+			ret = -EFAULT;
+
+		if (!(flags & MSG_PEEK))
+			kfree(rx_msg);
+
+		/* done */
+		return ret;
+
+	} while (1);
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int remoti_sock_setsockopt(struct socket *sock, int level, int optname,
+				  sockptr_t optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sk);
+
+	if (level != SOL_REMOTI)
+		return -ENOPROTOOPT;
+
+	switch (optname) {
+	case REMOTI_REGISTER_CB:
+	{
+		struct rti_callback cb;
+		struct rti_sock_callback *cb_elem;
+		int ret;
+
+		if (sock->state != SS_CONNECTED)
+			return -ENOTCONN;
+
+		if (optlen != sizeof (cb))
+			return -EINVAL;
+
+		if (copy_from_sockptr(&cb, optval, sizeof (cb)))
+			return -EFAULT;
+
+		mutex_lock(&rti_sk->udev_mutex);
+		if (!rti_sk->udev) {
+			mutex_unlock(&rti_sk->udev_mutex);
+			return -EIO;
+		}
+
+		cb_elem = kmalloc(sizeof (*cb_elem), GFP_KERNEL);
+		if (!cb_elem) {
+			mutex_unlock(&rti_sk->udev_mutex);
+			return -ENOMEM;
+		}
+
+		memcpy(&cb_elem->cb, &cb, sizeof (cb));
+
+		ret = rti_register_cmd_callback(rti_sk->udev,
+						cb.subsys, cb.cmd,
+						remoti_sock_deliver, rti_sk);
+
+		if (!ret)
+			list_add_tail(&cb_elem->next, &rti_sk->callback_list);
+		else
+			kfree(cb_elem);
+
+		mutex_unlock(&rti_sk->udev_mutex);
+		return ret;
+	}
+
+	default:
+		return -ENOPROTOOPT;
+	}
+
+	return 0;
+}
+
+
+/*
+ *
+ */
+static int remoti_sock_release(struct socket *sock)
+{
+	struct sock *sk;
+	struct rti_sock *rti_sk;
+
+	if (!sock || !sock->sk)
+		return 0;
+
+	sk = sock->sk;
+	rti_sk = to_rti_sock(sk);
+
+	sock_orphan(sk);
+	mutex_lock(&rti_sk->udev_mutex);
+	if (rti_sk->udev) {
+		struct rti_sock_callback *cb_elem, *tmp;
+
+		list_for_each_entry_safe(cb_elem, tmp, &rti_sk->callback_list,
+					 next) {
+			rti_unregister_cmd_callback(rti_sk->udev,
+						    cb_elem->cb.subsys,
+						    cb_elem->cb.cmd);
+			kfree(cb_elem);
+		}
+
+		INIT_LIST_HEAD(&rti_sk->callback_list);
+		rti_release_udevice(rti_sk->udev);
+		rti_sk->udev = NULL;
+	}
+	mutex_unlock(&rti_sk->udev_mutex);
+
+	mutex_lock(&remoti_socks_list_mutex);
+	list_del(&rti_sk->next);
+	mutex_unlock(&remoti_socks_list_mutex);
+
+	sock->sk = NULL;
+	sock_put(sk);
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int rti_udev_notifier_cb(struct notifier_block *n,
+				unsigned long id, void *data)
+{
+	struct rti_sock *rti_sk;
+	enum rti_udev_state *st = (enum rti_udev_state *)data;
+
+	/* only interested in "going down" state */
+	if (*st == RTI_UDEV_UP)
+		return 0;
+
+	mutex_lock(&remoti_socks_list_mutex);
+
+	list_for_each_entry(rti_sk, &remoti_socks_list, next) {
+
+		if (rti_sk->rti_dev_id != id)
+			continue;
+
+		if (!mutex_trylock(&rti_sk->udev_mutex))
+			continue;
+
+		if (rti_sk->udev) {
+			struct rti_sock_callback *cb_elem, *tmp;
+
+			list_for_each_entry_safe(cb_elem, tmp,
+						 &rti_sk->callback_list,
+						 next)
+				kfree(cb_elem);
+
+			INIT_LIST_HEAD(&rti_sk->callback_list);
+			rti_release_udevice(rti_sk->udev);
+			rti_sk->udev = NULL;
+
+			wake_up(sk_sleep(&rti_sk->sk));
+		}
+		mutex_unlock(&rti_sk->udev_mutex);
+	}
+
+	mutex_unlock(&remoti_socks_list_mutex);
+	return 0;
+}
+
+static struct notifier_block rti_udev_notifier_block = {
+	.notifier_call = rti_udev_notifier_cb,
+};
+
+static const struct proto_ops remoti_proto_ops = {
+	.family =	PF_REMOTI,
+
+	.accept =	sock_no_accept,
+	.bind =		sock_no_bind,
+	.connect =	remoti_sock_connect,
+	.getname =	sock_no_getname,
+	.ioctl =	sock_no_ioctl,
+	.listen =	sock_no_listen,
+	.mmap =		sock_no_mmap,
+	.owner =	THIS_MODULE,
+	.poll =		remoti_sock_poll,
+	.recvmsg =	remoti_sock_recvmsg,
+	.release =	remoti_sock_release,
+	.setsockopt =	remoti_sock_setsockopt,
+	.sendmsg =	remoti_sock_sendmsg,
+	.shutdown =	sock_no_shutdown,
+	.socketpair =	sock_no_socketpair,
+	.sendpage =	sock_no_sendpage,
+};
+
+static struct proto remoti_proto = {
+        .name           = "remoti",
+        .owner          =  THIS_MODULE,
+        .obj_size       = sizeof (struct rti_sock),
+};
+
+static int remoti_sock_create(struct net *net, struct socket *sock,
+			      int protocol, int kern)
+{
+	struct sock *sk;
+	struct rti_sock *rti_sk;
+
+	if (sock->type != SOCK_SEQPACKET || protocol)
+		return -ESOCKTNOSUPPORT;
+
+        sk = sk_alloc(net, PF_REMOTI, GFP_KERNEL, &remoti_proto, kern);
+	if (!sk)
+		return -ENOMEM;
+
+        sock_init_data(sock, sk);
+        sock->state = SS_UNCONNECTED;
+        sock->ops = &remoti_proto_ops;
+
+	rti_sk = to_rti_sock(sk);
+	rti_sk->udev = NULL;
+	mutex_init(&rti_sk->udev_mutex);
+	INIT_LIST_HEAD(&rti_sk->callback_list);
+	INIT_LIST_HEAD(&rti_sk->rx_queue);
+	spin_lock_init(&rti_sk->rx_queue_lock);
+
+	mutex_lock(&remoti_socks_list_mutex);
+	list_add_tail(&rti_sk->next, &remoti_socks_list);
+	mutex_unlock(&remoti_socks_list_mutex);
+
+	return 0;
+}
+
+static struct net_proto_family remoti_family_ops = {
+	.family = PF_REMOTI,
+	.create = remoti_sock_create,
+	.owner = THIS_MODULE,
+};
+
+static int __init remoti_user_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_socks_list);
+
+	ret = proto_register(&remoti_proto, 0);
+	if (ret)
+		return ret;
+
+	ret = sock_register(&remoti_family_ops);
+	if (ret)
+		goto fail_proto;
+
+	rti_register_udevice_notifier(&rti_udev_notifier_block);
+	return 0;
+
+fail_proto:
+	proto_unregister(&remoti_proto);
+
+	return ret;
+}
+
+static void __exit remoti_user_exit(void)
+{
+	rti_unregister_udevice_notifier(&rti_udev_notifier_block);
+	sock_unregister(PF_REMOTI);
+	proto_unregister(&remoti_proto);
+}
+
+module_init(remoti_user_init);
+module_exit(remoti_user_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_REMOTI);
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/drivers/mtd/nand/raw/denali_nand.c	2023-11-29 17:07:10.484989855 +0100
@@ -0,0 +1,995 @@
+/*
+ * denali nand controller driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/mtd.h>
+
+#include <linux/mtd/partitions.h>
+
+#define PFX	"denali_nand: "
+
+#include "denali_nand.h"
+
+#define DENALI_NAND_DMA_BUF_SIZE	(2 * 4096)
+
+static const char *parts_parsers[] = { "fbx6hd-mtdparts", NULL };
+
+static int ecc_strength;
+module_param(ecc_strength, int, 0);
+MODULE_PARM_DESC(ecc_strength, "ECC strength to use");
+
+/*
+ * All the interrupt sources used by the driver.
+ */
+#define DNL_ALL_INTERRUPTS (DNL_INT_DMA_DATA_CMD_COMPLETE |	\
+			    DNL_INT_BAD_CMD_SEQ |		\
+			    DNL_INT_LOAD_COMPLETE |		\
+			    DNL_INT_PROGRAM_COMPLETE |		\
+			    DNL_INT_PROGRAM_FAIL |		\
+			    DNL_INT_ERASE_FAILED |		\
+			    DNL_INT_ERASE_COMPLETE |		\
+			    DNL_INT_RESET_DONE |		\
+			    DNL_INT_WDOG_TIMEOUT)
+
+/*
+ * register accessors
+ */
+static inline u32 dnl_reg_readl(struct denali_nand_priv *priv, u32 addr)
+{
+	return readl(priv->regs + addr);
+}
+
+static inline void dnl_reg_writel(struct denali_nand_priv *priv, u32 val,
+				  u32 addr)
+{
+	writel(val, priv->regs + addr);
+}
+
+/*
+ * mem accessors.
+ */
+static inline u32 dnl_mem_readl(struct denali_nand_priv *priv, u32 addr)
+{
+	return readl(priv->mem + addr);
+}
+
+static inline void dnl_mem_writel(struct denali_nand_priv *priv, u32 val,
+				  u32 addr)
+{
+	writel(val, priv->mem + addr);
+}
+
+/*
+ * read/write to/from a map.
+ */
+static void dnl_map_write(struct denali_nand_priv *priv, u32 data,
+				 u32 map_ctl)
+{
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+	dnl_mem_writel(priv, data, DNL_MAP_DATA_REG);
+}
+
+/*
+ * get chip specific register offset depending on priv->chip_num.
+ */
+static inline u32 dnl_chip_reg_offset(struct denali_nand_priv *priv, u32 reg)
+{
+	return reg + priv->chip_num * 0x14 * 4;
+}
+
+/*
+ * read from chip specific register, specified in priv->chip_num
+ */
+static inline u32 dnl_chip_reg_readl(struct denali_nand_priv *priv, u32 reg)
+{
+	return dnl_reg_readl(priv, dnl_chip_reg_offset(priv, reg));
+}
+
+/*
+ * write from chip specific register, specified in priv->chip_num
+ */
+static inline void dnl_chip_reg_writel(struct denali_nand_priv *priv, u32 val,
+				      u32 reg)
+{
+	dnl_reg_writel(priv, val, dnl_chip_reg_offset(priv, reg));
+}
+
+/*
+ * enable/disable DMA helpers. DMA MUST be enabled before issuing the
+ * MAP10 four command sequence.
+ */
+static void dnl_enable_dma(struct denali_nand_priv *priv)
+{
+	dnl_reg_writel(priv, 1, DNL_DMA_ENABLE);
+	dnl_reg_readl(priv, DNL_DMA_ENABLE);
+}
+
+static void dnl_disable_dma(struct denali_nand_priv *priv)
+{
+	dnl_reg_writel(priv, 0, DNL_DMA_ENABLE);
+	dnl_reg_readl(priv, DNL_DMA_ENABLE);
+}
+
+/*
+ * used before and after reading/writing OOB.
+ */
+static void dnl_set_transfer_mode(struct denali_nand_priv *priv,
+				  int page, int mode)
+{
+	u32 map_ctl;
+	u32 data;
+
+	map_ctl = DNL_MAP_10_MASK;
+	map_ctl |= (priv->chip_num << DNL_CHIP_SHIFT);
+	map_ctl |= page;
+	data = mode;
+
+	dnl_map_write(priv, data, map_ctl);
+}
+
+static void dnl_clear_all_interrupts(struct denali_nand_priv *priv)
+{
+	spin_lock_irq(&priv->irq_status_lock);
+	dnl_chip_reg_writel(priv, 0xffff, DNL_0_INTR_STATUS_REG);
+	priv->irq_status = 0;
+	spin_unlock_irq(&priv->irq_status_lock);
+}
+
+/*
+ * configure a DMA access using the mapped dma buffer in priv. this is
+ * done by issuing the 4 command sequence described in the
+ * documentation, chapter7, page 52.
+ */
+static void dnl_setup_dma(struct denali_nand_priv *priv,
+			  u32 page_addr, int access_mode)
+{
+	u32 map_ctl;
+	u32 data;
+	u16 addr_hi;
+	u16 addr_lo;
+
+	addr_hi = ((u32)priv->read_buf_dma >> 16) & 0xffff;
+	addr_lo = (u32)priv->read_buf_dma & 0xffff;
+
+	map_ctl = DNL_MAP_10_MASK | (priv->chip_num << DNL_CHIP_SHIFT);
+
+	/*
+	 * first step, transmit page_addr, select between program or
+	 * read..
+	 */
+	if (access_mode == DNL_E_DMA_PROGRAM)
+		data = DNL_MAP10_DMA_WRITE_PAGE;
+	else
+		data = DNL_MAP10_DMA_READ_PAGE;
+	dnl_map_write(priv, data, map_ctl | page_addr);
+
+	/*
+	 * second step, transmit addr_hi
+	 */
+	dnl_map_write(priv, DNL_MAP10_DMA_SET_ADDR_HI,
+		      map_ctl | (addr_hi << 8));
+
+	/*
+	 * third step, transmit addr_lo
+	 */
+	dnl_map_write(priv, DNL_MAP10_DMA_SET_ADDR_LO,
+		      map_ctl | (addr_lo << 8));
+
+	/*
+	 * fourth step, raise interrupt when complete, 64byte burst.
+	 */
+	dnl_map_write(priv, DNL_MAP10_DMA_SET_PARAMS,
+		      map_ctl | DNL_DMA_PARAM_GEN_INT | DNL_DMA_BURST_64);
+}
+
+/*
+ * Enable interrupts globally on the Denali hardware. There is still a
+ * per chip interrupt status and mask.
+ */
+static void dnl_interrupt_global_enable(struct denali_nand_priv *priv, int enable)
+{
+	dnl_reg_writel(priv, enable ? 1 : 0, DNL_INT_ENABLE_REG);
+}
+
+/*
+ * clear all previous interrupts and unmask all interrupt statuses
+ * used by the driver. Interrupt are left globally disabled and will
+ * be enabled after request_irq().
+ */
+static void dnl_setup_irq(struct denali_nand_priv *priv)
+{
+	dnl_clear_all_interrupts(priv);
+	dnl_interrupt_global_enable(priv, 0);
+	dnl_chip_reg_writel(priv, DNL_ALL_INTERRUPTS, DNL_0_INTR_EN_REG);
+}
+
+/*
+ * clear the corresponding interrupt bits in the perchip interrupt
+ * status.
+ */
+static void dnl_clear_interrupts(struct denali_nand_priv *priv, u32 to_clear)
+{
+	dnl_chip_reg_writel(priv, to_clear, DNL_0_INTR_STATUS_REG);
+}
+
+/*
+ * Denali Interrupt service routing: check our interrupt status for
+ * the configured chip and signal waiters via irq_completion if there
+ * is something of interest.
+ */
+static irqreturn_t dnl_irq(int irq, void *dev_id)
+{
+	struct denali_nand_priv *priv = dev_id;
+	u32 irq_status = dnl_chip_reg_readl(priv, DNL_0_INTR_STATUS_REG) &
+		DNL_ALL_INTERRUPTS;
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	spin_lock(&priv->irq_status_lock);
+	dnl_clear_interrupts(priv, irq_status);
+	priv->irq_status |= irq_status;
+	complete(&priv->irq_completion);
+	spin_unlock(&priv->irq_status_lock);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Wait for specific interrupt flag to be set by the interrupt service
+ * routine, via irq_completion. report a timeout after 1 second if no
+ * of the bits of interest were set by the ISR.
+ *
+ * more than one bit can be set in the status_mask (for instance to
+ * watch program_complete and program_failed interrupt events). the
+ * status that caused this function to return is set in *res_status
+ * for the caller layer to sort out.
+ */
+static int dnl_wait_for_mask(struct denali_nand_priv *priv, u32 status_mask,
+			     u32 *res_status)
+{
+	int remain = msecs_to_jiffies(1000);
+
+	do {
+		remain = wait_for_completion_timeout(&priv->irq_completion,
+						     remain);
+
+		spin_lock_irq(&priv->irq_status_lock);
+		if (status_mask & priv->irq_status) {
+			*res_status = status_mask & priv->irq_status;
+			priv->irq_status &= ~status_mask;
+			spin_unlock_irq(&priv->irq_status_lock);
+			return 0;
+		}
+		spin_unlock_irq(&priv->irq_status_lock);
+
+	} while (remain > 0);
+
+	return -ETIMEDOUT;
+}
+
+/*
+ * read a page using DMA.
+ */
+static int dnl_read_page_raw(struct nand_chip *nand,
+			     u8 *buf, int oob_required, int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	u32 status;
+
+	dma_sync_single_for_device(&priv->dev->dev, priv->read_buf_dma,
+				   priv->read_buf_size, DMA_FROM_DEVICE);
+
+	dnl_enable_dma(priv);
+	dnl_setup_dma(priv, page, DNL_E_DMA_READ);
+
+	if (dnl_wait_for_mask(priv,
+			      DNL_INT_DMA_DATA_CMD_COMPLETE |
+			      DNL_INT_BAD_CMD_SEQ,
+			      &status) < 0) {
+		dev_err(&priv->dev->dev, "timedout waiting for DMA.\n");
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * disable and sync dma before considering status.
+	 */
+	dnl_disable_dma(priv);
+	dma_sync_single_for_cpu(&priv->dev->dev, priv->read_buf_dma,
+				priv->read_buf_size, DMA_FROM_DEVICE);
+
+	if (status & DNL_INT_BAD_CMD_SEQ) {
+		dev_err(&priv->dev->dev, "controller reported a bad command "
+			"sequence.\n");
+		return -EIO;
+	}
+
+	memcpy(buf, priv->read_buf, mtd->writesize);
+	if (oob_required)
+		memcpy(nand->oob_poi, priv->read_buf + mtd->writesize,
+		       mtd->oobsize);
+
+	return 0;
+}
+
+/*
+ * access oob zone using MAP01 command and no DMA.
+ */
+static int dnl_read_oob(struct nand_chip *nand, int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	u32 map_ctl;
+	u32 pos;
+	u32 *buf32;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	/*
+	 * tell the hardware to read only spare in MAP01 mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_ONLY);
+
+	/*
+	 * select the page to read oob from.
+	 */
+	map_ctl = DNL_MAP_01_MASK | page;
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	/*
+	 * read oob.
+	 */
+	buf32 = (u32*)nand->oob_poi;
+	for (pos = 0; pos < mtd->oobsize; pos += 4)
+		buf32[pos / 4] = dnl_mem_readl(priv, DNL_MAP_DATA_REG);
+
+	/*
+	 * ok, we already have the data in nand->oob_poi, so I guess
+	 * this is in the original driver just to be sure that we have
+	 * not read crap from the controller.
+	 */
+	if (dnl_wait_for_mask(priv, DNL_INT_LOAD_COMPLETE, &status) < 0) {
+		dev_err(&priv->dev->dev, "timeouted waiting for oob load "
+			"completion.\n");
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * switch back to MAIN + SPARE mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_AND_MAIN);
+
+	return 0;
+}
+
+/*
+ * write oob zone of given page. use MAP01 command, no DMA.
+ */
+static int dnl_write_oob(struct nand_chip *nand, int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	u32 map_ctl;
+	u32 *buf32;
+	u32 pos;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	/*
+	 * tell the hardware to read only spare in MAP01 mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_ONLY);
+
+	/*
+	 * select the page to write oob from.
+	 */
+	map_ctl = DNL_MAP_01_MASK | page;
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	/*
+	 * write the oob data to the controller.
+	 */
+	buf32 = (u32*)nand->oob_poi;
+	for (pos = 0; pos < mtd->oobsize; pos += 4)
+		dnl_mem_writel(priv, buf32[pos / 4], DNL_MAP_DATA_REG);
+
+	if (dnl_wait_for_mask(priv,
+			      DNL_INT_PROGRAM_COMPLETE |
+			      DNL_INT_PROGRAM_FAIL,
+			      &status) < 0) {
+		dev_err(&priv->dev->dev, "timeouted waiting for OOB program.\n");
+		return -ETIMEDOUT;
+	}
+
+
+	/*
+	 * switch back to MAIN + SPARE mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_AND_MAIN);
+
+	if (status & DNL_INT_PROGRAM_FAIL) {
+		dev_err(&priv->dev->dev, "controller reported a bad OOB program.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * issue an erase command using MAP10 command and wait for command
+ * completion.
+ */
+static int dnl_erase(struct nand_chip *nand, unsigned int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	u32 map_ctl;
+	u32 data;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	map_ctl = DNL_MAP_10_MASK | page;
+	data = DNL_MAP10_ERASE_COMMAND;
+	dnl_map_write(priv, data, map_ctl);
+
+	if (dnl_wait_for_mask(priv,
+			      DNL_INT_ERASE_FAILED | DNL_INT_ERASE_COMPLETE,
+			      &status) < 0) {
+		dev_err(&priv->dev->dev, "timeouted waiting for erase on page "
+			"%u.\n", page);
+		return NAND_STATUS_FAIL;
+	}
+
+	if (status & DNL_INT_ERASE_FAILED) {
+		dev_err(&priv->dev->dev, "controller reported erase failed on "
+			"block %i\n", page);
+		return NAND_STATUS_FAIL;
+	}
+
+	return 0;
+}
+
+/*
+ * start a page write, use DMA.
+ */
+static int dnl_write_page_raw(struct nand_chip *nand,
+			      const u8 *buf, int oob_required, int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	u32 status;
+
+	if (!oob_required)
+		dnl_set_transfer_mode(priv, page, DNL_XFER_MAIN_ONLY);
+	else
+		dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_AND_MAIN);
+
+	/*
+	 * build buffer for DMA with oob tightly following data.
+	 */
+	memcpy(priv->read_buf, buf, mtd->writesize);
+	if (oob_required)
+		memcpy(priv->read_buf + mtd->writesize, nand->oob_poi,
+		       mtd->oobsize);
+
+	dma_sync_single_for_device(&priv->dev->dev, priv->read_buf_dma,
+				   priv->read_buf_size, DMA_TO_DEVICE);
+
+	dnl_clear_all_interrupts(priv);
+	dnl_enable_dma(priv);
+	dnl_setup_dma(priv, page, DNL_E_DMA_PROGRAM);
+
+	if (dnl_wait_for_mask(priv,
+			      DNL_INT_DMA_DATA_CMD_COMPLETE |
+			      DNL_INT_PROGRAM_FAIL |
+			      DNL_INT_BAD_CMD_SEQ,
+			      &status) < 0) {
+		dev_err(&priv->dev->dev, "timedout waiting for program completion "
+		       "on page %u\n", page);
+		return -1;
+	}
+
+	dnl_disable_dma(priv);
+	dma_sync_single_for_cpu(&priv->dev->dev, priv->read_buf_dma,
+				priv->read_buf_size, DMA_TO_DEVICE);
+
+	if (status & DNL_INT_PROGRAM_FAIL) {
+		dev_err(&priv->dev->dev,  "controller reported a program failure "
+			"on page %u\n", page);
+		return -1;
+	}
+
+	if (status & DNL_INT_BAD_CMD_SEQ) {
+		dev_err(&priv->dev->dev, "controller reported a bad command "
+			"sequence.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+#define CLK_X		5000
+#define CLK_MULTI	4
+
+/*
+ * copied from spectra driver, should yield the same timings.
+ */
+static int denali_setup_interface(struct nand_chip *nand, int chipnr,
+				  const struct nand_interface_config *conf)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	const struct nand_sdr_timings *timings;
+	u16 en_lo, en_hi;
+	u16 acc_clks;
+	u16 dv_window = 0;
+	u16 addr_2_data;
+	u16 re_2_we;
+	u16 re_2_re;
+	u16 we_2_re;
+	u16 cs_cnt;
+
+	timings = nand_get_sdr_timings(conf);
+	if (IS_ERR(timings))
+		return PTR_ERR(timings);
+
+	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
+		return 0;
+
+	en_lo = DIV_ROUND_UP(timings->tRP_min, CLK_X);
+	en_hi = DIV_ROUND_UP(timings->tREH_min, CLK_X);
+
+	if (en_hi * CLK_X < timings->tREH_min + 2000)
+		++en_hi;
+	if (CLK_X * (en_lo + en_hi) < timings->tRC_min + 2000)
+		en_lo += DIV_ROUND_UP(timings->tRC_min - (en_lo + en_hi) * CLK_X,
+				  CLK_X);
+
+	if (en_lo + en_hi < CLK_MULTI)
+		en_lo += CLK_MULTI - en_lo - en_hi;
+
+	while (1) {
+		u16 data_invalid_rhoh, data_invalid_rloh, data_invalid;
+
+		data_invalid_rhoh = en_lo * CLK_X + timings->tRHOH_min;
+		data_invalid_rloh = (en_lo + en_hi) * CLK_X + timings->tRLOH_min;
+		data_invalid = min(data_invalid_rhoh, data_invalid_rloh);
+
+		dv_window = data_invalid - timings->tREA_max;
+		if (dv_window >= 8000)
+			break;
+		++en_lo;
+	}
+
+	acc_clks = DIV_ROUND_UP(timings->tREA_max, CLK_X);
+	while (acc_clks * CLK_X - timings->tREA_max < 3000)
+		++acc_clks;
+
+	addr_2_data = DIV_ROUND_UP(timings->tADL_min, CLK_X);
+	re_2_we = DIV_ROUND_UP(timings->tRHW_min, CLK_X);
+	re_2_re = DIV_ROUND_UP(timings->tRHZ_max, CLK_X);
+	we_2_re = DIV_ROUND_UP(timings->tWHR_min, CLK_X);
+	cs_cnt = DIV_ROUND_UP(timings->tCS_min - timings->tRP_min, CLK_X);
+	if (cs_cnt == 0)
+		cs_cnt = 1;
+
+	if (timings->tCEA_max)
+		while (cs_cnt * CLK_X + timings->tREA_max < timings->tCEA_max)
+			cs_cnt++;
+
+	/*
+	 * apply calculated timings.
+	 */
+	dnl_reg_writel(priv, acc_clks, DNL_ACC_CLKS_REG);
+	dnl_reg_writel(priv, re_2_we, DNL_RE_2_WE_REG);
+	dnl_reg_writel(priv, re_2_re, DNL_RE_2_RE_REG);
+	dnl_reg_writel(priv, we_2_re, DNL_WE_2_RE_REG);
+	dnl_reg_writel(priv, addr_2_data, DNL_ADDR_2_DATA_REG);
+	dnl_reg_writel(priv, en_lo, DNL_EN_LO_CNT_REG);
+	dnl_reg_writel(priv, en_hi, DNL_EN_HI_CNT_REG);
+	dnl_reg_writel(priv, cs_cnt, DNL_CS_SETUP_CNT_REG);
+
+	return 0;
+}
+
+static void denali_exec_in(struct denali_nand_priv *priv, u32 type,
+			   u8 *buf, unsigned int len)
+{
+	u32 map_ctl;
+	int i;
+
+	map_ctl = DNL_MAP_11_MASK;
+	map_ctl |= priv->chip_num << DNL_CHIP_SHIFT;
+	map_ctl |= type;
+
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	for (i = 0; i < len; ++i)
+		buf[i] = dnl_mem_readl(priv, DNL_MAP_DATA_REG);
+}
+
+static void denali_exec_out(struct denali_nand_priv *priv, u32 type,
+			    const u8 *buf, unsigned int len)
+{
+	u32 map_ctl;
+	int i;
+
+	map_ctl = DNL_MAP_11_MASK;
+	map_ctl |= (priv->chip_num << DNL_CHIP_SHIFT);
+	map_ctl |= type;
+
+	for (i = 0; i < len; i++)
+		dnl_map_write(priv, buf[i], map_ctl);
+}
+
+static int denali_exec_instr(struct nand_chip *nand,
+			     const struct nand_op_instr *instr)
+{
+	struct denali_nand_priv *priv = nand->priv;
+
+	switch (instr->type) {
+	case NAND_OP_CMD_INSTR:
+		denali_exec_out(priv, DNL_MAP_11_CMD_MASK,
+				&instr->ctx.cmd.opcode, 1);
+		return 0;
+	case NAND_OP_ADDR_INSTR:
+		denali_exec_out(priv, DNL_MAP_11_ADDR_MASK,
+				instr->ctx.addr.addrs,
+				instr->ctx.addr.naddrs);
+		return 0;
+	case NAND_OP_DATA_IN_INSTR:
+		denali_exec_in(priv, DNL_MAP_11_DATA_MASK,
+			       instr->ctx.data.buf.in,
+			       instr->ctx.data.len);
+		return 0;
+	case NAND_OP_DATA_OUT_INSTR:
+		denali_exec_out(priv, DNL_MAP_11_DATA_MASK,
+				instr->ctx.data.buf.out,
+				instr->ctx.data.len);
+		return 0;
+	case NAND_OP_WAITRDY_INSTR:
+		return nand_soft_waitrdy(nand,
+					 instr->ctx.waitrdy.timeout_ms);
+	default:
+		WARN_ONCE(1, "unsupported NAND instruction type: %d\n",
+			  instr->type);
+
+		return -EINVAL;
+	}
+}
+
+static int dnl_reset_bank(struct denali_nand_priv *priv)
+{
+	u32 reg;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	/*
+	 * reset controller.
+	 */
+	reg = dnl_reg_readl(priv, DNL_DEVICE_RESET_REG);
+	reg |= (1 << priv->chip_num);
+	dnl_reg_writel(priv, reg, DNL_DEVICE_RESET_REG);
+
+	/*
+	 * wait for reset completion.
+	 */
+	if (dnl_wait_for_mask(priv, DNL_INT_RESET_DONE | DNL_INT_WDOG_TIMEOUT,
+			      &status) < 0) {
+		dev_err(&priv->dev->dev, "timeouted waiting for device reset.\n");
+		return -ETIMEDOUT;
+	}
+
+	if (status & DNL_INT_WDOG_TIMEOUT) {
+		dev_err(&priv->dev->dev, "internal hardware watchdog "
+			"triggered.\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int denali_exec_op(struct nand_chip *nand,
+			  const struct nand_operation *op, bool check_only)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	const struct nand_op_instr *instr;
+	int i, ret;
+
+	if (check_only || !op->ninstrs)
+		return 0;
+
+	/*
+	 * intercept RESET & ERASE command
+	 */
+	instr = &op->instrs[0];
+	if (instr->type == NAND_OP_CMD_INSTR) {
+		switch (instr->ctx.cmd.opcode) {
+		case NAND_CMD_RESET:
+			return dnl_reset_bank(priv);
+
+		case NAND_CMD_ERASE1:
+		{
+			const struct nand_op_addr_instr *addr;
+			unsigned int page;
+			int i;
+
+			BUG_ON(op->ninstrs != 4);
+			BUG_ON(op->instrs[1].type != NAND_OP_ADDR_INSTR);
+			BUG_ON(op->instrs[2].type != NAND_OP_CMD_INSTR);
+			BUG_ON(op->instrs[2].ctx.cmd.opcode != NAND_CMD_ERASE2);
+			BUG_ON(op->instrs[3].type != NAND_OP_WAITRDY_INSTR);
+
+			addr = &op->instrs[1].ctx.addr;
+			page = 0;
+			for (i = 0; i < addr->naddrs; i++)
+				page |= addr->addrs[i] << (8 * i);
+
+			return dnl_erase(nand, page);
+		}
+		}
+	}
+
+	for (i = 0; i < op->ninstrs; i++) {
+		ret = denali_exec_instr(nand, &op->instrs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_FBX6HD
+extern int fbx6hd_board_ecc_level;
+static inline bool bch_ecc_needed(void)
+{
+	if (ecc_strength)
+		return ecc_strength > 1;
+	else
+		return fbx6hd_board_ecc_level > 1;
+}
+#else
+static inline bool bch_ecc_needed(void)
+{
+	return ecc_strength > 1;
+}
+#endif
+
+static int denali_attach_chip(struct nand_chip *nand)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	struct nand_ecc_ctrl *ecc = &nand->ecc;
+
+	if (bch_ecc_needed()) {
+		ecc->engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+		ecc->algo = NAND_ECC_ALGO_BCH;
+		ecc->size = 512;
+		ecc->strength = ecc_strength ? : 4;
+		dev_info(&priv->dev->dev,
+			 "using BCH ECC code, strength %d.\n",
+			 ecc->strength);
+	} else {
+		ecc->engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
+		ecc->algo = NAND_ECC_ALGO_HAMMING;
+		dev_info(&priv->dev->dev,
+			 "using Hamming ECC code.\n");
+	}
+
+	nand->ecc.read_page_raw = dnl_read_page_raw;
+	nand->ecc.write_page_raw = dnl_write_page_raw;
+	nand->ecc.read_oob = dnl_read_oob;
+	nand->ecc.write_oob = dnl_write_oob;
+
+	return 0;
+}
+
+static const struct nand_controller_ops denali_controller_ops = {
+	.attach_chip		= denali_attach_chip,
+	.exec_op		= denali_exec_op,
+	.setup_interface	= denali_setup_interface,
+};
+
+static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int err;
+	struct mtd_info *mtd;
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+
+	err = pci_enable_device(dev);
+	if (err) {
+		dev_err(&dev->dev, "unable to enable pci device: %i.\n", err);
+		return err;
+	}
+
+	priv = devm_kzalloc(&dev->dev, sizeof (*priv), GFP_KERNEL);
+	if (!priv) {
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+	dev_set_drvdata(&dev->dev, priv);
+	priv->dev = dev;
+	nand_controller_init(&priv->controller);
+	priv->controller.ops = &denali_controller_ops;
+
+	/*
+	 * mem zone is on the first pci resource, map xx access is done here.
+	 */
+	priv->mem_phys = pci_resource_start(dev, 0);
+	priv->mem_size = pci_resource_end(dev, 0) - priv->mem_phys + 1;
+
+	/*
+	 * registers are on the second pci resource.
+	 */
+	priv->regs_phys = pci_resource_start(dev, 1);
+	priv->regs_size = pci_resource_end(dev, 1) - priv->regs_phys + 1;
+
+	priv->mem = devm_ioremap(&dev->dev, priv->mem_phys, priv->mem_size);
+	if (!priv->mem) {
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+
+	priv->regs = devm_ioremap(&dev->dev, priv->regs_phys, priv->regs_size);
+	if (!priv->regs) {
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+
+	nand = devm_kzalloc(&dev->dev, sizeof (*nand), GFP_KERNEL);
+	if (!nand) {
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+
+	nand->controller = &priv->controller;
+	nand->priv = priv;
+	nand->options |=
+		NAND_NO_RNDOUT |
+		NAND_USES_DMA |
+		NAND_NO_SUBPAGE_WRITE;
+	nand->buf_align = 16;
+
+	mtd = nand_to_mtd(nand);
+	mtd->priv = nand;
+	mtd->dev.parent = &dev->dev;
+	priv->mtd = mtd;
+	mtd->owner = THIS_MODULE;
+
+	/*
+	 * enable prefetch on page read, to speed up things.
+	 */
+	dnl_reg_writel(priv, 1, DNL_PREFETCH_MODE);
+
+	/*
+	 * disable ECC verification/generation on page read/write.
+	 */
+	dnl_reg_writel(priv, 0, DNL_ECC_ENABLE_REG);
+
+	err = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
+	if (err) {
+		dev_err(&priv->dev->dev, "32bit dma not supported.\n");
+		goto out_disable_device;
+	}
+
+	/*
+	 * allocate read buffer: size should be main size + oob
+	 * size. we do not have the mtd fields populated yet with
+	 * these values, but controller registers do already have them
+	 * populated.
+	 */
+	priv->read_buf_size = dnl_reg_readl(priv, DNL_MAIN_SIZE_REG) +
+		dnl_reg_readl(priv, DNL_SPARE_SIZE_REG);
+	priv->read_buf = dma_alloc_noncoherent(&dev->dev,
+					       DENALI_NAND_DMA_BUF_SIZE,
+					       &priv->read_buf_dma,
+					       DMA_TO_DEVICE, GFP_KERNEL);
+	if (!priv->read_buf) {
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+
+	/*
+	 * Setup IRQs
+	 */
+	spin_lock_init(&priv->irq_status_lock);
+	init_completion(&priv->irq_completion);
+	dnl_setup_irq(priv);
+	err = devm_request_irq(&dev->dev, dev->irq, dnl_irq, IRQF_SHARED,
+			       "denali-nand", priv);
+	if (err) {
+		dev_err(&priv->dev->dev, "unable to request irq%d (%d).\n",
+			dev->irq, err);
+		goto out_free_dma;
+	}
+
+	dnl_interrupt_global_enable(priv, 1);
+	dnl_reset_bank(priv);
+
+	/*
+	 * FIXME: 4 chips can be supported
+	 */
+	err = nand_scan(nand, 1);
+        if (err) {
+		dev_err(&priv->dev->dev, "nand scan failed failed");
+		goto out_free_dma;
+	}
+
+	mtd->name = "denali_nand";
+	err = mtd_device_parse_register(mtd, parts_parsers, 0, NULL, 0);
+	if (err) {
+		dev_err(&priv->dev->dev, "unable to register MTD dev.\n");
+		goto out_free_dma;
+	}
+
+	return 0;
+
+out_free_dma:
+	dma_free_noncoherent(&dev->dev, DENALI_NAND_DMA_BUF_SIZE,
+			     priv->read_buf, priv->read_buf_dma, DMA_TO_DEVICE);
+out_disable_device:
+	pci_disable_device(dev);
+	return err;
+}
+
+static void denali_pci_remove(struct pci_dev *dev)
+{
+	struct denali_nand_priv *priv;
+
+	priv = dev_get_drvdata(&dev->dev);
+
+	mtd_device_unregister(priv->mtd);
+	dnl_interrupt_global_enable(priv, 0);
+	dma_free_noncoherent(&dev->dev, DENALI_NAND_DMA_BUF_SIZE,
+			     priv->read_buf, priv->read_buf_dma, DMA_TO_DEVICE);
+	pci_disable_device(dev);
+}
+
+const struct pci_device_id denali_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0701) },
+	{ 0, },
+};
+
+struct pci_driver	denali_nand_pci_driver =
+{
+	.name		= "denali_nand",
+	.id_table	= denali_pci_table,
+	.probe		= denali_pci_probe,
+	.remove		= denali_pci_remove,
+};
+
+static int __init denali_nand_init(void)
+{
+	int err;
+
+	err = pci_register_driver(&denali_nand_pci_driver);
+	if (err) {
+		printk(KERN_ERR PFX "pci_register_driver failed: %i.\n", err);
+		return err;
+	}
+	return 0;
+}
+
+static void __exit denali_nand_exit(void)
+{
+	pci_unregister_driver(&denali_nand_pci_driver);
+}
+
+module_init(denali_nand_init);
+module_exit(denali_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nicolas Schichan <nschichan@freebox.fr>");
+MODULE_DESCRIPTION("Denali NAND driver");
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/drivers/mtd/nand/raw/denali_nand.h	2022-09-28 14:08:50.160737533 +0200
@@ -0,0 +1,173 @@
+#ifndef __DENALI_NAND_H
+# define __DENALI_NAND_H
+
+#include <linux/completion.h>
+#include <linux/list.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+
+struct denali_nand_priv
+{
+	struct nand_controller controller;
+	int		chip_num;
+	unsigned long	regs_phys;
+	unsigned long	regs_size;
+
+	unsigned long	mem_phys;
+	unsigned long	mem_size;
+
+	void __iomem	*regs;
+	void __iomem	*mem;
+
+	u8		*read_buf;
+	int		read_buf_size;
+	int		read_buf_offset;
+
+	dma_addr_t	read_buf_dma;
+
+	struct pci_dev *dev;
+	struct mtd_info	*mtd;
+
+	/*
+	 * signals interrupts from dnl_irq() to dnl_wait_for_mask().
+	 */
+	struct completion irq_completion;
+
+	/*
+	 * serialize accesses to irq_status between dnl_irq() and
+	 * dnl_wait_for_mask()/dnl_clear_all_interrupts().
+	 */
+	spinlock_t irq_status_lock;
+
+	u32 irq_status;
+};
+
+#define DNL_DEVICE_RESET_REG		0x0
+
+#define DNL_XFER_SPARE_REG		(0x4 * 4)
+
+#define DNL_CE_REG			(0x34 * 4)
+#define  DNL_CE_DISABLE			(1 << 0)
+
+#define DNL_RB_PIN_ENABLED_REG		(0x18 * 4)
+# define DNL_RB_PIN_B0_EN		(1 << 0)
+# define DNL_RB_PIN_B1_EN		(1 << 1)
+# define DNL_RB_PIN_B2_EN		(1 << 2)
+# define DNL_RB_PIN_B3_EN		(1 << 3)
+
+#define DNL_PREFETCH_MODE		(0x30 * 4)
+#define DNL_ECC_ENABLE_REG		(0x38 * 4)
+
+#define DNL_INT_ENABLE_REG		(0x3c * 4)
+# define DNL_INT_ENABLE			(1 << 0)
+
+#define DNL_MAIN_SIZE_REG		(0x5c * 4)
+#define DNL_SPARE_SIZE_REG		(0x60 * 4)
+
+#define DNL_0_INTR_STATUS_REG		(0x104 * 4)
+#define DNL_0_INTR_EN_REG		(0x108 * 4)
+#define DNL_0_PAGE_COUNT_REG		(0x10c * 4)
+#define DNL_0_ERR_ADDR_REG		(0x110 * 4)
+#define DNL_0_ERR_BLOCK_REG		(0x114 * 4)
+
+#define DNL_1_INTR_STATUS_REG		(0x118 * 4)
+#define DNL_1_INTR_EN_REG		(0x11c * 4)
+#define DNL_1_PAGE_COUNT_REG		(0x120 * 4)
+#define DNL_1_ERR_ADDR_REG		(0x124 * 4)
+#define DNL_1_ERR_BLOCK_REG		(0x128 * 4)
+
+#define DNL_2_INTR_STATUS_REG		(0x12c * 4)
+#define DNL_2_INTR_EN_REG		(0x130 * 4)
+#define DNL_2_PAGE_COUNT_REG		(0x134 * 4)
+#define DNL_2_ERR_ADDR_REG		(0x138 * 4)
+#define DNL_2_ERR_BLOCK_REG		(0x13c * 4)
+
+#define DNL_3_INTR_STATUS_REG		(0x140 * 4)
+#define DNL_3_INTR_EN_REG		(0x144 * 4)
+#define DNL_3_PAGE_COUNT_REG		(0x148 * 4)
+#define DNL_3_ERR_ADDR_REG		(0x14c * 4)
+#define DNL_3_ERR_BLOCK_REG		(0x150 * 4)
+
+/*
+ * interrupt cause bits valid for all 4 controllers.
+ */
+#define DNL_INT_DMA_DATA_CMD_COMPLETE	(1 << 2)
+#define DNL_INT_WDOG_TIMEOUT		(1 << 3)
+#define DNL_INT_PROGRAM_FAIL		(1 << 4)
+#define DNL_INT_ERASE_FAILED		(1 << 5)
+#define DNL_INT_LOAD_COMPLETE		(1 << 6)
+#define DNL_INT_PROGRAM_COMPLETE	(1 << 7)
+#define DNL_INT_ERASE_COMPLETE		(1 << 8)
+#define DNL_INT_BAD_CMD_SEQ		(1 << 11)
+#define DNL_INT_ACT			(1 << 12)
+#define DNL_INT_RESET_DONE		(1 << 13)
+
+
+#define DNL_SKIP_BYTE_REG		(0x8c * 4)
+#define DNL_SPACE_AREA_MARKER_REG	(0x90 * 4)
+
+#define DNL_MANUFACTURER_REG		(0xc0 * 4)
+
+#define DNL_PAGE_SIZE			(0xd4 * 4)
+#define DNL_SPARE_SIZE			(0xd8 * 4)
+
+/*
+ * timing configuration registers
+ */
+#define DNL_WE_2_RE_REG			(0x40 * 4)
+#define DNL_ADDR_2_DATA_REG		(0x44 * 4)
+#define DNL_RE_2_WE_REG			(0x48 * 4)
+#define DNL_ACC_CLKS_REG		(0x4c * 4)
+
+#define DNL_EN_LO_CNT_REG		(0x7c * 4)
+#define DNL_EN_HI_CNT_REG		(0x80 * 4)
+#define DNL_CS_SETUP_CNT_REG		(0x88 * 4)
+#define DNL_RE_2_RE_REG			(0xa4 * 4)
+
+#define DNL_XFER_MODE			(0x100 * 4)
+
+#define DNL_DMA_ENABLE			(0x1c0 * 4)
+
+/*
+ * map xx indirect read/write accessors
+ */
+#define DNL_MAP_01_MASK		0x04000000
+#define DNL_MAP_10_MASK		0x08000000
+#define DNL_MAP_11_MASK		0x0c000000
+
+#define DNL_CHIP_MASK		0x03000000
+#define DNL_CHIP_SHIFT		(24)
+#define DNL_MAP_11_CMD_MASK	(0x0)
+#define DNL_MAP_11_ADDR_MASK	(0x1)
+#define DNL_MAP_11_DATA_MASK	(0x2)
+
+#define DNL_MAP_CTL_REG		0x00
+#define DNL_MAP_DATA_REG	0x10
+
+#define DNL_XFER_SPARE_ONLY		0x41
+#define DNL_XFER_MAIN_ONLY		0x42
+#define DNL_XFER_SPARE_AND_MAIN		0x43
+
+#define DNL_MAP10_READAHEAD_ONCE	0x2001
+
+enum {
+	DNL_E_DMA_READ,
+	DNL_E_DMA_PROGRAM,
+};
+
+#define DNL_MAP10_ERASE_COMMAND		0x1
+
+/*
+ * DMA command sequence.
+ */
+#define DNL_MAP10_DMA_READ_PAGE		0x2001
+#define DNL_MAP10_DMA_WRITE_PAGE	0x2101
+#define DNL_MAP10_DMA_SET_ADDR_HI	0x2200
+#define DNL_MAP10_DMA_SET_ADDR_LO	0x2300
+#define DNL_MAP10_DMA_SET_PARAMS	0x2400
+
+#define DNL_DMA_PARAM_GEN_INT		(1 << 16)
+#define DNL_DMA_BURST_64		(0x40 << 8)
+
+#endif /* !__DENALI_NAND_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/drivers/mtd/parsers/fbx6hd-mtdparts.c	2023-03-06 15:53:59.952702424 +0100
@@ -0,0 +1,281 @@
+/*
+ * MTD parser for fbx6hd, just return a static mtd partition
+ * list. optionally set all partitions to read/write if requested by
+ * config.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
+
+#define PFX	"fbx6hd-mtdparts: "
+
+#define SZ_1M	(1 << 20)
+
+#define MBR_BLOCKS	(8)
+#define CEFDK_S1_BLOCKS	(8)
+#define CEFDK_S2_BLOCKS	(8 * 4)
+#define SERIAL_BLOCKS	(16)
+#define KEYS_BLOCKS	(8)
+#define FIELD_KEYS_BLOCKS	(8)
+
+
+#define BANK0_SIZE	(18 * SZ_1M)
+#define CONFIG_SIZE	(7 * SZ_1M)
+#define DATA_SIZE	(72 * SZ_1M)
+#define NEWBANK0_SIZE	BANK0_SIZE
+enum {
+	E_PART_ALL,
+	E_PART_MBR,
+	E_PART_CEFDK_S1_B0,
+	E_PART_CEFDK_S1_B1,
+	E_PART_CEFDK_S2_B0,
+	E_PART_CEFDK_S2_B1,
+	E_PART_SERIALINFO,
+	E_PART_KEYS,
+	E_PART_BANK0,
+	E_PART_CONFIG,
+	E_PART_BANK1,
+	E_PART_FIELD_KEYS,
+	E_PART_DATA,
+	E_PART_NEWBANK0,
+};
+
+static struct mtd_partition fbx6hd_nand_partitions[] = {
+	[E_PART_ALL] = {
+		.name		= "all",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_MBR] = {
+		.name		= "mbr",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CEFDK_S1_B0] = {
+		.name		= "cefdk-stage1-bank0",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CEFDK_S1_B1] = {
+		.name		= "cefdk-stage1-bank1",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_CEFDK_S2_B0] = {
+		.name		= "cefdk-stage2-bank0",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CEFDK_S2_B1] = {
+		.name		= "cefdk-stage2-bank1",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_SERIALINFO] = {
+		.name		= "serial",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_KEYS] = {
+		.name		= "keys",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_BANK0] = {
+		.name		= "bank0",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CONFIG] = {
+		.name		= "config",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_BANK1] = {
+		.name		= "bank1",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_FIELD_KEYS] = {
+		.name		= "field_keys",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_DATA] = {
+		.name		= "data",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_NEWBANK0] = {
+		.name		= "newbank0",
+		.offset		= -1,
+		.size		= -1,
+	},
+};
+
+static int fbx6hd_parse_mtd_partitions(struct mtd_info *master,
+				       const struct mtd_partition **pparts,
+				       struct mtd_part_parser_data *pdata)
+{
+	struct mtd_partition *bank1;
+	struct mtd_partition *newbank0;
+	struct mtd_partition *field_keys;
+	struct mtd_partition *cur_part;
+	u32 cur_offset;
+	u32 bank1_start;
+
+	/*
+	 * make all partition cover the whole flash.
+	 */
+	cur_part = &fbx6hd_nand_partitions[E_PART_ALL];
+	cur_part->offset = 0;
+	cur_part->size = master->size;
+
+	/*
+	 * start filling partition offset/size one by one.
+	 */
+	cur_offset = 0;
+	cur_part = &fbx6hd_nand_partitions[E_PART_MBR];
+	cur_part->offset = cur_offset;
+	cur_part->size = MBR_BLOCKS * master->erasesize;
+
+	/*
+	 * CEFDK stage1 partitions
+	 */
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S1_B0];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S1_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S1_B1];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S1_BLOCKS * master->erasesize;
+
+	/*
+	 * CEFDK stage2 partitions
+	 */
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S2_B0];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S2_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S2_B1];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S2_BLOCKS * master->erasesize;
+
+	/*
+	 * Freebox specific
+	 */
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_SERIALINFO];
+	cur_part->offset = cur_offset;
+	cur_part->size = SERIAL_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_KEYS];
+	cur_part->offset = cur_offset;
+	cur_part->size = KEYS_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_BANK0];
+	cur_part->offset = cur_offset;
+	cur_part->size = BANK0_SIZE;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CONFIG];
+	cur_part->offset = cur_offset;
+	cur_part->size = CONFIG_SIZE;
+
+	bank1_start = cur_offset + cur_part->size;
+
+	/*
+	 * Config and newbank0 are added starting from the end of the flash
+	 */
+	cur_offset = master->size - NEWBANK0_SIZE;
+	cur_part = &fbx6hd_nand_partitions[E_PART_NEWBANK0];
+	cur_part->offset = cur_offset;
+	cur_part->size = NEWBANK0_SIZE;
+
+	cur_offset -= DATA_SIZE;
+	cur_part = &fbx6hd_nand_partitions[E_PART_DATA];
+	cur_part->offset = cur_offset;
+	cur_part->size = DATA_SIZE;
+
+	cur_offset -= FIELD_KEYS_BLOCKS * master->erasesize;
+	cur_part = &fbx6hd_nand_partitions[E_PART_FIELD_KEYS];
+	cur_part->offset = cur_offset;
+	cur_part->size = FIELD_KEYS_BLOCKS * master->erasesize;
+
+	/*
+	 * Bank1 fills the space between config and data partitions
+	 */
+	cur_part = &fbx6hd_nand_partitions[E_PART_BANK1];
+	cur_part->offset = bank1_start;
+	cur_part->size = cur_offset - bank1_start;
+
+	/*
+	 * some basic sanity checks before to avoid botched partitiont
+	 * table.
+	 */
+	bank1 = &fbx6hd_nand_partitions[E_PART_BANK1];
+	newbank0 = &fbx6hd_nand_partitions[E_PART_NEWBANK0];
+	field_keys = &fbx6hd_nand_partitions[E_PART_FIELD_KEYS];
+	if (bank1->offset > master->size) {
+		printk(KERN_CRIT PFX "bank1 partition starts after flash "
+		       "end: use a bigger flash.\n");
+		return -ENOSPC;
+	}
+
+	if (newbank0->offset < bank1->offset) {
+		printk(KERN_CRIT PFX "newbank0 starts before bank1: use a "
+		       "bigger flash.\n");
+		return -ENOSPC;
+	}
+
+	if (field_keys->offset < bank1->offset) {
+		printk(KERN_CRIT PFX "field_keys partition starts before "
+		       "bank1: use a bigger flash.\n");
+		return -ENOSPC;
+	}
+
+	printk(KERN_INFO PFX "%llu MiB available for bank1.\n",
+	       bank1->size >> 20);
+
+#ifdef CONFIG_MTD_FBX6HD_PARTS_WRITE_ALL
+	int i;
+	for (i = 0; i < ARRAY_SIZE(fbx6hd_nand_partitions); ++i)
+		fbx6hd_nand_partitions[i].mask_flags &= ~MTD_WRITEABLE;
+#endif
+
+	*pparts = kmemdup(fbx6hd_nand_partitions,
+			  sizeof (fbx6hd_nand_partitions), GFP_KERNEL);
+	return ARRAY_SIZE(fbx6hd_nand_partitions);
+}
+
+struct mtd_part_parser fbx6hd_mtd_parser = {
+	.owner		= THIS_MODULE,
+	.parse_fn	= fbx6hd_parse_mtd_partitions,
+	.name		= "fbx6hd-mtdparts",
+};
+
+static int __init fbx6hd_parser_init(void)
+{
+	register_mtd_parser(&fbx6hd_mtd_parser);
+	return 0;
+}
+
+module_init(fbx6hd_parser_init);
+
+
+MODULE_AUTHOR("Nicolas Schichan <nschichan@freebox.fr>");
+MODULE_LICENSE("GPL");
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158./Makefile linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158/Makefile
--- linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158/Makefile	2023-11-29 17:07:10.604990042 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_BCM63158_SF2) 		+= sf2/
+obj-$(CONFIG_BCM63158_ENET_RUNNER) 	+= enet/
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158./enet/Makefile linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158/enet/Makefile
--- linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158./enet/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158/enet/Makefile	2020-02-08 00:30:20.476492050 +0100
@@ -0,0 +1,11 @@
+obj-$(CONFIG_BCM63158_ENET_RUNNER) 	+= bcm63158_enet_runner.o
+
+bcm63158_enet_runner-y	:= \
+	ethtool.o \
+	main.o \
+	port_unimac.o \
+	port_xport.o \
+	port_xport_serdes.o \
+	port_xport_epon.o \
+	port_xport_epon_dbg.o \
+	port_xport_xlmac.o
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158./sf2/Makefile linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158/sf2/Makefile
--- linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158./sf2/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63158/sf2/Makefile	2020-08-18 11:07:48.126426795 +0200
@@ -0,0 +1,4 @@
+obj-$(CONFIG_BCM63158_SF2) 		+= bcm63158_sf2.o
+
+bcm63158_sf2-y 				+= sf2_main.o sf2_fdb.o
+bcm63158_sf2-$(CONFIG_DEBUG_FS) 	+= sf2_debug.o
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63xx_enet_runner./Makefile linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63xx_enet_runner/Makefile
--- linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63xx_enet_runner./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/broadcom/bcm63xx_enet_runner/Makefile	2020-02-08 00:30:20.484492128 +0100
@@ -0,0 +1,5 @@
+obj-$(CONFIG_BCM63XX_ENET_RUNNER) 	+= bcm63xx_enet_runner_mod.o
+obj-$(CONFIG_BCM63XX_ENET_RUNNER) 	+= bcm63xx_sf2.o
+
+bcm63xx_enet_runner_mod-y 			+= bcm63xx_enet_runner.o
+bcm63xx_enet_runner_mod-$(CONFIG_DEBUG_FS) 	+= bcm63xx_enet_runner_debug.o
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx./Kconfig linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx/Kconfig
--- linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx/Kconfig	2024-01-12 13:49:04.990035575 +0100
@@ -0,0 +1,14 @@
+config IPQ95XX_ESS
+	tristate "IPQ95XX ESS driver (edma+ppe)"
+	select NET_SWITCHDEV
+	select PHYLINK
+	select MII
+
+config IPQ95XX_FBX_FF
+	bool "fastpath support for freebox boards"
+	depends on IPQ95XX_ESS
+	select IP_FFN
+	select IPV6_FFN
+	select IPV6_SIT_6RD
+	select BRIDGE
+	select FBXBRIDGE
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx./Makefile linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx/Makefile
--- linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/qualcomm/ipq95xx/Makefile	2024-01-12 13:49:04.990035575 +0100
@@ -0,0 +1,13 @@
+obj-$(CONFIG_IPQ95XX_ESS) 	+= ipq95xx_ess.o
+
+ipq95xx_ess-objs		+= \
+				clocks.o \
+				debug.o \
+				hwdesc.o \
+				fdb.o \
+				ipo.o \
+				main.o \
+				port.o \
+				port_ethtool.o \
+				port_phylink.o \
+				uniphy.o
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/wintegra./Kconfig linux-6.4-fbx/drivers/net/ethernet/wintegra/Kconfig
--- linux-6.4-fbx/drivers/net/ethernet/wintegra./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/wintegra/Kconfig	2013-12-04 14:33:20.027478990 +0100
@@ -0,0 +1,10 @@
+config NET_VENDOR_WINTEGRA
+	bool
+
+config WINTEGRA_WINPATH3_ETH
+	tristate "Wintegra Winpath3 internal mac support"
+	depends on WINTEGRA_WINPATH3
+	select NET_VENDOR_WINTEGRA
+	select NET_CORE
+	select MII
+	select PHYLIB
diff -Nruw linux-6.4-fbx/drivers/net/ethernet/wintegra./Makefile linux-6.4-fbx/drivers/net/ethernet/wintegra/Makefile
--- linux-6.4-fbx/drivers/net/ethernet/wintegra./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/ethernet/wintegra/Makefile	2013-12-04 14:33:20.027478990 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_WINTEGRA_WINPATH3_ETH) += wp3_eth.o
diff -Nruw linux-6.4-fbx/drivers/net/wireless/marvell/mwl8k_new./Makefile linux-6.4-fbx/drivers/net/wireless/marvell/mwl8k_new/Makefile
--- linux-6.4-fbx/drivers/net/wireless/marvell/mwl8k_new./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/net/wireless/marvell/mwl8k_new/Makefile	2020-06-11 10:15:40.283294476 +0200
@@ -0,0 +1,12 @@
+mwl8k_new-$(CONFIG_DEBUG_FS) += debugfs.o
+mwl8k_new-y += fw.o
+mwl8k_new-y += main.o
+mwl8k_new-y += utils.o
+
+mwl8k_new-y += svc_console.o
+mwl8k_new-y += svc_dma_test.o
+mwl8k_new-y += svc_vtty.o
+
+mwl8k_new-y += wifi_core.o
+
+obj-$(CONFIG_MWL8K_NEW)	+= mwl8k_new.o
diff -Nruw linux-6.4-fbx/drivers/platform/fbxgw7r./Kconfig linux-6.4-fbx/drivers/platform/fbxgw7r/Kconfig
--- linux-6.4-fbx/drivers/platform/fbxgw7r./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/fbxgw7r/Kconfig	2020-02-08 00:30:21.744504371 +0100
@@ -0,0 +1,6 @@
+config FBXGW7R_PLATFORM
+	bool "Freebox Gateway V7 specific drivers"
+
+config FBXGW7R_SWITCH
+	bool "Freebox Gateway V7 in kernel switch init code."
+	depends on FBXGW7R_PLATFORM
diff -Nruw linux-6.4-fbx/drivers/platform/fbxgw7r./Makefile linux-6.4-fbx/drivers/platform/fbxgw7r/Makefile
--- linux-6.4-fbx/drivers/platform/fbxgw7r./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/fbxgw7r/Makefile	2020-02-08 00:30:21.744504371 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_FBXGW7R_SWITCH)	+= fbxgw7r-switch.o
diff -Nruw linux-6.4-fbx/drivers/platform/intelce./Kconfig linux-6.4-fbx/drivers/platform/intelce/Kconfig
--- linux-6.4-fbx/drivers/platform/intelce./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/intelce/Kconfig	2022-08-30 19:20:28.623606621 +0200
@@ -0,0 +1,18 @@
+#
+# IntelCE devices configuration
+#
+
+menu "IntelCE devices"
+
+config INTELCE_GPIO
+	tristate "GPIO support"
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  IntelCE 3100/4100 GPIO support.
+
+config INTELCE_DFX
+	tristate "DFX reporting support"
+	help
+	  IntelCE 3100/4100 DFX fuse reporting support.
+
+endmenu
diff -Nruw linux-6.4-fbx/drivers/platform/intelce./Makefile linux-6.4-fbx/drivers/platform/intelce/Makefile
--- linux-6.4-fbx/drivers/platform/intelce./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/intelce/Makefile	2013-12-04 14:33:20.395478996 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_INTELCE_GPIO)	+= gpio-intelce.o
+obj-$(CONFIG_INTELCE_DFX)	+= dfx.o
diff -Nruw linux-6.4-fbx/drivers/platform/intelce./dfx.c linux-6.4-fbx/drivers/platform/intelce/dfx.c
--- linux-6.4-fbx/drivers/platform/intelce./dfx.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/intelce/dfx.c	2023-11-29 17:07:11.778325198 +0100
@@ -0,0 +1,279 @@
+/*
+ * Intel CE DFX fuse SysFS export
+ *
+ * Copyright (C) 2009, Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * 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/pci.h>
+#include <linux/io.h>
+#include <linux/sysfs.h>
+
+#define DFX_IO_SIZE	(64 * 1024)
+#define PFX		KBUILD_MODNAME
+
+#define DFX_ID_CODE	0x24
+#define DFX_SKU		0x28
+#define DFX_SN1		0x40
+#define DFX_SN2		0x44
+#define DFX_VCFG	0x64
+
+#define CW_CFG_BASE	0xA0000010
+#define DDR_SPEED	0x4
+
+#define CW_BRD_MASK	0x3
+#define CW_SEC_BOOT	7
+#define CW_VDAC_CAL	14
+
+#define DDR_SPEED_MASK	0x7
+
+static void __iomem *dfx_base;
+static void __iomem *cw_cfg_base;
+
+static ssize_t show_fuse_id_code(struct device *dev, struct device_attribute
+		      *devattr, char *buf)
+{
+	return sprintf(buf, "%04x\n",
+			ioread32(dfx_base + DFX_ID_CODE) >> 19 & 0xf);
+}
+
+static ssize_t show_sku_id(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	return sprintf(buf, "%06x\n", ioread32(dfx_base + DFX_SKU) & 0x7f);
+}
+
+static ssize_t show_dev_serial1(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	return sprintf(buf, "%08x\n", ioread32(dfx_base + DFX_SN1));
+}
+
+static ssize_t show_dev_serial2(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	return sprintf(buf, "%08x\n", ioread32(dfx_base + DFX_SN2));
+}
+
+static ssize_t show_ca_vendor_cfg(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	u32 vcfg = ioread32(dfx_base + DFX_VCFG);
+
+	return sprintf(buf, "%2x%2x\n", (vcfg >> 10) & 0xff, vcfg & 0xff);
+}
+
+static DEVICE_ATTR(fuse_id_code, S_IRUGO, show_fuse_id_code, NULL);
+static DEVICE_ATTR(sku_id, S_IRUGO, show_sku_id, NULL);
+static DEVICE_ATTR(dev_serial1, S_IRUGO, show_dev_serial1, NULL);
+static DEVICE_ATTR(dev_serial2, S_IRUGO, show_dev_serial2, NULL);
+static DEVICE_ATTR(ca_vendor_cfg, S_IRUGO, show_ca_vendor_cfg, NULL);
+
+#define CW_SHOW_ATTR(_name, _bit)					\
+static ssize_t show_##_name(struct device *dev, struct device_attribute \
+			*devattr, char *buf)				\
+{									\
+	return sprintf(buf, "%d\n", (readl(cw_cfg_base) &		\
+				(1 << _bit)) >> _bit);			\
+}									\
+static DEVICE_ATTR(_name, S_IRUGO, show_##_name, NULL);			\
+
+CW_SHOW_ATTR(trusted_mode, CW_SEC_BOOT);
+CW_SHOW_ATTR(vdac_cal, CW_VDAC_CAL);
+
+static ssize_t show_board_model(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	u32 val = readl(cw_cfg_base) & CW_BRD_MASK;
+	const char *board;
+
+	switch (val) {
+	case 0:
+		board = "GoldenBeach";
+		break;
+	case 1:
+		board = "ChesapeakeBay";
+		break;
+	case 2:
+		board = "FalconFalls";
+		break;
+	case 3:
+		board = "PowerHouseLake";
+		break;
+	default:
+		board = "unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s\n", board);
+}
+
+static DEVICE_ATTR(board_model, S_IRUGO, show_board_model, NULL);
+
+static ssize_t show_ddr_type(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	u32 speed = (readl(cw_cfg_base + DDR_SPEED) >> 6) & DDR_SPEED_MASK;
+	const char *type;
+	const char *freq;
+
+	if (speed >= 4)
+		type = "DDR2";
+	else
+		type = "DDR3";
+
+	switch (speed) {
+	case 0:
+		freq = "800";
+		break;
+	case 1:
+		freq = "1066";
+		break;
+	case 2:
+		freq = "1333";
+		break;
+	case 3:
+		freq = "1600";
+		break;
+	case 4:
+		freq = "800";
+		break;
+	default:
+		freq = "unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s (%s Mhz)\n", type, freq);
+}
+
+static DEVICE_ATTR(ddr_type, S_IRUGO, show_ddr_type, NULL);
+
+static struct attribute *intelce_dfx_attributes[] = {
+	&dev_attr_fuse_id_code.attr,
+	&dev_attr_sku_id.attr,
+	&dev_attr_dev_serial1.attr,
+	&dev_attr_dev_serial2.attr,
+	&dev_attr_ca_vendor_cfg.attr,
+	&dev_attr_trusted_mode.attr,
+	&dev_attr_vdac_cal.attr,
+	&dev_attr_board_model.attr,
+	&dev_attr_ddr_type.attr,
+	NULL
+};
+
+static const struct attribute_group intelce_dfx_group = {
+	.name = "intelce-dfx",
+	.attrs = intelce_dfx_attributes,
+};
+
+static int intelce_dfx_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *id)
+{
+	int err;
+	int bar = 0;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out;
+
+	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (err) {
+		printk(KERN_ERR PFX ": 32-bit PCI DMA addresses"
+				"not supported by the card\n");
+		goto err_out;
+	}
+
+	if (pci_resource_len(pdev, bar) < DFX_IO_SIZE) {
+		printk(KERN_ERR PFX ": Insufficient PCI resources, aborting\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_request_regions(pdev, PFX);
+	if (err) {
+		printk(KERN_ERR PFX ": could not request PCI regions\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	dfx_base = pci_iomap(pdev, bar, DFX_IO_SIZE);
+	if (!dfx_base) {
+		printk(KERN_ERR PFX ": ioremap failed for device: %s\n",
+				pci_name(pdev));
+		err = -ENOMEM;
+		goto err_release_regions;
+	}
+
+	cw_cfg_base = ioremap(CW_CFG_BASE, 0x7);
+	if (!cw_cfg_base) {
+		printk(KERN_ERR PFX ": ioremap for CW[] failed\n");
+		err = -ENOMEM;
+		goto err_iounmap;
+	}
+
+	pci_set_drvdata(pdev, dfx_base);
+
+	err = sysfs_create_group(&pdev->dev.kobj, &intelce_dfx_group);
+	if (err) {
+		printk(KERN_ERR PFX ": unable to create sysfs group\n");
+		goto err_iounmap;
+	}
+
+	dev_info(&pdev->dev, "at 0x%p\n", dfx_base);
+
+	return 0;
+
+err_iounmap:
+	iounmap(cw_cfg_base);
+	pci_iounmap(pdev, dfx_base);
+err_release_regions:
+	pci_release_regions(pdev);
+err_out:
+	return err;
+}
+
+static void __exit intelce_dfx_remove(struct pci_dev *pdev)
+{
+	sysfs_remove_group(&pdev->dev.kobj, &intelce_dfx_group);
+	iounmap(cw_cfg_base);
+	pci_iounmap(pdev, dfx_base);
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id intelce_dfx_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6d) },
+	{ 0 }
+};
+
+static struct pci_driver intelce_dfx_driver = {
+	.name		= "intelce-dfx",
+	.id_table	= intelce_dfx_id_tbl,
+	.probe		= intelce_dfx_probe,
+	.remove		= intelce_dfx_remove,
+};
+
+static int __init intelce_dfx_init(void)
+{
+	return pci_register_driver(&intelce_dfx_driver);
+}
+
+static void __exit intelce_dfx_exit(void)
+{
+	pci_unregister_driver(&intelce_dfx_driver);
+}
+
+module_init(intelce_dfx_init);
+module_exit(intelce_dfx_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("Intel CE 3100/4100 sysfs fuse reporting");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff -Nruw linux-6.4-fbx/drivers/platform/intelce./gpio-intelce.c linux-6.4-fbx/drivers/platform/intelce/gpio-intelce.c
--- linux-6.4-fbx/drivers/platform/intelce./gpio-intelce.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/intelce/gpio-intelce.c	2023-11-29 17:07:11.778325198 +0100
@@ -0,0 +1,594 @@
+/*
+ * GPIO bus driver for the Intel CE3100/4100 SoC
+ *
+ * Copyright (C) 2009, Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/gpio/driver.h>
+#include <linux/of.h>
+
+#define DRV_NAME		"intelce-gpio"
+#define DRV_VERSION		"0.1"
+
+#define GEN3_GPIO_IO_BASE	0x1080
+#define GEN3_GPIO_IO_SIZE	0x40
+#define GEN3_NUM_GPIO_PINS	26
+
+#define NR_BUILTIN_GPIO		GEN3_NUM_GPIO_PINS
+#define GEN3_GPIO_GROUPS	4
+
+/* Starting point for the different GPIO groups on intel_gen3 */
+#define GEN3_GPIO_GROUP_ZERO    0
+#define GEN3_GPIO_GROUP_ONE     12
+#define GEN3_GPIO_GROUP_TWO     15
+#define GEN3_GPIO_GROUP_THREE   22
+
+/* GPIO Group 0 */
+#define GEN3_GPIO0_GPOUTR	0x00
+#define GEN3_GPIO0_GPOER	0x04
+#define GEN3_GPIO0_GPINR	0x08
+#define GEN3_GPIO0_GPSTR	0x0C
+#define GEN3_GPIO0_GPIT1R0	0x10
+#define GEN3_GPIO0_INT		0x14
+#define GEN3_GPIO0_GPIT1R1	0x18
+#define GEN3_GPIO0_MUX_CNTL	0x1C
+
+/* GPIO Group 1*/
+#define GEN3_GPIO1_CGEN		0x00
+#define GEN3_GPIO1_CGIO		0x04
+#define GEN3_GPIO1_CGLV		0x08
+#define GEN3_GPIO1_CGTPE	0x0C
+#define GEN3_GPIO1_CGTNE	0x10
+#define GEN3_GPIO1_CGGPE	0x14
+#define GEN3_GPIO1_CGSMI	0x18
+#define GEN3_GPIO1_CGTS		0x1C
+
+/* GPIO Group 2 */
+#define GEN3_GPIO2_CGEN		0x00
+#define GEN3_GPIO2_CGIO		0x04
+#define GEN3_GPIO2_CGLV		0x08
+#define GEN3_GPIO2_CGTPE	0x0C
+#define GEN3_GPIO2_CGTNE	0x10
+#define GEN3_GPIO2_CGGPE	0x14
+#define GEN3_GPIO2_CGSMI	0x18
+#define GEN3_GPIO2_CGTS		0x1C
+#define GEN3_GPIO2_MUX_CNTL	0x1C
+
+/* GPIO Group 3 */
+#define GEN3_GPIO3_CGEN		0x20
+#define GEN3_GPIO3_CGIO		0x24
+#define GEN3_GPIO3_CGLV		0x28
+#define GEN3_GPIO3_CGTPE	0x2C
+#define GEN3_GPIO3_CGTNE	0x30
+#define GEN3_GPIO3_CGGPE	0x34
+#define GEN3_GPIO3_CGSMI	0x38
+#define GEN3_GPIO3_CGTS		0x3C
+
+/* Controller limits */
+#define INTELCE_GPIO_IO_SIZE	256
+
+#define GEN3_TYPE_PCI		0
+#define GEN3_TYPE_IOPORT	1
+
+/* gpio adapter private structure */
+struct intelce_gpio {
+	struct gpio_chip	chip;
+	struct pci_dev		*pdev;
+	void __iomem		*base;
+	u32			ioport;
+	unsigned int		type:1;
+};
+
+/* Group 0 GPIO helpers */
+static void intelce_gpio0_set_direction(struct gpio_chip *chip,
+				unsigned offset, int direction)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = ioread32(gpch->base + GEN3_GPIO0_GPOER);
+	if (direction)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	iowrite32(mask, gpch->base + GEN3_GPIO0_GPOER);
+}
+
+static void intelce_gpio0_set_alt_func(struct gpio_chip *chip,
+				unsigned offset, int func)
+{
+	struct intelce_gpio *gpch;
+	unsigned bit;
+	u32 mask;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	if (offset <= 5)
+		bit = 0;
+	else if (offset <= 7)
+		bit = 1;
+	else
+		bit = 2;
+
+	/* Set functionnality */
+	mask = ioread32(gpch->base + GEN3_GPIO0_MUX_CNTL);
+	if (func)
+		mask |= (1 << bit);
+	else
+		mask &= ~(1 << bit);
+	iowrite32(mask, gpch->base + GEN3_GPIO0_MUX_CNTL);
+}
+
+/*
+ * GPIO lib stubs
+ * Note that you should call the direction
+ * helpers first which will set the muxing
+ * correctly
+ */
+static void intelce_gpio0_set_dataout(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = ioread32(gpch->base + GEN3_GPIO0_GPOUTR);
+	if (value)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	iowrite32(mask, gpch->base + GEN3_GPIO0_GPOUTR);
+}
+
+static int intelce_gpio0_get_datain(struct gpio_chip *chip,
+				unsigned offset)
+{
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	return ioread32(gpch->base + GEN3_GPIO0_GPINR) & (1 << offset);
+}
+
+static int intelce_gpio0_set_direction_input(struct gpio_chip *chip,
+				unsigned offset)
+{
+	/* Disable GPIO muxing */
+	intelce_gpio0_set_alt_func(chip, offset, 0);
+	intelce_gpio0_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio0_set_direction_output(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	/* Disable GPIO muxing */
+	intelce_gpio0_set_alt_func(chip, offset, 0);
+	intelce_gpio0_set_direction(chip, offset, 1);
+	intelce_gpio0_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Group 1 GPIO helpers */
+static int intelce_gpio1_get_datain(struct gpio_chip *chip,
+				unsigned offset)
+{
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	return inl(gpch->ioport + GEN3_GPIO1_CGLV) & (1 << offset);
+}
+
+static void intelce_gpio1_set_dataout(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = inl(gpch->ioport + GEN3_GPIO1_CGLV);
+	if (value)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO1_CGLV);
+}
+
+static void intelce_gpio1_set_direction(struct gpio_chip *chip,
+				unsigned offset, int direction)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	/* Set the correct GPIO mode (no muxing) */
+	mask = inl(gpch->ioport + GEN3_GPIO1_CGEN);
+	mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO1_CGEN);
+
+	/* Set direction (0 = input, 1 = output) */
+	mask = inl(gpch->ioport + GEN3_GPIO1_CGIO);
+	if (direction)
+		mask &= ~(1 << offset);
+	else
+		mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO1_CGIO);
+}
+
+static int intelce_gpio1_set_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	intelce_gpio1_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio1_set_direction_output(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	intelce_gpio1_set_direction(chip, offset, 1);
+	intelce_gpio1_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Group 2 GPIO helpers */
+static void intelce_gpio2_set_dataout(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	/* Rework base to call GPIO group 1 functions */
+	offset += chip->base - GEN3_GPIO_GROUP_ONE;
+	intelce_gpio1_set_dataout(chip, offset, value);
+}
+
+static int intelce_gpio2_get_datain(struct gpio_chip *chip,
+				unsigned offset)
+{
+	/* Rework base to call GPIO group 1 functions */
+	offset += chip->base - GEN3_GPIO_GROUP_ONE;
+	return intelce_gpio1_get_datain(chip, offset);
+}
+
+/*
+ * set a gpio offset to alternate function (func = 1)
+ * or gpio mode (func = 0)
+ */
+static void intelce_gpio2_set_alt_func(struct gpio_chip *chip,
+				unsigned offset, int func)
+{
+	u32 mask, bit_num;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	/* Clear or set the port GPIO mode */
+	mask = inl(gpch->ioport + GEN3_GPIO2_CGEN);
+	if (func)
+		mask &= ~(1 << offset);
+	else
+		mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO2_CGEN);
+
+	/* Set alternate function,
+	 * we need to recompute the base number */
+	offset += (chip->base + 3);
+	if (offset <= 4)
+		bit_num = 3;
+	else if (offset <= 7)
+		bit_num = 4;
+	else if (offset == 8)
+		bit_num = 5;
+	else
+		bit_num = 6;
+
+	mask = inl(gpch->ioport + GEN3_GPIO2_MUX_CNTL);
+	if (func)
+		mask |= (1 << bit_num);
+	else
+		mask &= ~(1 << bit_num);
+	outl(mask, gpch->ioport + GEN3_GPIO2_MUX_CNTL);
+}
+
+static void intelce_gpio2_set_direction(struct gpio_chip *chip,
+					unsigned offset, int direction)
+{
+	/* Set to no alternate function */
+	intelce_gpio2_set_alt_func(chip, offset, 0);
+	/* Use GPIO group 1 method here */
+	offset += chip->base  - GEN3_GPIO_GROUP_ONE;
+	intelce_gpio1_set_direction(chip, offset, direction);
+}
+
+static int intelce_gpio2_set_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	intelce_gpio2_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio2_set_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	intelce_gpio2_set_direction(chip, offset, 1);
+	intelce_gpio2_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Group 3 GPIO helpers */
+static void intelce_gpio3_set_dataout(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = inl(gpch->ioport + GEN3_GPIO3_CGLV);
+	if (value)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO3_CGLV);
+}
+
+static int intelce_gpio3_get_datain(struct gpio_chip *chip,
+					unsigned offset)
+{
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	return inl(gpch->ioport + GEN3_GPIO3_CGLV) & (1 << offset);
+}
+
+static void intelce_gpio3_set_direction(struct gpio_chip *chip,
+					unsigned offset, int direction)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	/* Set GPIO mode */
+	mask = inl(gpch->ioport + GEN3_GPIO3_CGEN);
+	mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO3_CGEN);
+
+	/* Set direction */
+	mask = inl(gpch->ioport + GEN3_GPIO3_CGIO);
+	if (direction)
+		mask &= ~(1 << offset);
+	else
+		mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO3_CGIO);
+}
+
+static int intelce_gpio3_set_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	intelce_gpio3_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio3_set_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	intelce_gpio3_set_direction(chip, offset, 1);
+	intelce_gpio3_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Array of gpio chips */
+static struct intelce_gpio intelce_gpio_chips[] = {
+	/* GPIO group 0 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio0",
+			.set			= intelce_gpio0_set_dataout,
+			.get			= intelce_gpio0_get_datain,
+			.direction_input 	= intelce_gpio0_set_direction_input,
+			.direction_output 	= intelce_gpio0_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_ZERO,
+			.ngpio			= GEN3_GPIO_GROUP_ONE,
+		}
+	},
+	/* GPIO group 1 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio1",
+			.set			= intelce_gpio1_set_dataout,
+			.get			= intelce_gpio1_get_datain,
+			.direction_input	= intelce_gpio1_set_direction_input,
+			.direction_output	= intelce_gpio1_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_ONE,
+			.ngpio			= GEN3_GPIO_GROUP_TWO - GEN3_GPIO_GROUP_ONE,
+		}
+	},
+	/* GPIO group 2 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio2",
+			.set			= intelce_gpio2_set_dataout,
+			.get			= intelce_gpio2_get_datain,
+			.direction_input	= intelce_gpio2_set_direction_input,
+			.direction_output	= intelce_gpio2_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_TWO,
+			.ngpio			= GEN3_GPIO_GROUP_THREE - GEN3_GPIO_GROUP_TWO,
+		}
+	},
+	/* GPIO group 3 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio3",
+			.set			= intelce_gpio3_set_dataout,
+			.get			= intelce_gpio3_get_datain,
+			.direction_input	= intelce_gpio3_set_direction_input,
+			.direction_output	= intelce_gpio3_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_THREE,
+			.ngpio			= GEN3_NUM_GPIO_PINS - GEN3_GPIO_GROUP_THREE,
+		}
+	},
+};
+
+/* We match on a PCI bus device even to driver GPIO at 0x1080 */
+static int intelce_gpio_probe(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
+{
+	struct fwnode_handle *fwnode;
+	int err, io_size = INTELCE_GPIO_IO_SIZE;
+	int bar = 0;
+	void __iomem *ioaddr;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out;
+
+	/* this should always be supported */
+	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (err) {
+		printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
+				"not supported by the card\n");
+		goto err_out;
+	}
+
+	/* IO Size check */
+	if (pci_resource_len(pdev, bar) < io_size) {
+		printk(KERN_ERR DRV_NAME ": Insufficient PCI resources, aborting\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		printk(KERN_ERR DRV_NAME ": failed to request PCI region\n");
+		goto err_out;
+	}
+
+	ioaddr = pci_iomap(pdev, bar, io_size);
+	if (!ioaddr) {
+		printk(KERN_ERR DRV_NAME ": ioremap failed for device: %s\n",
+					pci_name(pdev));
+		err = -ENOMEM;
+		goto err_release_pci_region;
+	}
+
+	if (!request_region(GEN3_GPIO_IO_BASE, GEN3_GPIO_IO_SIZE, DRV_NAME)) {
+		printk(KERN_ERR DRV_NAME ": failed to request IO port region\n");
+		err = -ENOMEM;
+		goto err_release_pci_region;
+	}
+
+	pci_set_drvdata(pdev, intelce_gpio_chips);
+
+	intelce_gpio_chips[0].base = ioaddr;
+	intelce_gpio_chips[0].pdev = pdev;
+
+	/* Register our gpio chips */
+	device_for_each_child_node(&pdev->dev, fwnode) {
+		u32 chip;
+
+		if (!fwnode_device_is_compatible(fwnode,
+					     "intel,intelce-gpio-controller"))
+			continue;
+
+		fwnode_property_read_u32(fwnode, "chip", &chip);
+
+		intelce_gpio_chips[chip].chip.parent = &pdev->dev;
+		intelce_gpio_chips[chip].chip.fwnode = fwnode;
+
+		/* Set IO base for gpio chips 1 to 3 */
+		if (chip > 0) {
+			intelce_gpio_chips[chip].ioport = GEN3_GPIO_IO_BASE;
+			intelce_gpio_chips[chip].pdev = pdev;
+			intelce_gpio_chips[chip].type = GEN3_TYPE_IOPORT;
+		}
+
+		/* Register our gpio chip */
+		err = devm_gpiochip_add_data(&pdev->dev,
+					     &intelce_gpio_chips[chip].chip,
+					     NULL);
+		if (err) {
+			printk(KERN_ERR DRV_NAME ": failed to register chip %d\n", chip);
+			goto err_drvdata;
+		}
+
+		printk(KERN_INFO DRV_NAME ": registered %s at 0x%08x (%s, %d GPIOs)\n",
+		       intelce_gpio_chips[chip].chip.label,
+		       intelce_gpio_chips[chip].type ?
+		       intelce_gpio_chips[chip].ioport :
+		       (u32)intelce_gpio_chips[chip].base,
+		       intelce_gpio_chips[chip].type ? "IO port" : "PCI",
+		       intelce_gpio_chips[chip].chip.ngpio);
+	}
+
+	return 0;
+
+err_drvdata:
+	pci_set_drvdata(pdev, NULL);
+	pci_iounmap(pdev, ioaddr);
+	release_region(GEN3_GPIO_IO_BASE, GEN3_GPIO_IO_SIZE);
+err_release_pci_region:
+	pci_release_regions(pdev);
+err_out:
+	return err;
+}
+
+static void __exit intelce_gpio_remove(struct pci_dev *pdev)
+{
+	release_region(GEN3_GPIO_IO_BASE, GEN3_GPIO_IO_SIZE);
+	pci_iounmap(pdev, intelce_gpio_chips[0].base);
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id intelce_gpio_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e67) },
+	{ 0 }
+};
+
+static struct pci_driver intelce_gpio_driver = {
+	.name		= DRV_NAME,
+	.id_table	= intelce_gpio_id_tbl,
+	.probe		= intelce_gpio_probe,
+	.remove		= intelce_gpio_remove,
+};
+
+static int __init intelce_gpio_init(void)
+{
+	return pci_register_driver(&intelce_gpio_driver);
+}
+
+static void __exit intelce_gpio_exit(void)
+{
+	pci_unregister_driver(&intelce_gpio_driver);
+}
+
+module_init(intelce_gpio_init);
+module_exit(intelce_gpio_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("GPIO driver for the Intel CE3100/4100 SoC");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
diff -Nruw linux-6.4-fbx/drivers/platform/ipq./Kconfig linux-6.4-fbx/drivers/platform/ipq/Kconfig
--- linux-6.4-fbx/drivers/platform/ipq./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/ipq/Kconfig	2023-11-29 17:07:11.778325198 +0100
@@ -0,0 +1,19 @@
+
+menuconfig QCOM_IPQ_PLATFORM
+	bool "Qualcomm IPQ Platform Specific Device Drivers"
+	default y
+	depends on ARCH_QCOM || COMPILE_TEST
+	help
+	  Say Y here to get to see options for device drivers for
+	  various Qualcomm IPQ platforms.  This option alone does not
+	  add any kernel code.
+
+	  If you say N, all options in this submenu will be skipped
+	  and disabled.
+
+if QCOM_IPQ_PLATFORM
+
+config IPQ_SEC_UPGRADE
+	bool "Qualcomm IPQ sec-upgrade driver."
+
+endif
diff -Nruw linux-6.4-fbx/drivers/platform/ipq./Makefile linux-6.4-fbx/drivers/platform/ipq/Makefile
--- linux-6.4-fbx/drivers/platform/ipq./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/platform/ipq/Makefile	2023-11-29 17:07:11.778325198 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_IPQ_SEC_UPGRADE)	+= sec-upgrade.o
diff -Nruw linux-6.4-fbx/drivers/soc/bcm/bcm63xx/rdp./Makefile linux-6.4-fbx/drivers/soc/bcm/bcm63xx/rdp/Makefile
--- linux-6.4-fbx/drivers/soc/bcm/bcm63xx/rdp./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/soc/bcm/bcm63xx/rdp/Makefile	2020-02-08 00:30:22.220508996 +0100
@@ -0,0 +1,9 @@
+obj-y += rdp_drv.o
+
+rdp_drv-y += \
+	rdp.o \
+	rdp_api.o \
+	rdp_io.o \
+	rdp_ioctl.o
+
+rdp_drv-$(CONFIG_DEBUG_FS) += rdp_debug.o
diff -Nruw linux-6.4-fbx/drivers/soc/bcm/bcm63xx/xrdp./Makefile linux-6.4-fbx/drivers/soc/bcm/bcm63xx/xrdp/Makefile
--- linux-6.4-fbx/drivers/soc/bcm/bcm63xx/xrdp./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/drivers/soc/bcm/bcm63xx/xrdp/Makefile	2023-03-04 02:08:36.875588595 +0100
@@ -0,0 +1,8 @@
+obj-$(CONFIG_SOC_BCM63XX_XRDP) += xrdp_drv.o
+
+xrdp_drv-y += \
+	xrdp.o \
+	xrdp_api.o
+
+xrdp_drv-$(CONFIG_SOC_BCM63XX_XRDP_IOCTL) += xrdp_ioctl.o
+xrdp_drv-$(CONFIG_DEBUG_FS) += xrdp_debug.o
diff -Nruw linux-6.4-fbx/fs/exfat-fbx./Kconfig linux-6.4-fbx/fs/exfat-fbx/Kconfig
--- linux-6.4-fbx/fs/exfat-fbx./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/fs/exfat-fbx/Kconfig	2022-08-30 19:20:31.303636900 +0200
@@ -0,0 +1,3 @@
+
+config EXFAT_FS_FBX
+	tristate "exFAT fs support (fbx)"
diff -Nruw linux-6.4-fbx/fs/exfat-fbx./Makefile linux-6.4-fbx/fs/exfat-fbx/Makefile
--- linux-6.4-fbx/fs/exfat-fbx./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/fs/exfat-fbx/Makefile	2022-08-30 19:20:31.303636900 +0200
@@ -0,0 +1,13 @@
+
+obj-$(CONFIG_EXFAT_FS_FBX)	+= exfat.o
+
+exfat-y	= super.o				\
+	inode.o					\
+	fat.o					\
+	read-write.o				\
+	upcase.o				\
+	bitmap.o				\
+	time.o					\
+	dir.o					\
+	namei.o					\
+	file.o
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/linux/fbxbootinfo.h	2010-08-16 18:15:01.008432229 +0200
@@ -0,0 +1,11 @@
+#ifndef FBXBOOTINFO_H
+#define FBXBOOTINFO_H
+
+struct fbx_bootinfo {
+	u32 bank_number;
+	char uboot_version_str[128];
+	u32 bank0_forced;
+	char cefdk_version_str[256];
+} __attribute__ ((packed));
+
+#endif /* FBXBOOTINFO_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/linux/fbxprocfs.h	2013-12-04 14:33:24.227479057 +0100
@@ -0,0 +1,40 @@
+#ifndef FBXPROCFS_H_
+#define FBXPROCFS_H_
+
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+#include <linux/seq_file.h>
+
+struct fbxprocfs_client
+{
+	const char *dirname;
+	struct module *owner;
+	struct proc_dir_entry *dir;
+	atomic_t refcount;
+	struct list_head list;
+};
+
+struct fbxprocfs_desc {
+	char		*name;
+	unsigned long	id;
+	int	(*rfunc)(struct seq_file *, void *);
+	int	(*wfunc)(struct file *, const char *, unsigned long, void *);
+};
+
+struct fbxprocfs_client *fbxprocfs_add_client(const char *dirname,
+					      struct module *owner);
+
+int fbxprocfs_remove_client(struct fbxprocfs_client *client);
+
+
+int
+fbxprocfs_create_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc);
+
+int
+fbxprocfs_remove_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc);
+
+#endif /* FBXPROCFS_H_ */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/linux/fbxserial.h	2020-02-08 00:30:24.236528585 +0100
@@ -0,0 +1,129 @@
+#ifndef FBXSERIAL_H_
+#define FBXSERIAL_H_
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+/*
+ * some part of serial may vary, we use abstract struct to store this,
+ * data content depends on type.
+ */
+#define EXTINFO_SIZE		128
+#define EXTINFO_MAX_COUNT	16
+
+/*
+ * extdev desc
+ */
+#define EXTINFO_TYPE_EXTDEV	1
+
+#define EXTDEV_TYPE_BUNDLE	1
+#define EXTDEV_TYPE_MAX		2
+
+struct fbx_serial_extinfo {
+	u32			type;
+
+	union {
+		/* extdev */
+		struct {
+			u32	type;
+			u32	model;
+			char	serial[64];
+		} extdev;
+
+		/* raw access */
+		unsigned char	data[EXTINFO_SIZE];
+	} u;
+}  __attribute__ ((packed));;
+
+
+/*
+ * master serial structure
+ */
+
+#define FBXSERIAL_VERSION	1
+
+#define FBXSERIAL_MAGIC		0x2d9521ab
+
+#define MAC_ADDR_SIZE		6
+#define RANDOM_DATA_SIZE	32
+
+/*
+ * this  is the  maximum size  we accept  to check  crc32  against, so
+ * structure may no grow larger than this
+ */
+#define FBXSERIAL_MAX_SIZE	8192
+
+struct fbx_serial {
+	u32	crc32;
+	u32	magic;
+	u32	struct_version;
+	u32	len;
+
+	/* board serial */
+	u16	type;
+	u8	version;
+	u8	manufacturer;
+	u16	year;
+	u8	week;
+	u32	number;
+	u32	flags;
+
+	/* mac address base */
+	u8	mac_addr_base[MAC_ADDR_SIZE];
+
+	/* mac address count */
+	u8	mac_count;
+
+	/* random data */
+	u8	random_data[RANDOM_DATA_SIZE];
+
+	/* last update of data (seconds since epoch) */
+	u32	last_modified;
+
+	/* count of following extinfo tag */
+	u32	extinfo_count;
+
+	/* beginning of extended info */
+	struct fbx_serial_extinfo	extinfos[EXTINFO_MAX_COUNT];
+
+} __attribute__ ((packed));
+
+
+/*
+ * default value to use in case magic is wrong (no cksum in that case)
+ */
+static inline void fbxserial_set_default(struct fbx_serial *s)
+{
+	memset(s, 0, sizeof (*s));
+	s->magic = FBXSERIAL_MAGIC;
+	s->struct_version = FBXSERIAL_VERSION;
+	s->len = sizeof (*s);
+	s->manufacturer = '_';
+	memcpy(s->mac_addr_base, "\x00\x07\xCB\x00\x00\xFD", 6);
+	s->mac_count = 1;
+}
+
+void
+fbxserialinfo_get_random(unsigned char *data, unsigned int len);
+
+const void *
+fbxserialinfo_get_mac_addr(unsigned int index);
+
+int
+fbxserialinfo_read(const void *data, struct fbx_serial *out);
+
+struct fbx_serial *fbxserialinfo_get(void);
+
+/*
+ * implemented in board specific code
+ */
+#ifdef CONFIG_ARCH_HAS_FBXSERIAL
+extern const struct fbx_serial *arch_get_fbxserial(void);
+#else
+static inline const struct fbx_serial *arch_get_fbxserial(void)
+{
+	return NULL;
+}
+#endif
+
+#endif /* FBXSERIAL_H_ */
diff -Nruw linux-6.4-fbx/include/linux/hdmi-cec./hdmi-cec.h linux-6.4-fbx/include/linux/hdmi-cec/hdmi-cec.h
--- linux-6.4-fbx/include/linux/hdmi-cec./hdmi-cec.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/include/linux/hdmi-cec/hdmi-cec.h	2017-02-23 16:14:36.430018880 +0100
@@ -0,0 +1,127 @@
+/*
+ * Header for the HDMI CEC core infrastructure
+ */
+#ifndef __HDMI_CEC_H
+#define __HDMI_CEC_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#include <uapi/linux/hdmi-cec/hdmi-cec.h>
+
+struct cec_adapter;
+
+#define CEC_HW_HAS_COUNTERS	(1 << 0)	/* HW counts events */
+#define CEC_HW_HAS_RX_FILTER	(1 << 1)	/* HW has receive filter */
+
+/**
+ * struct cec_adapter_ops - cec adapter low-level operations
+ * @set_logical_address:	callback to set the logical address
+ * @send:	callback to send a cec payload
+ * @reset:	callback to reset the hardware
+ * @get_counters:	callback to get the counters (if supported by HW)
+ * @set_rx_mode:	callback to set the receive mode
+ * @attach:	callback to attach the host to the device
+ * @detach:	callbackt to detach the host from the device
+ * @set_detached_config:	callback to configure adapter when detached
+ */
+struct cec_adapter_ops {
+	int	(*set_logical_address)(struct cec_adapter *, const u8);
+	int	(*send)(struct cec_adapter *, u16, u8, const u8 *, const u8);
+	int	(*reset)(struct cec_adapter *);
+	int	(*get_counters)(struct cec_adapter *, struct cec_counters *);
+	int	(*set_rx_mode)(struct cec_adapter *, enum cec_rx_mode);
+	int	(*attach)(struct cec_adapter *);
+	int	(*detach)(struct cec_adapter *);
+	int	(*set_detached_config)(struct cec_adapter *,
+				       const struct cec_detached_config *);
+};
+
+/**
+ * struct cec_adapter - cec adapter structure
+ * @driver_name:	driver prefix used for device naming
+ * @module:		module pointer for refcounting
+ * @ops:		struct cec_adapter_ops pointer
+ * @flags:		adapter flags bitmask
+ * @name:		adapter unique name
+ * @dev:		device structure for device/driver model interaction
+ * @lock:		adapter all-purpose mutex for exclusive locking
+ * @attached:		adapter attached to host or not
+ * @tx_pending:		true if tx is ongoing
+ * @tx_lock:		transmit lock
+ * @rx_msg_list:	receive message list head
+ * @rx_msg_list_lock:	receive message list lock
+ * @rx_msg_len:		receive message queue len
+ * @wait:		receive waitqueue (used for poll, read)
+ * @cdev:		character device node
+ */
+struct cec_adapter {
+	const char		*driver_name;
+	struct module		*module;
+	const struct cec_adapter_ops	*ops;
+	unsigned int		flags;
+	atomic_t		users;
+
+	/* unique device name, used for sysfs & chardev */
+	char			name[128];
+
+	/* associated sysfs device */
+	struct device		dev;
+
+	/* private */
+	struct mutex		lock;
+	bool			attached;
+
+	wait_queue_head_t	wait;
+
+	/* transmit message list */
+	spinlock_t		tx_done_lock;
+	unsigned long		tx_pending;
+	bool			last_tx_success;
+	u8			last_tx_flags;
+	u8			last_tx_tries;
+	struct timer_list	tx_timeout_timer;
+
+	/* receive message list */
+	struct list_head	rx_msg_list;
+	spinlock_t		rx_msg_list_lock;
+	unsigned int		rx_msg_len;
+
+	/* associated chardev */
+	struct cdev		cdev;
+
+	/* true when unregistering device */
+	bool			dead;
+};
+
+#define CECDEV_PRIV_ALIGN	8
+
+static inline void *cec_adapter_priv(struct cec_adapter *adapter)
+{
+	return (u8 *)adapter + ((sizeof(struct cec_adapter)
+			      + (CECDEV_PRIV_ALIGN - 1))
+			     & ~(CECDEV_PRIV_ALIGN - 1));
+}
+
+static inline struct cec_adapter *to_cec_adapter(struct device *d)
+{
+	return container_of(d, struct cec_adapter, dev);
+}
+
+struct cec_adapter *alloc_cec_adapter(size_t priv_size);
+int register_cec_adapter(struct cec_adapter *, struct device *);
+void unregister_cec_adapter(struct cec_adapter *);
+void free_cec_adapter(struct cec_adapter *);
+int adapter_rx_done(struct cec_adapter *, const u8 *, const u8 len,
+		    bool valid, u8 flags);
+void adapter_tx_done(struct cec_adapter *, bool success, u8 flags, u8 tries);
+
+#endif /* __HDMI_CEC_H */
diff -Nruw linux-6.4-fbx/include/linux/remoti./leds.h linux-6.4-fbx/include/linux/remoti/leds.h
--- linux-6.4-fbx/include/linux/remoti./leds.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/include/linux/remoti/leds.h	2013-12-04 14:33:24.819479067 +0100
@@ -0,0 +1,11 @@
+#ifndef __REMOTI_LEDS_H
+#define __REMOTI_LEDS_H
+
+#define REMOTI_LEDS_COUNT	2
+
+struct remoti_leds_pdata {
+	unsigned num_leds;
+	const char *names[REMOTI_LEDS_COUNT];
+};
+
+#endif /* __REMOTI_LEDS_H */
diff -Nruw linux-6.4-fbx/include/linux/remoti./remoti.h linux-6.4-fbx/include/linux/remoti/remoti.h
--- linux-6.4-fbx/include/linux/remoti./remoti.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/include/linux/remoti/remoti.h	2013-12-04 14:33:24.819479067 +0100
@@ -0,0 +1,60 @@
+#ifndef __REMOTI_H
+#define __REMOTI_H
+
+#include <uapi/linux/remoti/remoti.h>
+
+/*
+ * platform data definition
+ */
+struct remoti_dev_pdata {
+	unsigned int		id;
+	unsigned int		reset_gpio;
+	unsigned int		reset_polarity;
+};
+
+/*
+ * kernel API to access remoti device
+ */
+struct rti_udev;
+
+struct rti_udev *rti_get_udevice(unsigned int id);
+
+void rti_release_udevice(struct rti_udev *udev);
+
+int rti_send_sync_msg(struct rti_udev *udev, struct rti_msg *msg);
+
+int rti_send_async_msg(struct rti_udev *udev, struct rti_msg *msg);
+
+int rti_register_cmd_callback(struct rti_udev *udev,
+			      u8 subsys, u8 cmd,
+			      void (*cb)(void *cb_priv,
+					 const struct rti_msg *msg),
+			      void *cb_priv);
+
+void rti_unregister_cmd_callback(struct rti_udev *udev, u8 subsys, u8 cmd);
+
+struct rti_kcallback {
+	__u8		subsys;
+	__u8		cmd;
+	void		(*cb)(void *cb_priv, const struct rti_msg *msg);
+};
+
+int rti_register_cmds_callback(struct rti_udev *udev,
+			       const struct rti_kcallback *cbs,
+			       size_t cb_count,
+			       void *cb_priv);
+
+void rti_unregister_cmds_callback(struct rti_udev *udev,
+				  const struct rti_kcallback *cbs,
+				  size_t cb_count);
+
+
+enum rti_udev_state {
+	RTI_UDEV_UP = 0,
+	RTI_UDEV_GOING_DOWN,
+};
+
+void rti_register_udevice_notifier(struct notifier_block *nb);
+void rti_unregister_udevice_notifier(struct notifier_block *nb);
+
+#endif /* __REMOTI_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/net/gso.h	2023-11-29 17:07:13.661661459 +0100
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _NET_GSO_H
+#define _NET_GSO_H
+
+#include <linux/skbuff.h>
+
+/* Keeps track of mac header offset relative to skb->head.
+ * It is useful for TSO of Tunneling protocol. e.g. GRE.
+ * For non-tunnel skb it points to skb_mac_header() and for
+ * tunnel skb it points to outer mac header.
+ * Keeps track of level of encapsulation of network headers.
+ */
+struct skb_gso_cb {
+	union {
+		int	mac_offset;
+		int	data_offset;
+	};
+	int	encap_level;
+	__wsum	csum;
+	__u16	csum_start;
+};
+#define SKB_GSO_CB_OFFSET	32
+#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_GSO_CB_OFFSET))
+
+static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
+{
+	return (skb_mac_header(inner_skb) - inner_skb->head) -
+		SKB_GSO_CB(inner_skb)->mac_offset;
+}
+
+static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
+{
+	int new_headroom, headroom;
+	int ret;
+
+	headroom = skb_headroom(skb);
+	ret = pskb_expand_head(skb, extra, 0, GFP_ATOMIC);
+	if (ret)
+		return ret;
+
+	new_headroom = skb_headroom(skb);
+	SKB_GSO_CB(skb)->mac_offset += (new_headroom - headroom);
+	return 0;
+}
+
+static inline void gso_reset_checksum(struct sk_buff *skb, __wsum res)
+{
+	/* Do not update partial checksums if remote checksum is enabled. */
+	if (skb->remcsum_offload)
+		return;
+
+	SKB_GSO_CB(skb)->csum = res;
+	SKB_GSO_CB(skb)->csum_start = skb_checksum_start(skb) - skb->head;
+}
+
+/* Compute the checksum for a gso segment. First compute the checksum value
+ * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and
+ * then add in skb->csum (checksum from csum_start to end of packet).
+ * skb->csum and csum_start are then updated to reflect the checksum of the
+ * resultant packet starting from the transport header-- the resultant checksum
+ * is in the res argument (i.e. normally zero or ~ of checksum of a pseudo
+ * header.
+ */
+static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res)
+{
+	unsigned char *csum_start = skb_transport_header(skb);
+	int plen = (skb->head + SKB_GSO_CB(skb)->csum_start) - csum_start;
+	__wsum partial = SKB_GSO_CB(skb)->csum;
+
+	SKB_GSO_CB(skb)->csum = res;
+	SKB_GSO_CB(skb)->csum_start = csum_start - skb->head;
+
+	return csum_fold(csum_partial(csum_start, plen, partial));
+}
+
+struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
+				  netdev_features_t features, bool tx_path);
+
+static inline struct sk_buff *skb_gso_segment(struct sk_buff *skb,
+					      netdev_features_t features)
+{
+	return __skb_gso_segment(skb, features, true);
+}
+
+struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
+				    netdev_features_t features, __be16 type);
+
+struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
+				    netdev_features_t features);
+
+bool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu);
+
+bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len);
+
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+					int pulled_hlen, u16 mac_offset,
+					int mac_len)
+{
+	skb->protocol = protocol;
+	skb->encapsulation = 1;
+	skb_push(skb, pulled_hlen);
+	skb_reset_transport_header(skb);
+	skb->mac_header = mac_offset;
+	skb->network_header = skb->mac_header + mac_len;
+	skb->mac_len = mac_len;
+}
+
+#endif /* _NET_GSO_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/bcm63xx_rdp_ioctl.h	2020-02-08 00:30:24.628532394 +0100
@@ -0,0 +1,71 @@
+#ifndef LINUX_BCM63XX_RDP_IOCTL_H_
+#define LINUX_BCM63XX_RDP_IOCTL_H_
+
+#include <linux/types.h>
+
+enum {
+	RDP_IOC_OP_GET_INFO,
+
+	RDP_IOC_OP_READ8,
+	RDP_IOC_OP_READ16,
+	RDP_IOC_OP_READ32,
+	RDP_IOC_OP_WRITE8,
+	RDP_IOC_OP_WRITE16,
+	RDP_IOC_OP_WRITE32,
+
+	RDP_IOC_OP_READ_TM_32,
+	RDP_IOC_OP_WRITE_TM_32,
+	RDP_IOC_OP_READ_MC_32,
+	RDP_IOC_OP_WRITE_MC_32,
+
+	RDP_IOC_OP_RESET,
+
+	RDP_IOC_DMA_MAP,
+	RDP_IOC_DMA_GET_INFO,
+	RDP_IOC_DMA_FLUSH_ALL,
+	RDP_IOC_DMA_READ_BUFFER,
+	RDP_IOC_DMA_WRITE_BUFFER,
+
+	RDP_IOC_OP_MAP_INTERRUPTS,
+};
+
+struct bcm_rdp_pioctl_dma_result {
+	__u32		id;
+	__u32		size;
+	__u64		virt_addr;
+	__u64		dma_addr;
+};
+
+struct bcm_rdp_pioctl_get_info_result {
+	__u64		tm_dma_addr;
+	__u64		mc_dma_addr;
+	__u32		tm_size;
+	__u32		mc_size;
+};
+
+struct bcm_rdp_pioctl {
+	union {
+		/* for get_info op */
+		struct {
+			void __user	*buf_addr;
+		} get_info;
+
+		/* for read/write op */
+		struct {
+			__u32		reg_area;
+			__u32		offset;
+			__u32		size;
+			void __user	*buf_addr;
+		} io;
+
+		/* for dma op */
+		struct {
+			__u32		id;
+			__u32		size;
+			void __user	*buf_addr;
+		} dma;
+	} u;
+};
+
+#endif /* LINUX_BCM63XX_RDP_IOCTL_H_ */
+
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/exfat_user.h	2013-12-04 14:33:25.331479075 +0100
@@ -0,0 +1,47 @@
+/*
+ * exfat_user.h for exfat
+ * Created by <nschichan@freebox.fr> on Fri Aug 23 15:31:08 2013
+ */
+
+#ifndef __EXFAT_USER_H
+# define __EXFAT_USER_H
+
+struct exfat_fragment {
+	uint32_t	fcluster_start;
+	uint32_t	dcluster_start;
+	uint32_t	nr_clusters;
+	uint64_t	sector_start;
+};
+
+struct exfat_fragment_head {
+	uint32_t		fcluster_start;
+	uint32_t		nr_fragments;
+	uint32_t		sector_size;
+	uint32_t		cluster_size;
+	struct exfat_fragment	fragments[0];
+};
+
+struct exfat_bitmap_data {
+	uint32_t		start_cluster;
+	uint32_t		nr_clusters;
+	uint64_t		sector_start;
+	uint64_t		nr_sectors;
+};
+
+struct exfat_bitmap_head {
+	uint32_t			start_cluster;
+	uint32_t			nr_entries;
+	struct exfat_bitmap_data	entries[0];
+};
+
+struct exfat_dirent_head {
+	uint32_t offset;
+	uint32_t nr_entries;
+	uint8_t entries[0];
+};
+
+#define EXFAT_IOCGETFRAGMENTS	_IOR('X', 0x01, struct exfat_fragment_head)
+#define EXFAT_IOCGETBITMAP	_IOR('X', 0x02, struct exfat_bitmap_head)
+#define EXFAT_IOCGETDIRENTS	_IOR('X', 0x03, struct exfat_dirent_head)
+
+#endif /* !__EXFAT_USER_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/fbxatm.h	2016-12-16 12:58:03.574561133 +0100
@@ -0,0 +1,159 @@
+/*
+ * Generic fbxatm definition, exported to userspace
+ */
+#ifndef LINUX_FBXATM_H_
+#define LINUX_FBXATM_H_
+
+#include <linux/types.h>
+#include <linux/if.h>
+
+#define FBXATM_IOCTL_MAGIC		0xd3
+
+/* allow userspace usage without up to date kernel headers */
+#ifndef PF_FBXATM
+#define PF_FBXATM			32
+#define AF_FBXATM			PF_FBXATM
+#endif
+
+struct fbxatm_vcc_id {
+	int				dev_idx;
+	__u32				vpi;
+	__u32				vci;
+};
+
+enum fbxatm_vcc_user {
+	FBXATM_VCC_USER_NONE = 0,
+	FBXATM_VCC_USER_2684,
+	FBXATM_VCC_USER_PPPOA,
+};
+
+enum fbxatm_vcc_traffic_class {
+	FBXATM_VCC_TC_UBR_NO_PCR = 0,
+	FBXATM_VCC_TC_UBR,
+};
+
+struct fbxatm_vcc_qos {
+	__u32				traffic_class;
+	__u32				max_sdu;
+	__u32				max_buffered_pkt;
+	__u32				priority;
+	__u32				rx_priority;
+};
+
+
+/*
+ * VCC related
+ */
+struct fbxatm_vcc_params {
+	/* ADD/DEL/GET */
+	struct fbxatm_vcc_id		id;
+
+	/* ADD/GET */
+	struct fbxatm_vcc_qos		qos;
+
+	/* GET */
+	enum fbxatm_vcc_user		user;
+};
+
+#define FBXATM_IOCADD		_IOW(FBXATM_IOCTL_MAGIC,	1,	\
+					struct fbxatm_vcc_params)
+
+#define FBXATM_IOCDEL		_IOR(FBXATM_IOCTL_MAGIC,	2,	\
+					struct fbxatm_vcc_params)
+
+#define FBXATM_IOCGET		_IOWR(FBXATM_IOCTL_MAGIC,	3,	\
+					struct fbxatm_vcc_params)
+
+
+struct fbxatm_vcc_drop_params {
+	struct fbxatm_vcc_id		id;
+	unsigned int			drop_count;
+};
+
+#define FBXATM_IOCDROP		_IOWR(FBXATM_IOCTL_MAGIC,	5,	\
+					struct fbxatm_vcc_drop_params)
+
+/*
+ * OAM related
+ */
+enum fbxatm_oam_ping_type {
+	FBXATM_OAM_PING_SEG_F4	= 0,
+	FBXATM_OAM_PING_SEG_F5,
+	FBXATM_OAM_PING_E2E_F4,
+	FBXATM_OAM_PING_E2E_F5,
+};
+
+struct fbxatm_oam_ping_req {
+	/* only dev_idx for F4 */
+	struct fbxatm_vcc_id		id;
+
+	__u8				llid[16];
+	enum fbxatm_oam_ping_type	type;
+};
+
+#define FBXATM_IOCOAMPING	_IOWR(FBXATM_IOCTL_MAGIC,	10,	\
+				      struct fbxatm_oam_ping_req)
+
+
+/*
+ * PPPOA related
+ */
+enum fbxatm_pppoa_encap {
+	FBXATM_EPPPOA_AUTODETECT = 0,
+	FBXATM_EPPPOA_VCMUX,
+	FBXATM_EPPPOA_LLC,
+};
+
+struct fbxatm_pppoa_vcc_params {
+	struct fbxatm_vcc_id		id;
+	__u32				encap;
+	__u32				cur_encap;
+};
+
+#define FBXATM_PPPOA_IOCADD	_IOW(FBXATM_IOCTL_MAGIC,	20,	\
+					struct fbxatm_pppoa_vcc_params)
+
+#define FBXATM_PPPOA_IOCDEL	_IOW(FBXATM_IOCTL_MAGIC,	21,	\
+					struct fbxatm_pppoa_vcc_params)
+
+#define FBXATM_PPPOA_IOCGET	_IOWR(FBXATM_IOCTL_MAGIC,	22,	\
+					struct fbxatm_pppoa_vcc_params)
+
+
+
+/*
+ * 2684 related
+ */
+enum fbxatm_2684_encap {
+	FBXATM_E2684_VCMUX = 0,
+	FBXATM_E2684_LLC,
+};
+
+enum fbxatm_2684_payload {
+	FBXATM_P2684_BRIDGE = 0,
+	FBXATM_P2684_ROUTED,
+};
+
+#define FBXATM_2684_MAX_VCC		8
+
+struct fbxatm_2684_vcc_params {
+	struct fbxatm_vcc_id		id_list[FBXATM_2684_MAX_VCC];
+	size_t				id_count;
+
+	__u32				encap;
+	__u32				payload;
+	char				dev_name[IFNAMSIZ];
+	__u8				perm_addr[6];
+};
+
+
+#define FBXATM_2684_IOCADD	_IOW(FBXATM_IOCTL_MAGIC,	30,	\
+					struct fbxatm_2684_vcc_params)
+
+#define FBXATM_2684_IOCDEL	_IOW(FBXATM_IOCTL_MAGIC,	31,	\
+					struct fbxatm_2684_vcc_params)
+
+#define FBXATM_2684_IOCGET	_IOWR(FBXATM_IOCTL_MAGIC,	32,	\
+					struct fbxatm_2684_vcc_params)
+
+#endif /* LINUX_FBXATM_H_ */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/fbxbridge.h	2020-02-08 00:30:24.640532511 +0100
@@ -0,0 +1,72 @@
+#ifndef _UAPI_FBXBRIDGE_H
+# define _UAPI_FBXBRIDGE_H
+
+#include <linux/if.h>
+#include <linux/if_ether.h>
+
+#define MAX_ALIASES				3
+
+#define FBXBRIDGE_FLAGS_FILTER			(1 << 0)
+#define FBXBRIDGE_FLAGS_DHCPD			(1 << 1)
+#define FBXBRIDGE_FLAGS_NETFILTER		(1 << 2)
+
+/*
+ * ioctl command
+ */
+
+enum fbxbridge_ioctl_cmd
+{
+	E_CMD_BR_CHG = 0,
+	E_CMD_BR_DEV_CHG,
+	E_CMD_BR_PARAMS,
+};
+
+struct fbxbridge_ioctl_chg
+{
+	char	brname[IFNAMSIZ];
+	__u32	action;
+};
+
+struct fbxbridge_ioctl_dev_chg
+{
+	char	brname[IFNAMSIZ];
+	char	devname[IFNAMSIZ];
+	__u32	wan;
+	__u32	action;
+};
+
+struct fbxbridge_port_info
+{
+	char	name[IFNAMSIZ];
+	__u32	present;
+};
+
+struct fbxbridge_ioctl_params
+{
+	int				action;
+	char				brname[IFNAMSIZ];
+
+	/* config */
+	__u32				flags;
+	__be32				dns1_addr;
+	__be32				dns2_addr;
+	__be32				ip_aliases[MAX_ALIASES];
+	__u32				dhcpd_renew_time;
+	__u32				dhcpd_rebind_time;
+	__u32				dhcpd_lease_time;
+	__u32				inputmark;
+
+	/* status */
+	struct fbxbridge_port_info	wan_dev;
+	struct fbxbridge_port_info	lan_dev;
+	__u8				lan_hwaddr[ETH_ALEN];
+	__u32				have_hw_addr;
+};
+
+struct fbxbridge_ioctl_req
+{
+	enum fbxbridge_ioctl_cmd	cmd;
+	unsigned long			arg;
+};
+
+#endif /* _UAPI_FBXBRIDGE_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/fbxjtag.h	2020-02-08 00:30:24.644532550 +0100
@@ -0,0 +1,89 @@
+#ifndef FBXJTAG_H_
+# define FBXJTAG_H_
+
+#ifdef __KERNEL__
+# include <linux/types.h>
+#endif
+
+# define JTAG_RESET_STEPS	16
+# define JTAG_DATA_READ_SIZE	128
+# define JTAG_INST_READ_SIZE	128
+# define JTAG_DEF_CLOCK_DELAY	500
+# define JTAG_DEF_WAIT_TMS	0
+
+enum jtag_main_state {
+	JTAG_STATE_TEST_MASK	=	0x10,
+	JTAG_STATE_RUN_MASK	=	0x20,
+	JTAG_STATE_DR_MASK	=	0x40,
+	JTAG_STATE_IR_MASK	=	0x80,
+};
+#define JTAG_STATE_MASK			0xF0
+
+enum jtag_sub_state {
+	JTAG_SUB_STATE_SELECT	=	0x0,
+	JTAG_SUB_STATE_CAPTURE	=	0x1,
+	JTAG_SUB_STATE_SHIFT	=	0x2,
+	JTAG_SUB_STATE_EXIT1	=	0x3,
+	JTAG_SUB_STATE_PAUSE	=	0x4,
+	JTAG_SUB_STATE_EXIT2	=	0x5,
+	JTAG_SUB_STATE_UPDATE	=	0x6,
+};
+#define JTAG_SUB_STATE_MASK		0xF
+
+enum jtag_state {
+	JTAG_STATE_UNDEF	= 0,
+	JTAG_STATE_TEST_LOGIC_RESET	= JTAG_STATE_TEST_MASK,
+	JTAG_STATE_RUN_TEST_IDLE	= JTAG_STATE_RUN_MASK,
+
+	JTAG_STATE_SELECT_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_SELECT,
+	JTAG_STATE_CAPTURE_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_CAPTURE,
+	JTAG_STATE_SHIFT_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_SHIFT,
+	JTAG_STATE_EXIT1_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_EXIT1,
+	JTAG_STATE_PAUSE_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_PAUSE,
+	JTAG_STATE_EXIT2_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_EXIT2,
+	JTAG_STATE_UPDATE_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_UPDATE,
+
+	JTAG_STATE_SELECT_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_SELECT,
+	JTAG_STATE_CAPTURE_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_CAPTURE,
+	JTAG_STATE_SHIFT_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_SHIFT,
+	JTAG_STATE_EXIT1_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_EXIT1,
+	JTAG_STATE_PAUSE_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_PAUSE,
+	JTAG_STATE_EXIT2_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_EXIT2,
+	JTAG_STATE_UPDATE_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_UPDATE,
+
+	JTAG_STATE_MAX
+};
+
+#define JTAG_STATE_IN_DR(state)	((state) & JTAG_STATE_DR_MASK)
+#define JTAG_STATE_IN_IR(state)	((state) & JTAG_STATE_IR_MASK)
+
+#ifdef __KERNEL__
+
+#define JTAG_BUF_SIZE	2048
+
+struct fbxjtag_data {
+	const char	*name;
+	struct {
+		struct fbxgpio_pin	*tck;
+		struct fbxgpio_pin	*tms;
+		struct fbxgpio_pin	*tdi;
+		struct fbxgpio_pin	*tdo;
+	}		gpios;
+	u32		clock_delay;
+	u32		wait_tms;
+	u32		data_read_size;
+	u32		instruction_read_size;
+	bool		last_tms_dataout;
+	struct device	*dev;
+	enum jtag_state state;
+	char		nb_reset;
+	char		dr_buf[JTAG_BUF_SIZE];
+	unsigned 	dr_w;
+	unsigned 	dr_r;
+	char		ir_buf[JTAG_BUF_SIZE];
+	unsigned 	ir_r;
+	unsigned 	ir_w;
+};
+#endif
+
+#endif /* !FBXJTAG_H_ */
diff -Nruw linux-6.4-fbx/include/uapi/linux/hdmi-cec./dev.h linux-6.4-fbx/include/uapi/linux/hdmi-cec/dev.h
--- linux-6.4-fbx/include/uapi/linux/hdmi-cec./dev.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/include/uapi/linux/hdmi-cec/dev.h	2020-02-08 00:30:24.648532589 +0100
@@ -0,0 +1,30 @@
+#ifndef __HDMI_CEC_DEV_H
+#define __HDMI_CEC_DEV_H
+
+#include <linux/ioctl.h>
+#include <linux/hdmi-cec/hdmi-cec.h>
+
+#define CEC_IOCTL_BASE	'C'
+
+#define CEC_SET_LOGICAL_ADDRESS	_IOW(CEC_IOCTL_BASE, 0, int)
+#define CEC_RESET_DEVICE	_IOW(CEC_IOCTL_BASE, 3, int)
+#define CEC_GET_COUNTERS	_IOR(CEC_IOCTL_BASE, 4, struct cec_counters)
+#define CEC_SET_RX_MODE		_IOW(CEC_IOCTL_BASE, 5, enum cec_rx_mode)
+#define CEC_GET_TX_STATUS	_IOW(CEC_IOCTL_BASE, 6, struct cec_tx_status)
+#define CEC_SET_DETACHED_CONFIG	_IOW(CEC_IOCTL_BASE, 7, struct cec_detached_config)
+
+#define CEC_MAX_DEVS	(10)
+
+#ifdef __KERNEL__
+
+struct cec_adapter;
+
+int __init cec_cdev_init(void);
+void __exit cec_cdev_exit(void);
+
+int cec_create_adapter_node(struct cec_adapter *);
+void cec_remove_adapter_node(struct cec_adapter *);
+
+#endif /* __KERNEL__ */
+
+#endif /* __HDMI_CEC_DEV_H */
diff -Nruw linux-6.4-fbx/include/uapi/linux/hdmi-cec./hdmi-cec.h linux-6.4-fbx/include/uapi/linux/hdmi-cec/hdmi-cec.h
--- linux-6.4-fbx/include/uapi/linux/hdmi-cec./hdmi-cec.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/include/uapi/linux/hdmi-cec/hdmi-cec.h	2013-12-04 14:33:25.335479075 +0100
@@ -0,0 +1,153 @@
+#ifndef __UAPI_HDMI_CEC_H
+#define __UAPI_HDMI_CEC_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/* Common defines for HDMI CEC */
+#define CEC_BCAST_ADDR		(0x0f)
+#define CEC_ADDR_MAX		CEC_BCAST_ADDR
+
+#define CEC_MAX_MSG_LEN		(16)	/* 16 blocks */
+
+enum cec_rx_msg_flags {
+	/*
+	 * an ACK was received for this message
+	 */
+	CEC_RX_F_ACKED			= (1 << 0),
+
+	/*
+	 * message was fully received
+	 */
+	CEC_RX_F_COMPLETE		= (1 << 1),
+};
+
+/**
+ * struct cec_rx_msg - user-space exposed cec message cookie
+ * @data:	cec message payload
+ * @len:	cec message length
+ * @valid:	0 for invalid message
+ * @flags:	flag field (cec_rx_msg_flags)
+ */
+struct cec_rx_msg {
+	__u8	data[CEC_MAX_MSG_LEN];
+	__u8	len;
+	__u8	valid;
+	__u8	flags;
+
+} __attribute__((packed));
+
+enum cec_tx_status_flags {
+	/*
+	 * message was nacked at some point
+	 */
+	CEC_TX_F_NACK			= (1 << 0),
+
+	/*
+	 * abort sending because total time to send was elapsed
+	 */
+	CEC_TX_F_TIMEOUT		= (1 << 1),
+
+	/*
+	 * abort sending because maximum number of retry has passed
+	 */
+	CEC_TX_F_MAX_RETRIES		= (1 << 2),
+
+	/*
+	 * abort sending because of arbitration loss
+	 */
+	CEC_TX_F_ARBITRATION_LOST	= (1 << 3),
+
+	/*
+	 * message failed for other reason
+	 */
+	CEC_TX_F_UNKNOWN_ERROR		= (1 << 7),
+};
+
+/**
+ * struct cec_tx_msg - user-space exposed cec message cookie
+ * @expire_ms:	how long we try to send message (milliseconds)
+ * @data:	cec message payload
+ * @len:	cec message length
+ * @success:	0 => message was sent, else => failed to send message
+ * @flags:	flag field (cec_tx_msg_flags)
+ * @tries:	number of try done to send message
+ */
+struct cec_tx_msg {
+	__u16	expire_ms;
+	__u8	data[CEC_MAX_MSG_LEN];
+	__u8	len;
+	__u8	success;
+	__u8	flags;
+	__u8	tries;
+} __attribute__((packed));
+
+struct cec_tx_status {
+	__u8	sent;
+	__u8	success;
+	__u8	flags;
+	__u8	tries;
+} __attribute__((packed));
+
+#define DETACH_CFG_F_WAKEUP		(1 << 0)
+
+struct cec_detached_config {
+	__u8	phys_addr_valid;
+	__u8	phys_addr[2];
+	__u8	flags;
+} __attribute__((packed));
+
+/* Counters */
+
+/**
+ * struct cec_rx_counters - cec adpater RX counters
+ */
+struct cec_rx_counters {
+	__u8	pkts;
+	__u8	filtered_pkts;
+	__u8	valid_pkts;
+	__u8	rx_queue_full;
+	__u8	late_ack;
+	__u8	error;
+	__u8	rx_timeout_abort;
+	__u8	rx_throttled;
+};
+
+/**
+ * struct cec_tx_counters - cec adapter TX counters
+ */
+struct cec_tx_counters {
+	__u8	done;
+	__u8	fail;
+	__u8	timeout;
+	__u8	arb_loss;
+	__u8	bad_ack_timings;
+	__u8	tx_miss_early;
+	__u8	tx_miss_late;
+};
+
+/**
+ * struct cec_counters - tx and rx cec counters
+ * @rx:	struct cec_rx_counters
+ * @tx: struct cec_tx_counters
+ */
+struct cec_counters {
+	struct cec_rx_counters	rx;
+	struct cec_tx_counters	tx;
+};
+
+/**
+ * enum cec_rx_mode - cec adapter rx mode
+ * @CEC_RX_MODE_DISABLED:	RX path is disabled (default)
+ * @CEC_RX_MODE_DEFAULT:	accept only unicast traffic
+ * @CEC_RX_MODE_ACCEPT_ALL:	accept all incoming RX traffic (sniffing mode)
+ * @CEC_RX_MODE_MAX:		sentinel
+ */
+enum cec_rx_mode {
+	CEC_RX_MODE_DISABLED = 0,
+	CEC_RX_MODE_DEFAULT,
+	CEC_RX_MODE_ACCEPT_ALL,
+	CEC_RX_MODE_MAX
+};
+
+#endif /* __UAPI_HDMI_CEC_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/ipx.h	2020-02-08 00:30:24.656532666 +0100
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _IPX_H_
+#define _IPX_H_
+#include <linux/libc-compat.h>	/* for compatibility with glibc netipx/ipx.h */
+#include <linux/types.h>
+#include <linux/sockios.h>
+#include <linux/socket.h>
+#define IPX_NODE_LEN	6
+#define IPX_MTU		576
+
+#if __UAPI_DEF_SOCKADDR_IPX
+struct sockaddr_ipx {
+	__kernel_sa_family_t sipx_family;
+	__be16		sipx_port;
+	__be32		sipx_network;
+	unsigned char 	sipx_node[IPX_NODE_LEN];
+	__u8		sipx_type;
+	unsigned char	sipx_zero;	/* 16 byte fill */
+};
+#endif /* __UAPI_DEF_SOCKADDR_IPX */
+
+/*
+ * So we can fit the extra info for SIOCSIFADDR into the address nicely
+ */
+#define sipx_special	sipx_port
+#define sipx_action	sipx_zero
+#define IPX_DLTITF	0
+#define IPX_CRTITF	1
+
+#if __UAPI_DEF_IPX_ROUTE_DEFINITION
+struct ipx_route_definition {
+	__be32        ipx_network;
+	__be32        ipx_router_network;
+	unsigned char ipx_router_node[IPX_NODE_LEN];
+};
+#endif /* __UAPI_DEF_IPX_ROUTE_DEFINITION */
+
+#if __UAPI_DEF_IPX_INTERFACE_DEFINITION
+struct ipx_interface_definition {
+	__be32        ipx_network;
+	unsigned char ipx_device[16];
+	unsigned char ipx_dlink_type;
+#define IPX_FRAME_NONE		0
+#define IPX_FRAME_SNAP		1
+#define IPX_FRAME_8022		2
+#define IPX_FRAME_ETHERII	3
+#define IPX_FRAME_8023		4
+#define IPX_FRAME_TR_8022       5 /* obsolete */
+	unsigned char ipx_special;
+#define IPX_SPECIAL_NONE	0
+#define IPX_PRIMARY		1
+#define IPX_INTERNAL		2
+	unsigned char ipx_node[IPX_NODE_LEN];
+};
+#endif /* __UAPI_DEF_IPX_INTERFACE_DEFINITION */
+
+#if __UAPI_DEF_IPX_CONFIG_DATA
+struct ipx_config_data {
+	unsigned char	ipxcfg_auto_select_primary;
+	unsigned char	ipxcfg_auto_create_interfaces;
+};
+#endif /* __UAPI_DEF_IPX_CONFIG_DATA */
+
+/*
+ * OLD Route Definition for backward compatibility.
+ */
+
+#if __UAPI_DEF_IPX_ROUTE_DEF
+struct ipx_route_def {
+	__be32		ipx_network;
+	__be32		ipx_router_network;
+#define IPX_ROUTE_NO_ROUTER	0
+	unsigned char	ipx_router_node[IPX_NODE_LEN];
+	unsigned char	ipx_device[16];
+	unsigned short	ipx_flags;
+#define IPX_RT_SNAP		8
+#define IPX_RT_8022		4
+#define IPX_RT_BLUEBOOK		2
+#define IPX_RT_ROUTED		1
+};
+#endif /* __UAPI_DEF_IPX_ROUTE_DEF */
+
+#define SIOCAIPXITFCRT		(SIOCPROTOPRIVATE)
+#define SIOCAIPXPRISLT		(SIOCPROTOPRIVATE + 1)
+#define SIOCIPXCFGDATA		(SIOCPROTOPRIVATE + 2)
+#define SIOCIPXNCPCONN		(SIOCPROTOPRIVATE + 3)
+#endif /* _IPX_H_ */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/nlfbx.h	2024-01-12 13:49:05.006702363 +0100
@@ -0,0 +1,126 @@
+#ifndef __LINUX_NLFBX_H
+#define __LINUX_NLFBX_H
+
+/*
+ * Freebox netlink interface public header
+ *
+ * Copyright 2023 Freebox
+ */
+
+#include <linux/types.h>
+
+#define NLFBX_GENL_NAME "nlfbx"
+
+/**
+ * enum nlfbx_commands - supported nlfbx commands
+ *
+ * @NLFBX_CMD_UNSPEC: unspecified command to catch errors
+ *
+ * @NLFBX_CMD_CFG_STA_MONITOR: Configure unassociated STA monitor interface
+ * @NLFBX_CMD_ADD_STA_MONITOR: Add a new unasociated STA to monitor, needs
+ *	%NLFBX_ATTR_IFINDEX and %NLFBX_ATTR_MAC.
+ * @NLFBX_CMD_DEL_STA_MONITOR: Remove a new unasociated STA to monitor, needs
+ *	%NLFBX_ATTR_IFINDEX and %NLFBX_ATTR_MAC.
+ * @NLFBX_CMD_GET_STA_MONITOR: Dump info for all monitored unasociated STA,
+ *	a single monitor dev could be filtered with %NLFBX_ATTR_IFINDEX.
+ *
+ * @NLFBX_CMD_MAX: highest used command number
+ * @__NLFBX_CMD_AFTER_LAST: internal use
+ */
+enum nlfbx_commands {
+	NLFBX_CMD_UNSPEC,
+
+	NLFBX_CMD_CFG_STA_MONITOR,
+	NLFBX_CMD_ADD_STA_MONITOR,
+	NLFBX_CMD_DEL_STA_MONITOR,
+	NLFBX_CMD_GET_STA_MONITOR,
+
+	/* add new commands above here */
+
+	/* used to define NLFBX_CMD_MAX below */
+	__NLFBX_CMD_AFTER_LAST,
+	NLFBX_CMD_MAX = __NLFBX_CMD_AFTER_LAST - 1
+};
+
+/**
+ * enum nlfbx_attrs - nlfbx netlink attributes
+ *
+ * @NLFBX_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @NLFBX_ATTR_IFINDEX: network interface index of the device to operate on
+ * @NLFBX_ATTR_MAC: MAC address (various uses)
+ * @NLFBX_ATTR_SCUM_LIST_INFO: Same Channel Unassociated Metrics list
+ * @NLFBX_ATTR_DROP_FRAMES: Do not report frame to userland
+ */
+enum nlfbx_attrs {
+	NLFBX_ATTR_UNSPEC,
+	NLFBX_ATTR_IFINDEX,
+	NLFBX_ATTR_MAC,
+	NLFBX_ATTR_SCUM_INFO,
+	NLFBX_ATTR_SKIP_MONITOR,
+
+	/* add attributes here, update the policy in nlfbx.c */
+
+	__NLFBX_ATTR_AFTER_LAST,
+	NUM_NLFBX_ATTR = __NLFBX_ATTR_AFTER_LAST,
+	NLFBX_ATTR_MAX = __NLFBX_ATTR_AFTER_LAST - 1
+};
+
+/**
+ * enum nlfbx_scum_info_attrs - type of unassociated station information
+ *
+ * These describe the type of packets received to compute related unassociated
+ * station metrics.
+ *
+ * @NLFBX_ATTR_SCUM_INFO_UNSPEC: unspecified atttribute to catch errors
+ *
+ * @NLFBX_ATTR_SCUM_INFO_DATA: Unassociated station metrics for data packets
+ * @NLFBX_ATTR_SCUM_INFO_NONDATA: Unassociated station metrics for non data
+ *	packets
+ *
+ * @NLFBX_ATTR_SCUM_INFO_MAX: highest type of unassociated station infomartions
+ */
+enum nlfbx_scum_info_attrs {
+	NLFBX_ATTR_SCUM_INFO_UNSPEC,
+
+	NLFBX_ATTR_SCUM_INFO_DATA,
+	NLFBX_ATTR_SCUM_INFO_NONDATA,
+
+	__NLFBX_ATTR_SCUM_INFO_AFTER_LAST,
+	NUM_NLFBX_ATTR_SCUM_INFO = __NLFBX_ATTR_SCUM_INFO_AFTER_LAST,
+	NLFBX_ATTR_SCUM_INFO_MAX = __NLFBX_ATTR_SCUM_INFO_AFTER_LAST - 1,
+};
+
+/**
+ * enum nlfbx_scum_info_metrics - Type of unassociated station information
+ * metrics
+ *
+ * These attribute types are used within a %NLFBX_ATTR_SCUM_INFO_*
+ * when getting information about a station.
+ *
+ * @NLFBX_SCUM_INFO_METRICS_UNSPEC: attribute number 0 is reserved
+ *
+ * @NLFBX_SCUM_INFO_METRICS_SIGNAL: Average signal stength of PPDU monitored
+ * @NLFBX_SCUM_INFO_METRICS_BYTES: Total bytes monitored
+ * @NLFBX_SCUM_INFO_METRICS_PACKETS: Total number of packets monitored
+ * @NLFBX_SCUM_INFO_METRICS_INACTIVE_TIME: Time since last activity
+ *					      (u32, msecs)
+ *
+ * @__NLFBX_SCUM_INFO_METRICS_AFTER_LAST: internal
+ * @NLFBX_SCUM_LIST_INFO_ENTRY_MAX: highest possible scum info metrics attribute
+ */
+enum nlfbx_scum_info_metrics {
+	NLFBX_SCUM_INFO_METRICS_UNSPEC,
+
+	NLFBX_SCUM_INFO_METRICS_SIGNAL,
+	NLFBX_SCUM_INFO_METRICS_BYTES,
+	NLFBX_SCUM_INFO_METRICS_PACKETS,
+	NLFBX_SCUM_INFO_METRICS_INACTIVE_TIME,
+
+	/* keep last */
+	__NLFBX_SCUM_INFO_METRICS_AFTER_LAST,
+	NUM_NLFBX_SCUM_INFO_METRICS = __NLFBX_SCUM_INFO_METRICS_AFTER_LAST,
+	NLFBX_SCUM_INFO_METRICS_MAX = __NLFBX_SCUM_INFO_METRICS_AFTER_LAST - 1
+};
+
+#endif
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/nmeshd_nl.h	2023-03-04 02:08:41.992227542 +0100
@@ -0,0 +1,50 @@
+#ifndef __LINUX_NMESHD_NL_H
+#define __LINUX_NMESHD_NL_H
+
+#define NMESHD_NL_FAMILY "nmeshd_nl"
+#define NNL_MULTICAST_GROUP_MLME "nmeshd_nl_mlme"
+
+enum nmeshd_nl_commands {
+	NNL_CMD_MESH_PEER_PATH_METRICS = 1,
+	NNL_CMD_MESH_NODE_METRICS,
+	NNL_CMD_SET_MPP,
+	NNL_CMD_DEL_MPP,
+	NNL_CMD_MPLINK_BLOCK,
+	NNL_CMD_MPLINK_UNBLOCK,
+	NNL_CMD_DUMP_BLOCKED_MPLINK_INFO,
+	NNL_CMD_MPLINK_FLUSH,
+
+	NNL_CMD_AFTER_LAST,
+	NNL_CMD_MAX = NNL_CMD_AFTER_LAST - 1,
+};
+
+enum nmeshd_nl_attributes {
+	NNL_ATTR_IFINDEX = 1,
+	NNL_ATTR_IE_NODE_METRICS,
+	NNL_ATTR_IE_PATH_METRICS,
+	NNL_ATTR_WIPHY,
+	NNL_ATTR_IFNAME,
+	NNL_ATTR_MAC,
+	NNL_ATTR_FRAME_TYPE,
+	NNL_ATTR_SIGNAL_STRENGTH,
+	NNL_ATTR_BEACON_INTERVAL,
+	NNL_ATTR_MPP_PROXY,
+	NNL_ATTR_MPLINK_INFO,
+
+	NNL_ATTR_AFTER_LAST,
+	NNL_NUM_ATTR = NNL_ATTR_AFTER_LAST,
+	NNL_ATTR_MAX = NNL_ATTR_AFTER_LAST - 1,
+};
+
+#define QBC_VENDOR_IE NNL_CMD_AFTER_LAST
+
+enum mplink_info_attr {
+	__MPLINK_ATTR_INVALID,
+	NNL_MPLINK_ATTR_MAC,
+
+	/* keep last */
+	NNL_MPLINK_ATTR_AFTER_LAST,
+	NNL_MPLINK_ATTR_MAX = NNL_MPLINK_ATTR_AFTER_LAST - 1
+};
+
+#endif /* __LINUX_NMESHD_NL_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/include/uapi/linux/prctl-private.h	2023-11-29 17:07:13.768328291 +0100
@@ -0,0 +1,10 @@
+#ifndef _LINUX_PRCTL_PRIVATE_H
+#define _LINUX_PRCTL_PRIVATE_H
+
+/*
+ * Freebox addition: set/get exec mode.
+ */
+#define PR_SET_EXEC_MODE	69
+#define PR_GET_EXEC_MODE	70
+
+#endif /* ! _LINUX_PRCTL_PRIVATE_H */
diff -Nruw linux-6.4-fbx/include/uapi/linux/remoti./remoti.h linux-6.4-fbx/include/uapi/linux/remoti/remoti.h
--- linux-6.4-fbx/include/uapi/linux/remoti./remoti.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/include/uapi/linux/remoti/remoti.h	2013-12-04 14:33:25.391479076 +0100
@@ -0,0 +1,137 @@
+#ifndef _UAPI_REMOTI_H
+#define _UAPI_REMOTI_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/*
+ * subsystem definitions
+ */
+#define NPI_SYS_RES0		0
+#define NPI_SYS_SYS		1
+#define NPI_SYS_MAC		2
+#define NPI_SYS_NWK		3
+#define NPI_SYS_AF		4
+#define NPI_SYS_ZDO		5
+#define NPI_SYS_SAPI		6
+#define NPI_SYS_UTIL		7
+#define NPI_SYS_DBG		8
+#define NPI_SYS_APP		9
+#define NPI_SYS_RCAF		10
+#define NPI_SYS_RCN		11
+#define NPI_SYS_RCN_CLI		12
+#define NPI_SYS_BOOT		13
+#define NPI_SYS_MAX		14
+#define NPI_SYS_MASK		0x1F
+
+/*
+ * type definitions
+ */
+#define NPI_POLL		0
+#define NPI_SREQ		1
+#define NPI_AREQ		2
+#define NPI_SRSP		3
+#define NPI_TYPE_MAX		4
+#define NPI_TYPE_MASK		3
+#define NPI_TYPE_SHIFT		5
+
+
+/* common error codes (see RemoTI API) */
+#define RTI_SUCCESS		0x00
+
+/*
+ * rti user message
+ */
+#define NPI_MAX_DATA_LEN	123
+
+struct rti_msg {
+	__u8	type;
+	__u8	subsys;
+	__u8	cmd;
+
+	__u8	data_len;
+	__u8	data[NPI_MAX_DATA_LEN];
+
+	__u8	custom_reply_cmd;
+	__u8	reply_cmd;
+	__u8	reply_len;
+	__u8	reply[NPI_MAX_DATA_LEN];
+};
+
+/*
+ * socket addr family on "user" device
+ */
+#ifndef PF_REMOTI
+#define PF_REMOTI			37
+#define AF_REMOTI			PF_REMOTI
+#endif
+
+struct sockaddr_rti {
+	__u32	device_id;
+};
+
+#define SOL_REMOTI			280
+#define REMOTI_REGISTER_CB		0
+
+struct rti_callback {
+	__u8	subsys;
+	__u8	cmd;
+};
+
+/*
+ * ioctl on uart device
+ */
+enum rti_dev_state {
+	RTI_DEV_S_STOPPED = 0,
+	RTI_DEV_S_BOOTING,
+	RTI_DEV_S_BOOT_FAILED,
+	RTI_DEV_S_OPERATIONAL,
+	RTI_DEV_S_STOPPING,
+	RTI_DEV_S_DEAD,
+};
+
+struct rti_dev_status {
+	__u32	dev_state;
+	__u32	fw_version;
+};
+
+struct rti_dev_stats {
+	__u64	tx_bytes;
+	__u64	tx_packets;
+
+	__u64	tx_boot_packets;
+	__u64	tx_rcaf_packets;
+	__u64	tx_util_packets;
+	__u64	tx_other_packets;
+
+
+	__u64	rx_bytes;
+	__u64	rx_packets;
+	__u64	rx_bad_sof;
+	__u64	rx_len_errors;
+	__u64	rx_fcs_errors;
+	__u64	rx_tty_errors;
+	__u64	rx_full_errors;
+	__u64	rx_subsys_errors;
+	__u64	rx_type_errors;
+	__u64	rx_no_callback;
+
+	__u64	rx_boot_packets;
+	__u64	rx_rcaf_packets;
+	__u64	rx_util_packets;
+	__u64	rx_other_packets;
+};
+
+enum {
+	RTI_BOOT_FLAGS_FORCE_UPDATE	= (1 << 0),
+};
+
+#define RTI_IOCTL_MAGIC		0xd4
+#define RTI_ATTACH_DEVICE	_IOR(RTI_IOCTL_MAGIC, 1, __u32)
+#define RTI_GET_STATUS		_IOW(RTI_IOCTL_MAGIC, 2, struct rti_dev_status)
+#define RTI_GET_STATS		_IOW(RTI_IOCTL_MAGIC, 3, struct rti_dev_stats)
+
+#define RTI_START_DEVICE	_IOR(RTI_IOCTL_MAGIC, 8, __u32)
+#define RTI_STOP_DEVICE		_IO(RTI_IOCTL_MAGIC, 9)
+
+#endif /* _UAPI_REMOTI_H */
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/lib/fbxserial.c	2020-02-08 00:30:24.884534882 +0100
@@ -0,0 +1,178 @@
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include <linux/fbxserial.h>
+
+#define PFX "builtin-fbxserial: "
+
+static void __init
+fbxserialinfo_use_default(struct fbx_serial *serial)
+{
+	printk(KERN_WARNING PFX "warning: using default serial infos\n");
+	fbxserial_set_default(serial);
+}
+
+/*
+ * add trailing 0 for bundle string here.
+ */
+static void __init
+bundle_fixup(struct fbx_serial *serial)
+{
+	struct fbx_serial_extinfo *p;
+	int i;
+
+	for (i = 0; i < be32_to_cpu(serial->extinfo_count); i++) {
+
+		if (i >= EXTINFO_MAX_COUNT)
+			break;
+
+		p = &serial->extinfos[i];
+		if (be32_to_cpu(p->type) == EXTINFO_TYPE_EXTDEV &&
+		    be32_to_cpu(p->u.extdev.type) == EXTDEV_TYPE_BUNDLE) {
+			int size;
+
+			size = sizeof (p->u.extdev.serial);
+			p->u.extdev.serial[size - 1] = 0;
+		}
+	}
+}
+
+/*
+ * called from  arch code early  in the boot sequence.   This function
+ * returns 1  in case serial infos are  invalid/unreadable and default
+ * values have been used.
+ */
+int __init
+fbxserialinfo_read(const void *data, struct fbx_serial *out)
+{
+	uint32_t sum;
+
+	/*
+	 * get partial serial data from flash/whatever.
+	 */
+	memcpy(out, data, sizeof (*out));
+
+	/* check magic first */
+	if (be32_to_cpu(out->magic) != FBXSERIAL_MAGIC) {
+		printk(KERN_NOTICE PFX "invalid magic (%08x, expected %08x), "
+			"using defaults !\n", be32_to_cpu(out->magic),
+		       FBXSERIAL_MAGIC);
+		goto out_default;
+	}
+
+	/* fetch size for which we have to check CRC */
+	if (be32_to_cpu(out->len) > FBXSERIAL_MAX_SIZE) {
+		printk(KERN_NOTICE PFX "structure size too big (%d), "
+		       "using defaults !\n", be32_to_cpu(out->len));
+		goto out_default;
+	}
+
+	/* compute and check checksum */
+	sum = crc32(0, data + 4, be32_to_cpu(out->len) - 4);
+
+	if (be32_to_cpu(out->crc32) != sum) {
+		printk(KERN_NOTICE PFX "invalid checksum (%08x, "
+		       "expected %08x), using defaults !\n", sum,
+		       be32_to_cpu(out->crc32));
+		goto out_default;
+	}
+
+	printk(KERN_INFO PFX "Found valid serial infos !\n");
+	bundle_fixup(out);
+	return 0;
+
+ out_default:
+	fbxserialinfo_use_default(out);
+	bundle_fixup(out);
+	return 1;
+}
+
+void
+fbxserialinfo_get_random(unsigned char *data, unsigned int len)
+{
+	const struct fbx_serial *s;
+
+	memset(data, 0, 6);
+	s = arch_get_fbxserial();
+	if (WARN(!s, "arch_get_fbxserial returned NULL"))
+		return;
+
+	if (len > sizeof (s->random_data))
+		len = sizeof (s->random_data);
+
+	memcpy(data, s->random_data, len);
+}
+EXPORT_SYMBOL(fbxserialinfo_get_random);
+
+static u8 *mac_table;
+
+static void inc_mac(u8 *mac, int count)
+{
+	int index = 5;
+	int overflow;
+
+	do {
+		unsigned int val = mac[index] + count;
+
+		overflow = val >> 8;
+		mac[index] = val;
+		count = (count + 255) >> 8;
+		--index;
+	} while (index >= 0 && overflow);
+}
+
+static int gen_mac_table(const struct fbx_serial *s)
+{
+	int i;
+
+	mac_table = kmalloc(6 * s->mac_count, GFP_KERNEL);
+	if (!mac_table)
+		return -ENOMEM;
+
+	for (i = 0; i < s->mac_count; ++i) {
+		u8 *mac = &mac_table[6 * i];
+
+		memcpy(mac, s->mac_addr_base, 6);
+		inc_mac(mac, i);
+	}
+	return 0;
+}
+
+const void *
+fbxserialinfo_get_mac_addr(unsigned int index)
+{
+	const struct fbx_serial *s;
+
+	s = arch_get_fbxserial();
+
+	if (!s) {
+		pr_warn(PFX "no serial available: using default.\n");
+		goto default_mac;
+	}
+
+	if (index >= s->mac_count) {
+		pr_warn(PFX "mac index %d too high: using default.\n",
+			index);
+		goto default_mac;
+	}
+
+	if (!mac_table) {
+		int error = gen_mac_table(s);
+		if (error) {
+			pr_err(PFX "gen_mac_table() failed: using default.\n");
+			goto default_mac;
+		}
+	}
+
+	return &mac_table[6 * index];
+
+default_mac:
+	 return "\x00\x07\xcb\x00\x00\xfd";
+}
+EXPORT_SYMBOL(fbxserialinfo_get_mac_addr);
--- /dev/null	2024-02-29 19:25:32.507034555 +0100
+++ linux-6.4-fbx/net/core/gso.c	2023-11-29 17:07:14.101662142 +0100
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/skbuff.h>
+#include <linux/sctp.h>
+#include <net/gso.h>
+#include <net/gro.h>
+
+/**
+ *	skb_eth_gso_segment - segmentation handler for ethernet protocols.
+ *	@skb: buffer to segment
+ *	@features: features for the output path (see dev->features)
+ *	@type: Ethernet Protocol ID
+ */
+struct sk_buff *skb_eth_gso_segment(struct sk_buff *skb,
+				    netdev_features_t features, __be16 type)
+{
+	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
+	struct packet_offload *ptype;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ptype, &offload_base, list) {
+		if (ptype->type == type && ptype->callbacks.gso_segment) {
+			segs = ptype->callbacks.gso_segment(skb, features);
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return segs;
+}
+EXPORT_SYMBOL(skb_eth_gso_segment);
+
+/**
+ *	skb_mac_gso_segment - mac layer segmentation handler.
+ *	@skb: buffer to segment
+ *	@features: features for the output path (see dev->features)
+ */
+struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
+				    netdev_features_t features)
+{
+	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
+	struct packet_offload *ptype;
+	int vlan_depth = skb->mac_len;
+	__be16 type = skb_network_protocol(skb, &vlan_depth);
+
+	if (unlikely(!type))
+		return ERR_PTR(-EINVAL);
+
+	__skb_pull(skb, vlan_depth);
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ptype, &offload_base, list) {
+		if (ptype->type == type && ptype->callbacks.gso_segment) {
+			segs = ptype->callbacks.gso_segment(skb, features);
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	__skb_push(skb, skb->data - skb_mac_header(skb));
+
+	return segs;
+}
+EXPORT_SYMBOL(skb_mac_gso_segment);
+/* openvswitch calls this on rx path, so we need a different check.
+ */
+static bool skb_needs_check(const struct sk_buff *skb, bool tx_path)
+{
+	if (tx_path)
+		return skb->ip_summed != CHECKSUM_PARTIAL &&
+		       skb->ip_summed != CHECKSUM_UNNECESSARY;
+
+	return skb->ip_summed == CHECKSUM_NONE;
+}
+
+/**
+ *	__skb_gso_segment - Perform segmentation on skb.
+ *	@skb: buffer to segment
+ *	@features: features for the output path (see dev->features)
+ *	@tx_path: whether it is called in TX path
+ *
+ *	This function segments the given skb and returns a list of segments.
+ *
+ *	It may return NULL if the skb requires no segmentation.  This is
+ *	only possible when GSO is used for verifying header integrity.
+ *
+ *	Segmentation preserves SKB_GSO_CB_OFFSET bytes of previous skb cb.
+ */
+struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
+				  netdev_features_t features, bool tx_path)
+{
+	struct sk_buff *segs;
+
+	if (unlikely(skb_needs_check(skb, tx_path))) {
+		int err;
+
+		/* We're going to init ->check field in TCP or UDP header */
+		err = skb_cow_head(skb, 0);
+		if (err < 0)
+			return ERR_PTR(err);
+	}
+
+	/* Only report GSO partial support if it will enable us to
+	 * support segmentation on this frame without needing additional
+	 * work.
+	 */
+	if (features & NETIF_F_GSO_PARTIAL) {
+		netdev_features_t partial_features = NETIF_F_GSO_ROBUST;
+		struct net_device *dev = skb->dev;
+
+		partial_features |= dev->features & dev->gso_partial_features;
+		if (!skb_gso_ok(skb, features | partial_features))
+			features &= ~NETIF_F_GSO_PARTIAL;
+	}
+
+	BUILD_BUG_ON(SKB_GSO_CB_OFFSET +
+		     sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb));
+
+	SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb);
+	SKB_GSO_CB(skb)->encap_level = 0;
+
+	skb_reset_mac_header(skb);
+	skb_reset_mac_len(skb);
+
+	segs = skb_mac_gso_segment(skb, features);
+
+	if (segs != skb && unlikely(skb_needs_check(skb, tx_path) && !IS_ERR(segs)))
+		skb_warn_bad_offload(skb);
+
+	return segs;
+}
+EXPORT_SYMBOL(__skb_gso_segment);
+
+/**
+ * skb_gso_transport_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_transport_seglen is used to determine the real size of the
+ * individual segments, including Layer4 headers (TCP/UDP).
+ *
+ * The MAC/L2 or network (IP, IPv6) headers are not accounted for.
+ */
+static unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
+{
+	const struct skb_shared_info *shinfo = skb_shinfo(skb);
+	unsigned int thlen = 0;
+
+	if (skb->encapsulation) {
+		thlen = skb_inner_transport_header(skb) -
+			skb_transport_header(skb);
+
+		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
+			thlen += inner_tcp_hdrlen(skb);
+	} else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
+		thlen = tcp_hdrlen(skb);
+	} else if (unlikely(skb_is_gso_sctp(skb))) {
+		thlen = sizeof(struct sctphdr);
+	} else if (shinfo->gso_type & SKB_GSO_UDP_L4) {
+		thlen = sizeof(struct udphdr);
+	}
+	/* UFO sets gso_size to the size of the fragmentation
+	 * payload, i.e. the size of the L4 (UDP) header is already
+	 * accounted for.
+	 */
+	return thlen + shinfo->gso_size;
+}
+
+/**
+ * skb_gso_network_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_network_seglen is used to determine the real size of the
+ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
+ *
+ * The MAC/L2 header is not accounted for.
+ */
+static unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
+{
+	unsigned int hdr_len = skb_transport_header(skb) -
+			       skb_network_header(skb);
+
+	return hdr_len + skb_gso_transport_seglen(skb);
+}
+
+/**
+ * skb_gso_mac_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_mac_seglen is used to determine the real size of the
+ * individual segments, including MAC/L2, Layer3 (IP, IPv6) and L4
+ * headers (TCP/UDP).
+ */
+static unsigned int skb_gso_mac_seglen(const struct sk_buff *skb)
+{
+	unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
+
+	return hdr_len + skb_gso_transport_seglen(skb);
+}
+
+/**
+ * skb_gso_size_check - check the skb size, considering GSO_BY_FRAGS
+ *
+ * There are a couple of instances where we have a GSO skb, and we
+ * want to determine what size it would be after it is segmented.
+ *
+ * We might want to check:
+ * -    L3+L4+payload size (e.g. IP forwarding)
+ * - L2+L3+L4+payload size (e.g. sanity check before passing to driver)
+ *
+ * This is a helper to do that correctly considering GSO_BY_FRAGS.
+ *
+ * @skb: GSO skb
+ *
+ * @seg_len: The segmented length (from skb_gso_*_seglen). In the
+ *           GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS].
+ *
+ * @max_len: The maximum permissible length.
+ *
+ * Returns true if the segmented length <= max length.
+ */
+static inline bool skb_gso_size_check(const struct sk_buff *skb,
+				      unsigned int seg_len,
+				      unsigned int max_len) {
+	const struct skb_shared_info *shinfo = skb_shinfo(skb);
+	const struct sk_buff *iter;
+
+	if (shinfo->gso_size != GSO_BY_FRAGS)
+		return seg_len <= max_len;
+
+	/* Undo this so we can re-use header sizes */
+	seg_len -= GSO_BY_FRAGS;
+
+	skb_walk_frags(skb, iter) {
+		if (seg_len + skb_headlen(iter) > max_len)
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * skb_gso_validate_network_len - Will a split GSO skb fit into a given MTU?
+ *
+ * @skb: GSO skb
+ * @mtu: MTU to validate against
+ *
+ * skb_gso_validate_network_len validates if a given skb will fit a
+ * wanted MTU once split. It considers L3 headers, L4 headers, and the
+ * payload.
+ */
+bool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu)
+{
+	return skb_gso_size_check(skb, skb_gso_network_seglen(skb), mtu);
+}
+EXPORT_SYMBOL_GPL(skb_gso_validate_network_len);
+
+/**
+ * skb_gso_validate_mac_len - Will a split GSO skb fit in a given length?
+ *
+ * @skb: GSO skb
+ * @len: length to validate against
+ *
+ * skb_gso_validate_mac_len validates if a given skb will fit a wanted
+ * length once split, including L2, L3 and L4 headers and the payload.
+ */
+bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len)
+{
+	return skb_gso_size_check(skb, skb_gso_mac_seglen(skb), len);
+}
+EXPORT_SYMBOL_GPL(skb_gso_validate_mac_len);
+
diff -Nruw linux-6.4-fbx/net/fbxatm./Kconfig linux-6.4-fbx/net/fbxatm/Kconfig
--- linux-6.4-fbx/net/fbxatm./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/net/fbxatm/Kconfig	2020-02-08 00:30:25.088536864 +0100
@@ -0,0 +1,28 @@
+menuconfig FBXATM
+	tristate "Freebox Asynchronous Transfer Mode (ATM)"
+
+if FBXATM
+
+config FBXATM_REMOTE
+	bool
+
+choice
+	prompt "mode"
+	default FBXATM_STACK
+
+config FBXATM_STACK
+	bool "standard"
+
+config FBXATM_REMOTE_STUB
+	bool "remote stub"
+	select FBXATM_REMOTE
+
+endchoice
+
+config FBXATM_REMOTE_DRIVER
+	tristate "remote fbxatm driver"
+	depends on FBXATM_STACK
+	select FBXATM_REMOTE
+	select OF
+
+endif
diff -Nruw linux-6.4-fbx/net/fbxbridge./Kconfig linux-6.4-fbx/net/fbxbridge/Kconfig
--- linux-6.4-fbx/net/fbxbridge./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/net/fbxbridge/Kconfig	2020-02-08 00:30:25.088536864 +0100
@@ -0,0 +1,8 @@
+
+#
+# Freebox bridge
+#
+config FBXBRIDGE
+	bool "Freebox Bridge"
+	select NETFILTER
+	select NF_CONNTRACK
diff -Nruw linux-6.4-fbx/net/mac80211/tests./Makefile linux-6.4-fbx/net/mac80211/tests/Makefile
--- linux-6.4-fbx/net/mac80211/tests./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/net/mac80211/tests/Makefile	2023-11-29 17:07:14.211662313 +0100
@@ -0,0 +1,3 @@
+mac80211-tests-y += module.o elems.o
+
+obj-$(CONFIG_MAC80211_KUNIT_TEST) += mac80211-tests.o
diff -Nruw linux-6.4-fbx/net/wireless/tests./Makefile linux-6.4-fbx/net/wireless/tests/Makefile
--- linux-6.4-fbx/net/wireless/tests./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-6.4-fbx/net/wireless/tests/Makefile	2023-11-29 17:07:14.354995869 +0100
@@ -0,0 +1,3 @@
+cfg80211-tests-y += module.o fragmentation.o
+
+obj-$(CONFIG_CFG80211_KUNIT_TEST) += cfg80211-tests.o
