Quantenna Linux 4.7 from sdk-v37.4.1.89
find . -name '.git' -prune -o -type f ! -name '.*' -exec rm '{}' +
cp -pr
/usr/local/google/home/danielmentz/hdd1/quantenna-sdk-v37.4.1.89.pristine/linux-4.7.0/*
.
diff --git a/Makefile b/Makefile
index 66da9a3..06e1720 100644
--- a/Makefile
+++ b/Makefile
@@ -773,7 +773,7 @@
CHECKFLAGS += $(NOSTDINC_FLAGS)
# warn about C99 declaration after statement
-KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
+#KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
# disable pointer signed / unsigned warnings in gcc 4.0
KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign)
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 0d3e59f..374aaf5 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -93,11 +93,10 @@
menu "ARC Platform/SoC/Board"
-source "arch/arc/plat-sim/Kconfig"
-source "arch/arc/plat-tb10x/Kconfig"
-source "arch/arc/plat-axs10x/Kconfig"
#New platform adds here
-source "arch/arc/plat-eznps/Kconfig"
+source "arch/arc/plat-qtn/Kconfig"
+source "../drivers/ruby/Kconfig"
+source "../drivers/topaz/Kconfig"
endmenu
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 85814e7..9e0727e 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -8,6 +8,9 @@
UTS_MACHINE := arc
+PLATFORM := ruby
+export PLATFORM
+
ifeq ($(CROSS_COMPILE),)
ifndef CONFIG_CPU_BIG_ENDIAN
CROSS_COMPILE := arc-linux-
@@ -16,7 +19,7 @@
endif
endif
-KBUILD_DEFCONFIG := nsim_700_defconfig
+KBUILD_DEFCONFIG := fpga_defconfig
cflags-y += -fno-common -pipe -fno-builtin -D__linux__
cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7
@@ -42,6 +45,9 @@
# any kernel headers, and missing the r25 global register
# Can't do unconditionally because of recursive include issues
# due to <linux/thread_info.h>
+LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h -I$(srctree)/../ -I$(srctree)/../include/
+LINUXINCLUDE += -include $(src)/../common/ruby_mem.h
+LINUXINCLUDE += -include $(src)/../common/current_platform.h -include $(src)/../common/common_mem.h
LINUXINCLUDE += -include ${src}/arch/arc/include/asm/current.h
endif
@@ -66,6 +72,8 @@
endif
+cflags-$(CONFIG_ARC_DW2_UNWIND) += -fasynchronous-unwind-tables
+
# By default gcc 4.8 generates dwarf4 which kernel unwinder can't grok
ifeq ($(atleast_gcc48),y)
cflags-$(CONFIG_ARC_DW2_UNWIND) += -gdwarf-2
@@ -99,8 +107,15 @@
# Finally dump eveything into kernel build system
KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -Iarch/arc/include/asm/board-$(PLATFORM)
KBUILD_AFLAGS += $(KBUILD_CFLAGS)
LDFLAGS += $(ldflags-y)
+KBUILD_CFLAGS += -I../drivers/include/kernel
+KBUILD_CFLAGS += -I../drivers/include/shared
+
+ifdef CONFIG_ARC_PLAT_QTN
+KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-qtn/include/
+endif
head-y := arch/arc/kernel/head.o
@@ -110,13 +125,16 @@
# w/o this dtb won't embed into kernel binary
core-y += arch/arc/boot/dts/
-core-$(CONFIG_ARC_PLAT_SIM) += arch/arc/plat-sim/
-core-$(CONFIG_ARC_PLAT_TB10X) += arch/arc/plat-tb10x/
-core-$(CONFIG_ARC_PLAT_AXS10X) += arch/arc/plat-axs10x/
-core-$(CONFIG_ARC_PLAT_EZNPS) += arch/arc/plat-eznps/
+core-$(CONFIG_ARC_PLAT_QTN) += arch/arc/plat-qtn/
-ifdef CONFIG_ARC_PLAT_EZNPS
-KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include
+ifdef CONFIG_ARC_PLAT_QTN
+ARCH_CFLAGS += -mmedium-calls
+endif
+
+drivers-$(CONFIG_QUANTENNA_RUBY) += ../drivers/ruby/
+
+ifeq ($(CONFIG_QUANTENNA_TOPAZ),y)
+drivers-$(CONFIG_QUANTENNA_TOPAZ) += ../drivers/topaz/
endif
drivers-$(CONFIG_OPROFILE) += arch/arc/oprofile/
@@ -126,12 +144,14 @@
boot := arch/arc/boot
#default target for make without any arguments.
-KBUILD_IMAGE := bootpImage
+KBUILD_IMAGE := Image
all: $(KBUILD_IMAGE)
-bootpImage: vmlinux
-boot_targets += uImage uImage.bin uImage.gz
+bootpImage:= vmlinux
+bzImage: zImage
+
+boot_targets += zImage Image uImage uImage.bin uImage.gz xipImage
$(boot_targets): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
@@ -145,6 +165,9 @@
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
+archheaders:
+ $(Q)ln -fsn board-ruby ${src}/arch/arc/include/asm/board
+
# Hacks to enable final link due to absence of link-time branch relexation
# and gcc choosing optimal(shorter) branches at -O3
#
diff --git a/arch/arc/boot/Makefile b/arch/arc/boot/Makefile
index e597cb34..cfccf2e 100644
--- a/arch/arc/boot/Makefile
+++ b/arch/arc/boot/Makefile
@@ -1,35 +1,62 @@
-targets := vmlinux.bin vmlinux.bin.gz uImage
+#
+#
+# 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.
+#
+# Copyright (C) 2003 ARC International
+#
-# uImage build relies on mkimage being availble on your host for ARC target
-# You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
-# and make sure it's reacable from your PATH
-OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S
+SYSTEM =$(srctree)/vmlinux
-LINUX_START_TEXT = $$(readelf -h vmlinux | \
- grep "Entry point address" | grep -o 0x.*)
+#obj-y += initrd.o
-UIMAGE_LOADADDR = $(CONFIG_LINUX_LINK_BASE)
-UIMAGE_ENTRYADDR = $(LINUX_START_TEXT)
+MKIMAGE =mkimage
+MKIMAGEFLAGS =-A arc -O linux -C none -T kernel -a 0x80000000 -e 0x80002000 -n "ARC700 Linux kernel" -d Image
+OBJCOPYFLAGS =-O binary -R .note -R .comment -S vmlinux
-suffix-y := bin
-suffix-$(CONFIG_KERNEL_GZIP) := gz
+# From Beta's doc:
+# ZTEXTADDR - Address where zImage is located by the bootloader
+# ZRELADDR - Address where the zImage will be relocated
+# PARAMS_PHYS - Address where tagged parameters are to be found
+# INITRD_PHYS - Physical Address of the Ramdisk
+# ZBSSADDR - Address where the real kernel should execute from
-targets += uImage uImage.bin uImage.gz
-extra-y += vmlinux.bin vmlinux.bin.gz
+#not very sure as to what to fill here...
-$(obj)/vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
+ZRELADDR = 0x00000000 # where to relocate it... hmmm....
+ZTEXTADDR = 0x00000000 # we'll put the kernel image here for now...
+#endif
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
- $(call if_changed,gzip)
-$(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE
- $(call if_changed,uimage,none)
+#
+# If you don't define ZRELADDR above,
+# then it defaults to ZTEXTADDR
+#
+ifeq ($(ZRELADDR),)
+ZRELADDR = $(ZTEXTADDR)
+endif
-$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE
- $(call if_changed,uimage,gzip)
+export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR
-$(obj)/uImage: $(obj)/uImage.$(suffix-y)
- @ln -sf $(notdir $<) $@
- @echo ' Image $@ is ready'
+targets := uImage
+
+#arch/arc/boot/bootpImage: $(SYSTEM)
+# cp -f $(SYSTEM) $@
+
+$(obj)/Image: vmlinux
+ $(OBJCOPY) $(OBJCOPYFLAGS) $@
+
+Image: bootpImage
+ $(OBJCOPY) $(OBJCOPYFLAGS) $@
+
+uImage: Image
+ $(MKIMAGE) $(MKIMAGEFLAGS) $@
+clean:
+ $(RM) Image zImage bootpImage initrd.c jffsimg.c
+ #@$(MAKE) -C compressed clean
+
+
+dep:
+
diff --git a/arch/arc/boot/dts/topaz.dts b/arch/arc/boot/dts/topaz.dts
new file mode 100644
index 0000000..dee273d
--- /dev/null
+++ b/arch/arc/boot/dts/topaz.dts
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "qtn,qsr1000";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&core_intc>;
+
+ chosen {
+ bootargs = "earlyprintk=1 debug console=ttyS0,115200n8 print-fatal-signals=1";
+/* bootargs = "earlycon debug console=ttyS0,115200n8";*/
+ stdout-path = &uart0;
+ };
+ memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x00000000 0x80000000 0x40000000>;
+ device_type = "memory";
+ reg = <0x80000000 0x08000000>; /* 128MiB */
+ };
+ core_clk: core_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <500000000>;
+ /* 500 MHZ */
+ };
+
+ core_intc: arc700-intc@cpu {
+ compatible = "snps,arc700-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ uart0: dw-apb-uart {
+/* compatible = "snps,dw-apb-uart", "ns16550";*/
+ compatible = "snps,dw-apb-uart", "ns16550a";
+ reg = <0xF0000000 0x100>;
+ clock-frequency = <125000000>;
+ interrupt-parent = <&core_intc>;
+ interrupts = <24>;
+ baud = <115200>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+/* pcie: pcie@e9000000 {*/
+/* compatible = "snps,dw-pcie";*/
+/* reg = <0xe9000000 0x2000>,*/
+ /* Controller registers */
+/* <0xcf000000 0x10000>;*/
+ /* PCI config space */
+/* reg-names = "ctrlreg", "config";*/
+/* device_type = "pci";*/
+/* num-lanes = <1>;*/
+/* interrupt-parent = <&core_intc>;*/
+/* interrupts = <28>, <18>;*/
+/* #address-cells = <3>;*/
+/* #size-cells = <2>;*/
+/* ranges = <0x82000000 0 0xc0000000 0xc0000000 0 0x01000000*/
+/* 0x83000000 0 0xc1000000 0xc1000000 0 0x01000000>;*/
+/* #interrupt-cells = <1>;*/
+/* interrupt-map-mask = <0x0 0 0 1>;*/
+/* interrupt-map = <0x0 0 0 1 &core_intc 28>;*/
+/* };*/
+};
diff --git a/arch/arc/configs/topaz_config b/arch/arc/configs/topaz_config
new file mode 100644
index 0000000..3d5c929
--- /dev/null
+++ b/arch/arc/configs/topaz_config
@@ -0,0 +1,1818 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arc 4.7.0 Kernel Configuration
+#
+CONFIG_ARC=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_MMU=y
+CONFIG_NO_IOPORT_MAP=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_QTN_PLATFORM_MISALIGN_WAR=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE="/usr/local/arcgcc48/bin/arc-linux-uclibc-"
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_USELIB is not set
+# CONFIG_AUDIT is not set
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_GENERIC_CLOCKEVENTS=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 is not set
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../buildroot/rootfs.arc-linux-uclibc.cpio"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# 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_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN=y
+CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+# CONFIG_SYSFS_SYSCALL is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_HAVE_FUTEX_CMPXCHG=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_ADVISE_SYSCALLS is not set
+# CONFIG_USERFAULTFD is not set
+# CONFIG_PCI_QUIRKS is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_CLK=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_PGTABLE_LEVELS=2
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CPU_NO_EFFICIENT_FFS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_FREEZER is not set
+
+#
+# ARC Architecture Configuration
+#
+
+#
+# ARC Platform/SoC/Board
+#
+CONFIG_ARC_PLAT_QTN=y
+CONFIG_QTN_PLATFORM_MISALIGN_WAR=y
+CONFIG_ARCH_QSR1000=y
+
+#
+# Quantenna
+#
+CONFIG_QUANTENNA_RUBY=y
+CONFIG_ARCH_RUBY_NUMA=y
+CONFIG_QVSP=y
+# CONFIG_RUBY_PCIE_TARGET is not set
+# CONFIG_RUBY_PCIE_HOST is not set
+# CONFIG_TOPAZ_PCIE_TARGET is not set
+# CONFIG_TOPAZ_PCIE_HOST is not set
+CONFIG_PCIEPORTBUS=y
+# CONFIG_TOPAZ_DBDC_HOST is not set
+# CONFIG_KERNEL_TEXT_SNAPSHOTS is not set
+CONFIG_ARCH_RUBY_EMAC_LIB=m
+CONFIG_ARCH_RUBY_EMAC=m
+CONFIG_ARCH_RUBY_EMAC_SMOOTHING=y
+CONFIG_ARCH_RUBY_EMAC_SMOOTHING_BURST_SIZE=48
+CONFIG_ARCH_RUBY_EMAC_SMOOTHING_RATE=50000
+# CONFIG_QUANTENNA_RESTRICT_WLAN_IP is not set
+# CONFIG_SWITCH_RTL8365MB is not set
+CONFIG_SWITCH_RTL8363SB=m
+# CONFIG_QTN_SKB_RECYCLE is not set
+
+#
+# Quantenna Topaz
+#
+CONFIG_QUANTENNA_TOPAZ=y
+CONFIG_ARCH_TOPAZ_FWT=m
+CONFIG_ARCH_TOPAZ_TQE=m
+# CONFIG_ARCH_TOPAZ_SWITCH_TEST is not set
+CONFIG_ARCH_TOPAZ_EMAC=m
+CONFIG_ISA_ARCOMPACT=y
+# CONFIG_ISA_ARCV2 is not set
+
+#
+# ARC CPU Configuration
+#
+CONFIG_ARC_CPU_750D=y
+# CONFIG_ARC_CPU_770 is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SMP is not set
+CONFIG_ARC_CACHE=y
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_ARC_HAS_ICACHE=y
+CONFIG_ARC_HAS_DCACHE=y
+CONFIG_ARC_CACHE_PAGES=y
+# CONFIG_ARC_CACHE_VIPT_ALIASING is not set
+# CONFIG_ARC_HAS_ICCM is not set
+# CONFIG_ARC_HAS_DCCM is not set
+# CONFIG_ARC_MMU_V1 is not set
+CONFIG_ARC_MMU_V2=y
+CONFIG_ARC_PAGE_SIZE_8K=y
+# CONFIG_ARC_COMPACT_IRQ_LEVELS is not set
+# CONFIG_ARC_FPU_SAVE_RESTORE is not set
+CONFIG_ARC_CANT_LLSC=y
+# CONFIG_ARC_HAS_SWAPE is not set
+CONFIG_LINUX_LINK_BASE=0x80000000
+# CONFIG_HIGHMEM is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARC_PLAT_NEEDS_PHYS_TO_DMA=y
+CONFIG_ARC_KVADDR_SIZE=64
+CONFIG_ARC_CURR_IN_REG=y
+CONFIG_ARC_EMUL_UNALIGNED=y
+CONFIG_HZ=200
+# CONFIG_ARC_METAWARE_HLINK is not set
+CONFIG_ARC_DBG=y
+CONFIG_ARC_DW2_UNWIND=y
+# CONFIG_ARC_DBG_TLB_PARANOIA is not set
+# CONFIG_ARC_DBG_TLB_MISS_COUNT is not set
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_ARC_BUILTIN_DTB_NAME="topaz"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY 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_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER 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_STP=y
+CONFIG_BRIDGE=y
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q_MVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX 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=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+# CONFIG_NET_SCH_FQ is not set
+# CONFIG_NET_SCH_HHF is not set
+# CONFIG_NET_SCH_PIE is not set
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_BPF is not set
+# CONFIG_NET_CLS_FLOWER is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+# 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_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_PRIV=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX 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_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+# CONFIG_DEVTMPFS_MOUNT is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_FW_LOADER_USER_HELPER=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# 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_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# 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_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_SPI_NOR is not set
+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=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_ADDRESS_PCI=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_MTD=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OF_RESOLVE=y
+CONFIG_OF_OVERLAY=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_BLK_DEV_NVME is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# 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_BH1780 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_BMP085_I2C is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_SRAM 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_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER 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_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER 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
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+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_ALTEON is not set
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMD is not set
+CONFIG_NET_VENDOR_ARC=y
+# CONFIG_ARC_EMAC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE 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_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_EZCHIP is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_JME 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_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI 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_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_RDC 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_SFC is not set
+# CONFIG_NET_VENDOR_SMSC 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_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Host-side USB support is needed for USB Network Adapter support
+#
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# 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 is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI 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 is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+# CONFIG_SERIAL_8250_FSL is not set
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_RT288X is not set
+# CONFIG_SERIAL_8250_MOXA is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+
+#
+# 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_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_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_CONEXANT_DIGICOLOR is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# 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_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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
+
+#
+# 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_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_PCI is not set
+# 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_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# 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
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_OF_GPIO=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_VX855 is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+
+#
+# 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_RDC321X is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 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_AXP20X_I2C 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_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_INTEL_SOC_PMIC 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_MAX77686 is not set
+# CONFIG_MFD_MAX77693 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_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_RT5033 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_SMSC is not set
+# CONFIG_ABX500_CORE 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_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_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS80031 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_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_VX855 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_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGA_ARB is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 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_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+# CONFIG_COMMON_CLK_OXNAS is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# 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_VME_BUS is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_DW_APB_ICTL=y
+# CONFIG_EZNPS_GIC is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+CONFIG_RAS=y
+# CONFIG_THUNDERBOLT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+CONFIG_NVMEM=y
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Bus Support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEAER is not set
+# CONFIG_PCIEASPM is not set
+# CONFIG_PCIE_DPC is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCI host controller drivers
+#
+# CONFIG_PCIE_DW_PLAT is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_DAX is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_FS_ENCRYPTION is not set
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# 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 is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# 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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT 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_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_TRACING_EVENTS_GPIO is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_UBSAN is not set
+# CONFIG_16KSTACKS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+# CONFIG_CRYPTO_RSA is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 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 is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# 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
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+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
+# 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
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+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_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+# CONFIG_PM is not set
diff --git a/arch/arc/configs/topaz_umm_config b/arch/arc/configs/topaz_umm_config
new file mode 100644
index 0000000..3d5c929
--- /dev/null
+++ b/arch/arc/configs/topaz_umm_config
@@ -0,0 +1,1818 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arc 4.7.0 Kernel Configuration
+#
+CONFIG_ARC=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_MMU=y
+CONFIG_NO_IOPORT_MAP=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_QTN_PLATFORM_MISALIGN_WAR=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE="/usr/local/arcgcc48/bin/arc-linux-uclibc-"
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_USELIB is not set
+# CONFIG_AUDIT is not set
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_GENERIC_CLOCKEVENTS=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 is not set
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../buildroot/rootfs.arc-linux-uclibc.cpio"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# 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_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN=y
+CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+# CONFIG_SYSFS_SYSCALL is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_HAVE_FUTEX_CMPXCHG=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_ADVISE_SYSCALLS is not set
+# CONFIG_USERFAULTFD is not set
+# CONFIG_PCI_QUIRKS is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_CLK=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_PGTABLE_LEVELS=2
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CPU_NO_EFFICIENT_FFS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_FREEZER is not set
+
+#
+# ARC Architecture Configuration
+#
+
+#
+# ARC Platform/SoC/Board
+#
+CONFIG_ARC_PLAT_QTN=y
+CONFIG_QTN_PLATFORM_MISALIGN_WAR=y
+CONFIG_ARCH_QSR1000=y
+
+#
+# Quantenna
+#
+CONFIG_QUANTENNA_RUBY=y
+CONFIG_ARCH_RUBY_NUMA=y
+CONFIG_QVSP=y
+# CONFIG_RUBY_PCIE_TARGET is not set
+# CONFIG_RUBY_PCIE_HOST is not set
+# CONFIG_TOPAZ_PCIE_TARGET is not set
+# CONFIG_TOPAZ_PCIE_HOST is not set
+CONFIG_PCIEPORTBUS=y
+# CONFIG_TOPAZ_DBDC_HOST is not set
+# CONFIG_KERNEL_TEXT_SNAPSHOTS is not set
+CONFIG_ARCH_RUBY_EMAC_LIB=m
+CONFIG_ARCH_RUBY_EMAC=m
+CONFIG_ARCH_RUBY_EMAC_SMOOTHING=y
+CONFIG_ARCH_RUBY_EMAC_SMOOTHING_BURST_SIZE=48
+CONFIG_ARCH_RUBY_EMAC_SMOOTHING_RATE=50000
+# CONFIG_QUANTENNA_RESTRICT_WLAN_IP is not set
+# CONFIG_SWITCH_RTL8365MB is not set
+CONFIG_SWITCH_RTL8363SB=m
+# CONFIG_QTN_SKB_RECYCLE is not set
+
+#
+# Quantenna Topaz
+#
+CONFIG_QUANTENNA_TOPAZ=y
+CONFIG_ARCH_TOPAZ_FWT=m
+CONFIG_ARCH_TOPAZ_TQE=m
+# CONFIG_ARCH_TOPAZ_SWITCH_TEST is not set
+CONFIG_ARCH_TOPAZ_EMAC=m
+CONFIG_ISA_ARCOMPACT=y
+# CONFIG_ISA_ARCV2 is not set
+
+#
+# ARC CPU Configuration
+#
+CONFIG_ARC_CPU_750D=y
+# CONFIG_ARC_CPU_770 is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_SMP is not set
+CONFIG_ARC_CACHE=y
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_ARC_HAS_ICACHE=y
+CONFIG_ARC_HAS_DCACHE=y
+CONFIG_ARC_CACHE_PAGES=y
+# CONFIG_ARC_CACHE_VIPT_ALIASING is not set
+# CONFIG_ARC_HAS_ICCM is not set
+# CONFIG_ARC_HAS_DCCM is not set
+# CONFIG_ARC_MMU_V1 is not set
+CONFIG_ARC_MMU_V2=y
+CONFIG_ARC_PAGE_SIZE_8K=y
+# CONFIG_ARC_COMPACT_IRQ_LEVELS is not set
+# CONFIG_ARC_FPU_SAVE_RESTORE is not set
+CONFIG_ARC_CANT_LLSC=y
+# CONFIG_ARC_HAS_SWAPE is not set
+CONFIG_LINUX_LINK_BASE=0x80000000
+# CONFIG_HIGHMEM is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARC_PLAT_NEEDS_PHYS_TO_DMA=y
+CONFIG_ARC_KVADDR_SIZE=64
+CONFIG_ARC_CURR_IN_REG=y
+CONFIG_ARC_EMUL_UNALIGNED=y
+CONFIG_HZ=200
+# CONFIG_ARC_METAWARE_HLINK is not set
+CONFIG_ARC_DBG=y
+CONFIG_ARC_DW2_UNWIND=y
+# CONFIG_ARC_DBG_TLB_PARANOIA is not set
+# CONFIG_ARC_DBG_TLB_MISS_COUNT is not set
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_ARC_BUILTIN_DTB_NAME="topaz"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY 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_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER 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_STP=y
+CONFIG_BRIDGE=y
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q_MVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX 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=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_CODEL is not set
+# CONFIG_NET_SCH_FQ_CODEL is not set
+# CONFIG_NET_SCH_FQ is not set
+# CONFIG_NET_SCH_HHF is not set
+# CONFIG_NET_SCH_PIE is not set
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_BPF is not set
+# CONFIG_NET_CLS_FLOWER is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+# 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_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_PRIV=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX 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_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+# CONFIG_DEVTMPFS_MOUNT is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_FW_LOADER_USER_HELPER=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# 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_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# 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_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_SPI_NOR is not set
+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=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_ADDRESS_PCI=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_MTD=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OF_RESOLVE=y
+CONFIG_OF_OVERLAY=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_BLK_DEV_NVME is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# 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_BH1780 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_BMP085_I2C is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_SRAM 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_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+CONFIG_BONDING=m
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER 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_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER 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
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+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_ALTEON is not set
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMD is not set
+CONFIG_NET_VENDOR_ARC=y
+# CONFIG_ARC_EMAC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE 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_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_EZCHIP is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_JME 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_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI 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_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_RDC 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_SFC is not set
+# CONFIG_NET_VENDOR_SMSC 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_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Host-side USB support is needed for USB Network Adapter support
+#
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# 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 is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI 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 is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+# CONFIG_SERIAL_8250_FSL is not set
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_RT288X is not set
+# CONFIG_SERIAL_8250_MOXA is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+
+#
+# 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_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_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_CONEXANT_DIGICOLOR is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# 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_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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
+
+#
+# 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_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_PCI is not set
+# 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_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# 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
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_OF_GPIO=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_VX855 is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+
+#
+# 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_RDC321X is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 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_AXP20X_I2C 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_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_INTEL_SOC_PMIC 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_MAX77686 is not set
+# CONFIG_MFD_MAX77693 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_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_RT5033 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_SMSC is not set
+# CONFIG_ABX500_CORE 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_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_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS80031 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_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_VX855 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_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGA_ARB is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 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_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+# CONFIG_COMMON_CLK_OXNAS is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# 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_VME_BUS is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_DW_APB_ICTL=y
+# CONFIG_EZNPS_GIC is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+CONFIG_RAS=y
+# CONFIG_THUNDERBOLT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+CONFIG_NVMEM=y
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Bus Support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEAER is not set
+# CONFIG_PCIEASPM is not set
+# CONFIG_PCIE_DPC is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCI host controller drivers
+#
+# CONFIG_PCIE_DW_PLAT is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_DAX is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_FS_ENCRYPTION is not set
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# 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 is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# 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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT 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_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_TRACING_EVENTS_GPIO is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_UBSAN is not set
+# CONFIG_16KSTACKS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+# CONFIG_CRYPTO_RSA is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 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 is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# 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
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+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
+# 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
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+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_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+# CONFIG_PM is not set
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 7fbaea0..bed7fbd 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -15,6 +15,7 @@
#define ARC_REG_CRC_BCR 0x62
#define ARC_REG_VECBASE_BCR 0x68
#define ARC_REG_PERIBASE_BCR 0x69
+#define ARC_REG_DATA_UNCACHED 0x6a
#define ARC_REG_FP_BCR 0x6B /* ARCompact: Single-Precision FPU */
#define ARC_REG_DPFP_BCR 0x6C /* ARCompact: Dbl Precision FPU */
#define ARC_REG_FP_V2_BCR 0xc8 /* ARCv2 FPU */
@@ -40,16 +41,27 @@
#define ARC_REG_AUX_ICCM 0x208 /* ICCM Base Addr (ARCv2) */
/* status32 Bits Positions */
+#define STATUS_H_BIT 0
+#define STATUS_E1_BIT 1
+#define STATUS_E2_BIT 2
+#define STATUS_A1_BIT 3
+#define STATUS_A2_BIT 4
#define STATUS_AE_BIT 5 /* Exception active */
#define STATUS_DE_BIT 6 /* PC is in delay slot */
#define STATUS_U_BIT 7 /* User/Kernel mode */
#define STATUS_L_BIT 12 /* Loop inhibit */
/* These masks correspond to the status word(STATUS_32) bits */
-#define STATUS_AE_MASK (1<<STATUS_AE_BIT)
-#define STATUS_DE_MASK (1<<STATUS_DE_BIT)
-#define STATUS_U_MASK (1<<STATUS_U_BIT)
-#define STATUS_L_MASK (1<<STATUS_L_BIT)
+#define STATUS_H_MASK (1<<STATUS_H_BIT) /* Mask for Halt bit */
+#define STATUS_E1_MASK (1<<STATUS_E1_BIT) /* Mask for Int 1 enable */
+#define STATUS_E2_MASK (1<<STATUS_E2_BIT) /* Mask for Int 2 enable */
+#define STATUS_A1_MASK (1<<STATUS_A1_BIT) /* Interrupt 1 active */
+#define STATUS_A2_MASK (1<<STATUS_A2_BIT) /* Interrupt 2 active */
+#define STATUS_AE_MASK (1<<STATUS_AE_BIT) /* Exception active */
+#define STATUS_DE_MASK (1<<STATUS_DE_BIT) /* PC is in delay slot */
+#define STATUS_U_MASK (1<<STATUS_U_BIT) /* User/Kernel mode bit */
+#define STATUS_L_MASK (1<<STATUS_L_BIT) /* Loop inhibit bit */
+
/*
* ECR: Exception Cause Reg bits-n-pieces
@@ -108,6 +120,17 @@
#define ARC_AUX_DPFP_2H 0x304
#define ARC_AUX_DPFP_STAT 0x305
+/*
+ * New added from BBIC4 arcreg.h
+ */
+
+#define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */
+#define ARC_REG_TIMER0_CTRL 0x22 /* timer 0 control */
+#define ARC_REG_TIMER0_CNT 0x21 /* timer 0 count */
+#define ARC_REG_TIMER1_LIMIT 0x102 /* timer 1 limit */
+#define ARC_REG_TIMER1_CTRL 0x101 /* timer 1 control */
+#define ARC_REG_TIMER1_CNT 0x100 /* timer 1 count */
+
#ifndef __ASSEMBLY__
/*
@@ -171,6 +194,9 @@
#endif
+#define read_new_aux_reg read_aux_reg
+#define write_new_aux_reg write_aux_reg
+
#define READ_BCR(reg, into) \
{ \
unsigned int tmp; \
diff --git a/arch/arc/include/asm/board-ruby b/arch/arc/include/asm/board-ruby
new file mode 120000
index 0000000..1ca4289
--- /dev/null
+++ b/arch/arc/include/asm/board-ruby
@@ -0,0 +1 @@
+../../../../../drivers/ruby/
\ No newline at end of file
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index 23706c6..c94450a 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -18,6 +18,7 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define CACHE_LINE_MASK (~(L1_CACHE_BYTES - 1))
+#define ARC_DCACHE_LINE_LEN (L1_CACHE_BYTES)
/*
* ARC700 doesn't cache any access in top 1G (0xc000_0000 to 0xFFFF_FFFF)
@@ -27,8 +28,44 @@
#define ARC_UNCACHED_ADDR_SPACE 0xc0000000
#ifndef __ASSEMBLY__
-
/* Uncached access macros */
+#define arc_read_uncached_8(ptr) \
+ ({ \
+ uint8_t __ret; \
+ __asm__ __volatile__ ("ldb.di %0, [%1]":"=r"(__ret):"r"(ptr)); \
+ __ret; \
+ })
+
+#define arc_write_uncached_8(ptr, data) \
+ ({ \
+ __asm__ __volatile__ ("stb.di %0, [%1]"::"r"(data), "r"(ptr)); \
+ })
+
+#define arc_read_uncached_16(ptr) \
+ ({ \
+ uint16_t __ret; \
+ __asm__ __volatile__ ("ldw.di %0, [%1]":"=r"(__ret):"r"(ptr)); \
+ __ret; \
+ })
+
+#define arc_write_uncached_16(ptr, data) \
+ ({ \
+ __asm__ __volatile__ ("stw.di %0, [%1]"::"r"(data), "r"(ptr)); \
+ })
+
+#define arc_read_uncached_32(ptr) \
+ ({ \
+ uint32_t __ret; \
+ __asm__ __volatile__ ("ld.di %0, [%1]":"=r"(__ret):"r"(ptr)); \
+ __ret; \
+ })
+
+#define arc_write_uncached_32(ptr, data) \
+ ({ \
+ __asm__ __volatile__ ("st.di %0, [%1]"::"r"(data), "r"(ptr)); \
+ })
+
+#if 0
#define arc_read_uncached_32(ptr) \
({ \
unsigned int __ret; \
@@ -46,6 +83,7 @@
: \
: "r"(data), "r"(ptr)); \
})
+#endif
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index a093adb..f026ad1 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -43,6 +43,7 @@
void dma_cache_wback_inv(phys_addr_t start, unsigned long sz);
void dma_cache_inv(phys_addr_t start, unsigned long sz);
void dma_cache_wback(phys_addr_t start, unsigned long sz);
+#define inv_dcache_range(s, e) dma_cache_inv(s, (unsigned long)(e) - (unsigned long)(s));
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/arch/arc/include/asm/checksum.h b/arch/arc/include/asm/checksum.h
index 913eb4a..451135b 100644
--- a/arch/arc/include/asm/checksum.h
+++ b/arch/arc/include/asm/checksum.h
@@ -38,7 +38,7 @@
* which always checksum on 4 octet boundaries.
*/
static inline __sum16
-ip_fast_csum(const void *iph, unsigned int ihl)
+asm_ip_fast_csum(const void *iph, unsigned int ihl)
{
const void *ptr = iph;
unsigned int tmp, tmp2, sum;
@@ -93,7 +93,6 @@
}
#define csum_fold csum_fold
-#define ip_fast_csum ip_fast_csum
#define csum_tcpudp_nofold csum_tcpudp_nofold
#include <asm-generic/checksum.h>
diff --git a/arch/arc/include/asm/elf.h b/arch/arc/include/asm/elf.h
index 51a99e2..7096f97 100644
--- a/arch/arc/include/asm/elf.h
+++ b/arch/arc/include/asm/elf.h
@@ -23,8 +23,7 @@
/* ARC Relocations (kernel Modules only) */
#define R_ARC_32 0x4
#define R_ARC_32_ME 0x1B
-#define R_ARC_S25H_PCREL 0x10
-#define R_ARC_S25W_PCREL 0x11
+#define R_ARC_32_PCREL 0x31
/*to set parameters in the core dumps */
#define ELF_ARCH EM_ARCOMPACT
diff --git a/arch/arc/include/asm/hardware.h b/arch/arc/include/asm/hardware.h
new file mode 100644
index 0000000..b3f528f
--- /dev/null
+++ b/arch/arc/include/asm/hardware.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) Quantenna Communications Incorporated 2010.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#define IO_ADDRESS(x) ((void *)(x))
+/* FIXME: Ruby only has a single BB, so I'm not sure we should allow this: */
+#define BB2_IO_ADDRESS(x) (IO_ADDRESS((x)))
+
+#define PHYS_IO_ADDRESS(x) (x)
+
+#endif
+
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index c22b181..4ee75b8 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -22,6 +22,9 @@
#define __iowmb() do { } while (0)
#endif
+#define IO_ADDRESS(x) ((void *)(x))
+#define __io_address(n) ((void __iomem *)IO_ADDRESS(n))
+
extern void __iomem *ioremap(phys_addr_t paddr, unsigned long size);
extern void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
unsigned long flags);
@@ -52,8 +55,8 @@
/* Change struct page to physical address */
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
-#define __raw_readb __raw_readb
-static inline u8 __raw_readb(const volatile void __iomem *addr)
+#define __raw_readb(addr) __raw_arc_readb((const volatile void __iomem *)(addr))
+static inline u8 __raw_arc_readb(const volatile void __iomem *addr)
{
u8 b;
@@ -66,8 +69,8 @@
return b;
}
-#define __raw_readw __raw_readw
-static inline u16 __raw_readw(const volatile void __iomem *addr)
+#define __raw_readw(addr) __raw_arc_readw((const volatile void __iomem *)(addr))
+static inline u16 __raw_arc_readw(const volatile void __iomem *addr)
{
u16 s;
@@ -80,8 +83,8 @@
return s;
}
-#define __raw_readl __raw_readl
-static inline u32 __raw_readl(const volatile void __iomem *addr)
+#define __raw_readl(addr) __raw_arc_readl((const volatile void __iomem *)(addr))
+static inline u32 __raw_arc_readl(const volatile void __iomem *addr)
{
u32 w;
@@ -94,8 +97,8 @@
return w;
}
-#define __raw_writeb __raw_writeb
-static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+#define __raw_writeb(b, addr) __raw_arc_writeb((b), (volatile void __iomem *)(addr))
+static inline void __raw_arc_writeb(u8 b, volatile void __iomem *addr)
{
__asm__ __volatile__(
" stb%U1 %0, %1 \n"
@@ -104,8 +107,8 @@
: "memory");
}
-#define __raw_writew __raw_writew
-static inline void __raw_writew(u16 s, volatile void __iomem *addr)
+#define __raw_writew(s, addr) __raw_arc_writew((s), (volatile void __iomem *)(addr))
+static inline void __raw_arc_writew(u16 s, volatile void __iomem *addr)
{
__asm__ __volatile__(
" stw%U1 %0, %1 \n"
@@ -115,8 +118,8 @@
}
-#define __raw_writel __raw_writel
-static inline void __raw_writel(u32 w, volatile void __iomem *addr)
+#define __raw_writel(w, addr) __raw_arc_writel(w, (volatile void __iomem *)(addr))
+static inline void __raw_arc_writel(u32 w, volatile void __iomem *addr)
{
__asm__ __volatile__(
" st%U1 %0, %1 \n"
@@ -164,6 +167,8 @@
#define writeb_relaxed(v,c) __raw_writeb(v,c)
#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)
+#define writel_or(b, addr) writel(readl(addr) | (b), (addr))
+#define writel_and(b, addr) writel(readl(addr) & (b), (addr))
#include <asm-generic/io.h>
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index c0fa0d2..b70bd05 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -10,7 +10,13 @@
#define __ASM_ARC_IRQ_H
#define NR_CPU_IRQS 32 /* number of interrupt lines of ARC770 CPU */
-#define NR_IRQS 128 /* allow some CPU external IRQ handling */
+#define NR_IRQS 64 /* allow some CPU external IRQ handling */
+
+#define QTN_IRQ_LAST_EXT0 (63)
+
+/* Platform Independent IRQs */
+#define TIMER0_IRQ 3
+#define TIMER1_IRQ 4
/* Platform Independent IRQs */
#ifdef CONFIG_ISA_ARCV2
diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h
index c1d3645..4c6eed8 100644
--- a/arch/arc/include/asm/irqflags-compact.h
+++ b/arch/arc/include/asm/irqflags-compact.h
@@ -188,10 +188,10 @@
.endm
.macro IRQ_ENABLE scratch
+ TRACE_ASM_IRQ_ENABLE
lr \scratch, [status32]
or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
flag \scratch
- TRACE_ASM_IRQ_ENABLE
.endm
#endif /* __ASSEMBLY__ */
diff --git a/arch/arc/include/asm/kdebug.h b/arch/arc/include/asm/kdebug.h
index 3fbe6c4..6aade56 100644
--- a/arch/arc/include/asm/kdebug.h
+++ b/arch/arc/include/asm/kdebug.h
@@ -16,4 +16,18 @@
DIE_OOPS
};
+#define INIT_PRINT 0
+
+#if (INIT_PRINT == 2)
+#define printk_init(fmt, args...) printk(fmt, ## args)
+#elif (INIT_PRINT == 1)
+#define printk_init(fmt, args...)
+#else
+#define printk_init(fmt, args...) \
+ ({ \
+ static const __initconst char __fmt[] = fmt; \
+ printk(__fmt, ## args); \
+ })
+#endif
+
#endif
diff --git a/arch/arc/include/asm/mem.h b/arch/arc/include/asm/mem.h
new file mode 100755
index 0000000..c407981
--- /dev/null
+++ b/arch/arc/include/asm/mem.h
@@ -0,0 +1,51 @@
+#ifndef _ASM_ARC_MEM_H
+#define _ASM_ARC_MEM_H
+
+/* Kernels Virtual memory area.
+ * Unlike other architectures(MIPS, sh, cris ) ARC 700 does not have a
+ * "kernel translated" region (like KSEG2 in MIPS). So we use a upper part
+ * of the translated bottom 2GB for kernel virtual memory and protect
+ * these pages from user accesses by disabling Ru, Eu and Wu.
+ */
+
+/* Kernel Virtual memory Layout
+ *
+ * 0x00000000------------------->|---------------|
+ * | user space |
+ * | |
+ * | |
+ * TASK_SIZE-------------------->|---------------|
+ * | | USER_KERNEL_GUTTER(0x01000000, just as ARC_SOME_PADDING in
+ * | 16M | 2.6.30, some padding between user space and kernel virtual
+ * | | address space, ARC guys also don't know why need it)
+ * VMALLOC_START---------------->|---------------|
+ * | |
+ * | 128M/48M | VMALLOC_SIZE
+ * | 256M/64M | VMALLOC_SIZE
+ * | |
+ * PCI_REMAP_START(0x58000000)-->|---------------|
+ * | |
+ * | 512M | PCI_REMAP_SIZE(0x20000000)
+ * | |
+ * DMA_NOCACHE_START(0x78000000)>|---------------|
+ * | |
+ * | 128M | DMA_NOCACHE_SIZE(0x08000000)
+ * DMA_NOCACHE_END-----| | |
+ * PAGE_OFFSET(0x80000000)------>|---------------|
+ * | |
+ * | kernel 2G |
+ * | |
+ * (0xffffffff)------>|---------------|
+ */
+
+#define DMA_NOCACHE_SIZE (RUBY_MAX_DRAM_SIZE) /*must be >= memory size, not very scalable with DDR size growing*/
+#define DMA_NOCACHE_START (PAGE_OFFSET - DMA_NOCACHE_SIZE)
+#define DMA_NOCACHE_END (PAGE_OFFSET)
+
+/* PCI remapping */
+#define PCI_REMAP_SIZE (128*1024*1024)
+#define PCI_REMAP_START (DMA_NOCACHE_START - PCI_REMAP_SIZE)
+#define PCI_REMAP_END (DMA_NOCACHE_START)
+
+#endif /* _ARM_ARC_MEM_H */
+
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index 296c342..9a2b355 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -10,6 +10,8 @@
#include <uapi/asm/page.h>
+#define PHYS_SRAM_OFFSET 0x80000000
+
#ifndef __ASSEMBLY__
#define clear_page(paddr) memset((paddr), 0, PAGE_SIZE)
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 16b630f..9fa23f2 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -17,6 +17,8 @@
#ifndef __ASSEMBLY__
#include <asm/ptrace.h>
+#include <common/topaz_config.h>
+#include <asm/mem.h>
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
/* These DPFP regs need to be saved/restored across ctx-sw */
@@ -120,6 +122,42 @@
* -----------------------------------------------------------------------------
*/
+#define QTN_MEM_ARCH 1
+#define QTN_MEM_FIXED_TASK_SIZE 1
+
+#if QTN_MEM_ARCH
+/* QTN defined memory arch */
+
+#define VMALLOC_START (PCI_REMAP_START - (CONFIG_ARC_KVADDR_SIZE << 20))
+#define VMALLOC_SIZE ((CONFIG_ARC_KVADDR_SIZE << 20) - PGDIR_SIZE * 4)
+#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+/* Most of the architectures seem to be keeping some kind of padding between
+ * userspace TASK_SIZE and PAGE_OFFSET. i.e TASK_SIZE != PAGE_OFFSET.
+ */
+
+/* User address space:
+ * On ARC700, CPU allows the entire lower half of 32 bit address space to be
+ * translated. Thus potentially 2G (0:0x7FFF_FFFF) could be User vaddr space.
+ * However we steal some addr space for kernel virtual memory and others and another
+ * 16M is gutter between user/kernel spaces
+ * Thus total User vaddr space is (0 - (VMALLOC_START - USER_KERNEL_GUTTER))
+ */
+
+#if QTN_MEM_FIXED_TASK_SIZE
+/* Fixed TASK_SIZE */
+#define TASK_SIZE 0x60000000
+#define USER_KERNEL_GUTTER (VMALLOC_START - TASK_SIZE)
+#else
+/* Maximize TASK_SIZE */
+#define USER_KERNEL_GUTTER 0x02000000
+#define TASK_SIZE (VMALLOC_START - USER_KERNEL_GUTTER)
+#endif
+
+#define STACK_TOP TASK_SIZE
+
+#else
+/*ARCH specific defines*/
#define TASK_SIZE 0x60000000
#define VMALLOC_START (PAGE_OFFSET - (CONFIG_ARC_KVADDR_SIZE << 20))
@@ -131,22 +169,6 @@
#define USER_KERNEL_GUTTER (VMALLOC_START - TASK_SIZE)
-#ifdef CONFIG_ARC_PLAT_EZNPS
-/* NPS architecture defines special window of 129M in user address space for
- * special memory areas, when accessing this window the MMU do not use TLB.
- * Instead MMU direct the access to:
- * 0x57f00000:0x57ffffff -- 1M of closely coupled memory (aka CMEM)
- * 0x58000000:0x5fffffff -- 16 huge pages, 8M each, with fixed map (aka FMTs)
- *
- * CMEM - is the fastest memory we got and its size is 16K.
- * FMT - is used to map either to internal/external memory.
- * Internal memory is the second fast memory and its size is 16M
- * External memory is the biggest memory (16G) and also the slowest.
- *
- * STACK_TOP need to be PMD align (21bit) that is why we supply 0x57e00000.
- */
-#define STACK_TOP 0x57e00000
-#else
#define STACK_TOP TASK_SIZE
#endif
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index cfcdedf..3a2ae69 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -8,7 +8,7 @@
# Pass UTS_MACHINE for user_regset definition
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
-obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
+obj-y := arcksyms.o setup.o irq.o time.o ptrace.o process.o devtree.o
obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o
obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o
diff --git a/arch/arc/kernel/arcksyms.c b/arch/arc/kernel/arcksyms.c
index 4d9e777..3a2de1e 100644
--- a/arch/arc/kernel/arcksyms.c
+++ b/arch/arc/kernel/arcksyms.c
@@ -21,6 +21,7 @@
extern void __muldi3(void);
extern void __ucmpdi2(void);
extern void __udivsi3(void);
+extern void __udivdi3(void);
extern void __umodsi3(void);
extern void __cmpdi2(void);
extern void __fixunsdfsi(void);
@@ -38,6 +39,7 @@
EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__ucmpdi2);
EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__udivdi3);
EXPORT_SYMBOL(__umodsi3);
EXPORT_SYMBOL(__cmpdi2);
EXPORT_SYMBOL(__fixunsdfsi);
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 2efb062..741712d 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -61,18 +61,6 @@
b ret_from_exception
END(ret_from_fork)
-#ifdef CONFIG_ARC_DW2_UNWIND
-; Workaround for bug 94179 (STAR ):
-; Despite -fasynchronous-unwind-tables, linker is not making dwarf2 unwinder
-; section (.debug_frame) as loadable. So we force it here.
-; This also fixes STAR 9000487933 where the prev-workaround (objcopy --setflag)
-; would not work after a clean build due to kernel build system dependencies.
-.section .debug_frame, "wa",@progbits
-
-; Reset to .text as this file is included in entry-<isa>.S
-.section .text, "ax",@progbits
-#endif
-
;################### Non TLB Exception Handling #############################
; ---------------------------------------------
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 689dd86..47b70c9 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -17,6 +17,7 @@
#include <asm/entry.h>
#include <asm/arcregs.h>
#include <asm/cache.h>
+#include <common/topaz_platform.h>
.macro CPU_EARLY_SETUP
@@ -65,6 +66,13 @@
;----------------------------------------------------------------
ENTRY(stext)
+ b topaz_unified_mmap
+ruby_boot:
+
+ ;-------------------------------------------------------------------
+ ; Don't clobber r0-r2 yet. It might have bootloader provided info
+ ;-------------------------------------------------------------------
+
CPU_EARLY_SETUP
#ifdef CONFIG_SMP
@@ -90,6 +98,17 @@
st.ab 0, [r5, 4]
1:
+ ;clear .sram.bss memory section
+__clear_sram_bss:
+ mov r5, __sram_bss_start
+ mov r6, __sram_bss_end
+
+__clear_sram_bss_loop:
+ st.ab 0, [r5,4]
+ brlt r5, r6, __clear_sram_bss_loop
+
+;inclue head_fixup.S to move sram memory content to sram
+#include "head_fixup.S"
#ifdef CONFIG_ARC_UBOOT_SUPPORT
; Uboot - kernel ABI
; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
@@ -113,6 +132,8 @@
j start_kernel ; "C" entry point
END(stext)
+#include <common/topaz_mmap.S>
+
#ifdef CONFIG_SMP
;----------------------------------------------------------------
; First lines of code run by secondary before jumping to 'C'
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
index ce9deb9..c2ff603 100644
--- a/arch/arc/kernel/intc-compact.c
+++ b/arch/arc/kernel/intc-compact.c
@@ -13,8 +13,14 @@
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
#include <asm/irq.h>
+#include <asm/board/board_config.h>
+#include <asm/board/platform.h>
+#include <asm/board/mem_check.h>
+//#include <asm/hardware.h>
-#define TIMER0_IRQ 3 /* Fixed by ISA */
+#ifdef CONFIG_ARCH_QSR1000
+#include <asm/io.h>
+#endif
/*
* Early Hardware specific Interrupt setup
@@ -59,6 +65,24 @@
ienb = read_aux_reg(AUX_IENABLE);
ienb &= ~(1 << data->irq);
write_aux_reg(AUX_IENABLE, ienb);
+
+#ifdef CONFIG_ARCH_QSR1000
+ {
+ if (data->irq >= RUBY_IRQ_WATCHDOG) {
+ /* If higher than timer, this is external irq to cpu and needs additional reg set up. */
+ /* Copied from drivers/ruby/irq.c */
+ unsigned long status = readl(RUBY_SYS_CTL_LHOST_INT_EN);
+ status &= ~(1 << (data->irq - RUBY_IRQ_WATCHDOG));
+ writel(status, RUBY_SYS_CTL_LHOST_INT_EN);
+ }
+ if (data->irq == RUBY_IRQ_UART) {
+ unsigned long status = readl(RUBY_SYS_CTL_LHOST_ORINT_EN);
+ unsigned int irq = 48;
+ status &= ~(1 << (irq - RUBY_IRQ_VECTORS_NUM));
+ writel(status, RUBY_SYS_CTL_LHOST_ORINT_EN);
+ }
+ }
+#endif
}
static void arc_irq_unmask(struct irq_data *data)
@@ -68,6 +92,28 @@
ienb = read_aux_reg(AUX_IENABLE);
ienb |= (1 << data->irq);
write_aux_reg(AUX_IENABLE, ienb);
+#ifdef CONFIG_ARCH_QSR1000
+ {
+ if (data->irq >= RUBY_IRQ_WATCHDOG) {
+ /* If higher than timer, this is external irq to cpu and needs additional reg set up. */
+ /* Copied from drivers/ruby/irq.c */
+ unsigned long status = readl(RUBY_SYS_CTL_LHOST_INT_EN);
+ status |= (1 << (data->irq - RUBY_IRQ_WATCHDOG));
+ writel(status, RUBY_SYS_CTL_LHOST_INT_EN);
+ }
+ if (data->irq == 24) {
+ unsigned long status = readl(RUBY_SYS_CTL_LHOST_ORINT_EN);
+ unsigned int irq = 48;
+ status |= (1 << (irq - RUBY_IRQ_VECTORS_NUM));
+ writel(status, RUBY_SYS_CTL_LHOST_ORINT_EN);
+ }
+ if (data->irq == 28) {
+ unsigned long temp = readl(RUBY_SYS_CTL_PCIE_INT_MASK);
+ temp |= BIT(11); /* Legacy INTx */
+ writel(temp, RUBY_SYS_CTL_PCIE_INT_MASK);
+ }
+ }
+#endif
}
static struct irq_chip onchip_intc = {
@@ -95,7 +141,26 @@
.map = arc_intc_domain_map,
};
-static int __init
+static int __init ruby_intc_init(void)
+{
+ int irq;
+ unsigned long status;
+
+ /*
+ * the irq from RUBY_IRQ_WATCHDOG to RUBY_IRQ_VECTORS_NUM are enabled
+ * by setting both RUBY_SYS_CTL_LHOST_INT_EN and AUX_IENABLE register
+ * Enable RUBY_SYS_CTL_LHOST_INT_EN here
+ */
+ status = readl(IO_ADDRESS(RUBY_SYS_CTL_LHOST_INT_EN));
+
+ for (irq = RUBY_IRQ_WATCHDOG; irq < RUBY_IRQ_VECTORS_NUM; irq++)
+ status |= (1 << (irq - RUBY_IRQ_WATCHDOG));
+
+ writel(status, IO_ADDRESS(RUBY_SYS_CTL_LHOST_INT_EN));
+ return 0;
+}
+
+int __init
init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
{
struct irq_domain *root_domain;
@@ -103,7 +168,9 @@
if (parent)
panic("DeviceTree incore intc not a root irq controller\n");
- root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS,
+ ruby_intc_init();
+
+ root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
&arc_intc_domain_ops, NULL);
if (!root_domain)
panic("root irq domain not avail\n");
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 538b36a..88ab422 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -12,6 +12,9 @@
#include <asm/mach_desc.h>
#include <asm/smp.h>
+int __init
+init_onchip_IRQ(struct device_node *intc, struct device_node *parent);
+
/*
* Late Interrupt system init called from start_kernel for Boot CPU only
*
@@ -20,6 +23,10 @@
*/
void __init init_IRQ(void)
{
+
+ /* process the entire interrupt tree in one go */
+/* init_onchip_IRQ(NULL, NULL);*/
+
/*
* process the entire interrupt tree in one go
* Any external intc will be setup provided DT chains them
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c
index 376e046..63e3fee 100644
--- a/arch/arc/kernel/module.c
+++ b/arch/arc/kernel/module.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/string.h>
+#include <linux/mm.h>
#include <asm/unwind.h>
static inline void arc_write_me(unsigned short *addr, unsigned long value)
@@ -22,13 +23,39 @@
*(addr + 1) = (value & 0xffff);
}
-/* ARC specific section quirks - before relocation loop in generic loader
- *
- * For dwarf unwinding out of modules, this needs to
- * 1. Ensure the .debug_frame is allocatable (ARC Linker bug: despite
- * -fasynchronous-unwind-tables it doesn't).
- * 2. Since we are iterating thru sec hdr tbl anyways, make a note of
- * the exact section index, for later use.
+void *module_alloc(unsigned long size)
+{
+ void *ret;
+
+ if(size == 0)
+ return NULL;
+
+ /* kmalloc() allocated memory does not require TLB - so this should work faster */
+ ret = kmalloc(size, GFP_KERNEL);
+ if (!ret) {
+ printk(KERN_WARNING "Module cannot be allocated using kmalloc(), let's try vmalloc()\n");
+ ret = vmalloc(size);
+ }
+
+ return ret;
+}
+
+void module_memfree(void *region)
+{
+ if (!region)
+ return;
+
+ if (unlikely(is_vmalloc_addr(region))) {
+ vfree(region);
+ }
+ else {
+ kfree(region);
+ }
+}
+
+/*
+ * This gets called before relocation loop in generic loader
+ * Make a note of the section index of unwinding section
*/
int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
char *secstr, struct module *mod)
@@ -40,8 +67,7 @@
mod->arch.unw_info = NULL;
for (i = 1; i < hdr->e_shnum; i++) {
- if (strcmp(secstr+sechdrs[i].sh_name, ".debug_frame") == 0) {
- sechdrs[i].sh_flags |= SHF_ALLOC;
+ if (strcmp(secstr+sechdrs[i].sh_name, ".eh_frame") == 0) {
mod->arch.unw_sec_idx = i;
break;
}
@@ -106,10 +132,12 @@
*/
relo_type = ELF32_R_TYPE(rel_entry[i].r_info);
- if (likely(R_ARC_32_ME == relo_type))
+ if (likely(R_ARC_32_ME == relo_type)) /* ME ( S + A ) */
arc_write_me((unsigned short *)location, relocation);
- else if (R_ARC_32 == relo_type)
+ else if (R_ARC_32 == relo_type) /* ( S + A ) */
*((Elf32_Addr *) location) = relocation;
+ else if (R_ARC_32_PCREL == relo_type) /* ( S + A ) - PDATA ) */
+ *((Elf32_Addr *) location) = relocation - location;
else
goto relo_err;
@@ -143,3 +171,247 @@
#endif
return 0;
}
+
+#ifdef CONFIG_ARCH_RUBY_NUMA
+
+/* roundmb - Round address up to size of memblock */
+#define roundmb(x) (void *)( (0x07 + (unsigned long)(x)) & ~0x07 )
+/* truncmb - Truncate address down to size of memblock */
+#define truncmb(x) (void *)( ((unsigned long)(x)) & ~0x07 )
+
+struct memblock
+{
+ struct memblock *next; /* Pointer to next memory block */
+ unsigned long length; /* Size of memory block (with struct) */
+};
+
+static struct memblock s_memlist = { NULL, 0 }; /* List of free memory blocks */
+static DEFINE_SPINLOCK(s_heap_lock);
+
+extern char __sram_end;
+
+int heap_sram_ptr(void *pmem)
+{
+#ifdef QTN_RC_ENABLE_HDP
+ return (pmem >= (void*)&__sram_end) &&
+ (pmem < (void*)(RUBY_SRAM_BEGIN + CONFIG_ARC_SRAM_END));
+#else
+ return (pmem >= (void*)&__sram_end) &&
+ (pmem < (void*)(RUBY_SRAM_BEGIN + CONFIG_ARC_KERNEL_SRAM_B2_END));
+#endif
+}
+EXPORT_SYMBOL(heap_sram_ptr);
+
+static __init struct memblock* qtn_new_memblock_init(struct memblock *pmblock, void *begin, void *end)
+{
+ if (!pmblock) {
+ pmblock = (struct memblock *) begin;
+ s_memlist.next = pmblock;
+ } else {
+ pmblock->next = (struct memblock *) begin;
+ pmblock = pmblock->next;
+ }
+
+ pmblock->next = NULL;
+ pmblock->length = (unsigned) (end - begin);
+
+ return pmblock;
+}
+
+static int __init qtn_meminit(void)
+{
+ void *heapbegin, *heapend;
+ s_memlist.next = NULL;
+
+ heapbegin = roundmb(&__sram_end);
+#ifdef QTN_RC_ENABLE_HDP
+ heapend = truncmb(RUBY_SRAM_BEGIN + CONFIG_ARC_SRAM_END);
+#else
+ heapend = truncmb(RUBY_SRAM_BEGIN + CONFIG_ARC_KERNEL_SRAM_B2_END);
+#endif
+
+ printk(KERN_INFO"Topaz heap in SRAM %p<->%p, B2 BASE %x\n",
+ heapbegin, heapend, CONFIG_ARC_KERNEL_SRAM_B2_BASE);
+
+ if (heapbegin < heapend) {
+ qtn_new_memblock_init(NULL, heapbegin, heapend);
+ }
+
+ return 0;
+}
+arch_initcall(qtn_meminit);
+
+static void *qtn_memget(unsigned long nbytes)
+{
+ struct memblock *memlist = &s_memlist;
+ unsigned long flags;
+ register struct memblock *prev, *curr, *leftover;
+
+ if(0 == nbytes)
+ {
+ return NULL;
+ }
+
+ /* Round to multiple of memblock size */
+ nbytes = (unsigned long) roundmb(nbytes);
+
+ spin_lock_irqsave(&s_heap_lock, flags);
+
+ prev = memlist;
+ curr = memlist->next;
+
+ while(curr != NULL)
+ {
+ if(curr->length == nbytes)
+ {
+ prev->next = curr->next;
+ memlist->length -= nbytes;
+
+ goto return_curr;
+ }
+ else if(curr->length > nbytes)
+ {
+ /* Split block into two */
+ leftover = (struct memblock *)((unsigned long) curr + nbytes);
+ prev->next = leftover;
+ leftover->next = curr->next;
+ leftover->length = curr->length - nbytes;
+ memlist->length -= nbytes;
+
+ goto return_curr;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+
+ spin_unlock_irqrestore(&s_heap_lock, flags);
+ return NULL;
+
+return_curr:
+ spin_unlock_irqrestore(&s_heap_lock, flags);
+ return (void *)curr;
+}
+
+static int qtn_memfree(void *memptr, unsigned long nbytes)
+{
+ struct memblock *memlist = &s_memlist;
+ unsigned long flags;
+ register struct memblock *block, *next, *prev;
+ unsigned long top;
+
+ block = (struct memblock *) memptr;
+ nbytes = (unsigned long) roundmb(nbytes);
+
+ spin_lock_irqsave(&s_heap_lock, flags);
+
+ prev = memlist;
+ next = memlist->next;
+ while((next != NULL) && (next < block))
+ {
+ prev = next;
+ next = next->next;
+ }
+
+ /* Find top of previous memblock */
+ if(prev == memlist)
+ {
+ top = (unsigned long) NULL;
+ }
+ else
+ {
+ top = (unsigned long) prev + prev->length;
+ }
+
+ /* Make sure block is not overlapping on prev or next blocks */
+ if ((top > (unsigned long) block)
+ || ((next != NULL) && ((unsigned long) block + nbytes) > (unsigned long)next))
+ {
+ spin_unlock_irqrestore(&s_heap_lock, flags);
+ return -1;
+ }
+
+ memlist->length += nbytes;
+
+ /* Coalesce with previous block if adjacent */
+ if(top == (unsigned long) block)
+ {
+ prev->length += nbytes;
+ block = prev;
+ }
+ else
+ {
+ block->next = next;
+ block->length = nbytes;
+ prev->next = block;
+ }
+
+ /* coalesce with next block if adjacent */
+ if(((unsigned long) block + block->length) == (unsigned long) next)
+ {
+ block->length += next->length;
+ block->next = next->next;
+ }
+
+ spin_unlock_irqrestore(&s_heap_lock, flags);
+
+ return 0;
+}
+
+void *heap_sram_alloc(unsigned long nbytes)
+{
+ struct memblock *pmem;
+
+ /* We don't allocate 0 bytes. */
+ if(0 == nbytes)
+ {
+ return(NULL);
+ }
+
+ /* Make room for accounting info */
+ nbytes += sizeof(struct memblock);
+
+ /* Acquire memory from system */
+ if((pmem = (struct memblock *) qtn_memget(nbytes)) == NULL)
+ {
+ pr_debug("Warning: %s failed to allocate 0x%x bytes from caller %p\n", __func__,
+ nbytes, __builtin_return_address(0));
+ return(NULL);
+ }
+
+ /* set accounting info */
+ pmem->next = pmem;
+ pmem->length = nbytes;
+
+ return((void *)(pmem + 1)); /* +1 to skip accounting info */
+}
+EXPORT_SYMBOL(heap_sram_alloc);
+
+void heap_sram_free(void *pmem)
+{
+ struct memblock *block;
+
+ /* We skip NULL pointers. */
+ if(NULL == pmem)
+ {
+ return;
+ }
+
+ /* Block points at the memblock we want to free */
+ block = (struct memblock *) pmem;
+
+ /* Back up to accounting information */
+ block--;
+
+ /* Don't memfree if we fail basic checks */
+ if(block->next != block)
+ {
+ return;
+ }
+
+ qtn_memfree(block, block->length);
+}
+EXPORT_SYMBOL(heap_sram_free);
+
+#endif // #ifdef CONFIG_ARCH_RUBY_NUMA
+
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 2ee7a4d..36bf411 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -25,6 +25,7 @@
#include <asm/unwind.h>
#include <asm/mach_desc.h>
#include <asm/smp.h>
+#include <asm/board/board_config.h>
#define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x))
@@ -409,6 +410,8 @@
/* To force early parsing of things like mem=xxx */
parse_early_param();
+ parse_board_config(boot_command_line);
+
/* Platform/board specific: e.g. early console registration */
if (machine_desc->init_early)
machine_desc->init_early();
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c
index b9192a6..8d4a1b8 100644
--- a/arch/arc/kernel/stacktrace.c
+++ b/arch/arc/kernel/stacktrace.c
@@ -25,6 +25,7 @@
*/
#include <linux/ptrace.h>
+#include <linux/module.h>
#include <linux/export.h>
#include <linux/stacktrace.h>
#include <linux/kallsyms.h>
@@ -32,6 +33,17 @@
#include <asm/unwind.h>
#include <asm/switch_to.h>
+#define CRASH_MAX_ENTRIES 16
+#define CRASH_SYM_LEN 64
+struct crash_stack_trace {
+ int num_entries;
+ struct {
+ unsigned int addr;
+ char sym[KSYM_SYMBOL_LEN];
+ } e [CRASH_MAX_ENTRIES];
+};
+
+struct crash_stack_trace crash_log;
/*-------------------------------------------------------------------------
* Unwinder Iterator
*-------------------------------------------------------------------------
@@ -156,13 +168,31 @@
*-------------------------------------------------------------------------
*/
+void save_crash_log(unsigned int address)
+{
+ unsigned long flags;
+ int count;
+
+ local_irq_save(flags);
+
+ count = crash_log.num_entries;
+ if (count < CRASH_MAX_ENTRIES-1) {
+ crash_log.e[count].addr = address;
+ sprint_symbol(crash_log.e[count].sym, address);
+ crash_log.num_entries++;
+ }
+
+ local_irq_restore(flags);
+}
/* Call-back which plugs into unwinding core to dump the stack in
* case of panic/OOPs/BUG etc
*/
-static int __print_sym(unsigned int address, void *unused)
+int verbose_dump_stack(unsigned int address, void *unused)
{
- __print_symbol(" %s\n", address);
- return 0;
+ printk(" 0x%08x ", address);
+ __print_symbol(" %s\n", address);
+ save_crash_log(address);
+ return 0;
}
#ifdef CONFIG_STACKTRACE
@@ -217,12 +247,29 @@
* APIs expected by various kernel sub-systems
*-------------------------------------------------------------------------
*/
+void (*g_qtn_show_info) (void) = NULL;
+
+void qtn_show_info_register(void *fn) {
+ g_qtn_show_info = fn;
+}
+
+void qtn_show_info_unregister(void) {
+ g_qtn_show_info = NULL;
+}
+
+EXPORT_SYMBOL(qtn_show_info_register);
+EXPORT_SYMBOL(qtn_show_info_unregister);
noinline void show_stacktrace(struct task_struct *tsk, struct pt_regs *regs)
{
+ if (g_qtn_show_info) {
+ g_qtn_show_info();
+ }
+
pr_info("\nStack Trace:\n");
- arc_unwind_core(tsk, regs, __print_sym, NULL);
+ arc_unwind_core(tsk, regs, verbose_dump_stack, NULL);
}
+
EXPORT_SYMBOL(show_stacktrace);
/* Expected by sched Code */
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 4549ab2..4b05e0f 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -41,6 +41,8 @@
#include <asm/arcregs.h>
#include <asm/mcip.h>
+#include <qtn/topaz_hbm.h>
+#include <asm/board/soc.h>
/* Timer related Aux registers */
#define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */
@@ -291,6 +293,8 @@
*/
write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
+ topaz_hbm_filter_txdone_pool();
+ pet_watchdog_timer();
evt->event_handler(evt);
return IRQ_HANDLED;
@@ -373,4 +377,5 @@
{
of_clk_init(NULL);
clocksource_probe();
+ init_watchdog_timer();
}
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index c927aa8..84cd9cb 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -22,6 +22,7 @@
#include <asm/setup.h>
#include <asm/unaligned.h>
#include <asm/kprobes.h>
+#include <linux/reboot.h>
void __init trap_init(void)
{
@@ -32,8 +33,9 @@
{
show_kernel_fault_diag(str, regs, address);
+ machine_restart(NULL);
+
/* DEAD END */
- __asm__("flag 1");
}
/*
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index 934150e..4c5d3f2 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -15,6 +15,25 @@
#include <linux/file.h>
#include <asm/arcregs.h>
#include <asm/irqflags.h>
+#include <asm/board/troubleshoot.h>
+#include <asm/cacheflush.h>
+#include <linux/kmsg_dump.h>
+#include <linux/vmalloc.h>
+#include <linux/zlib.h>
+#include <linux/slab.h>
+
+/* 3.8 times seems safe for LHost, MuC and/or AuC crash - found by trial and error */
+#define CORE_DUMP_COMPRESS_RATIO (380)
+
+static void kmsg_dumper_core_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+
+static unsigned long sram_safe_start;
+static unsigned long sram_safe_size;
+
+static arc_troubleshoot_start_hook_cbk troubleshoot_start;
+static void *troubleshoot_ctx;
+
+static struct kmsg_dumper dumper_core_dump = {.dump = kmsg_dumper_core_dump, .max_reason = KMSG_DUMP_PANIC};
/*
* Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
@@ -165,6 +184,236 @@
}
}
+static int32_t compress_chunk(z_stream *stream, const bool is_last_stream)
+{
+ int32_t zlib_retval;
+
+ if (!stream) {
+ printk(KERN_ERR "%s: stream is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (is_last_stream) {
+ zlib_retval = zlib_deflate(stream, Z_FINISH);
+ if (zlib_retval != Z_STREAM_END) {
+ if (zlib_retval != Z_OK) {
+ printk(KERN_ERR "%s: only chunk; zlib_deflate returned %d\n", __func__,
+ zlib_retval);
+ return -1;
+ }
+
+ printk(KERN_WARNING "%s: zlib_deflate (only chunk): some data would be missing\n",
+ __func__);
+ }
+ } else {
+ zlib_retval = zlib_deflate(stream, Z_SYNC_FLUSH);
+ if (zlib_retval != Z_OK) {
+ printk(KERN_ERR "%s: first chunk, zlib_deflate returned %d\n", __func__,
+ zlib_retval);
+ return -1;
+ }
+
+ /*
+ * If stream.avail_in is not 0, some logs could be missing; we should recheck len_max_input in
+ * arc_save_to_sram_safe_area()
+ */
+ if (stream->avail_in != 0)
+ printk(KERN_WARNING "%s: stream->avail_in (%ld) is not 0\n", __func__, stream->avail_in);
+ }
+
+ return 0;
+}
+
+static int32_t compress_circular_buffer(const char *buf_chunk_one, uint32_t len_chunk_one,
+ const char *buf_chunk_two, uint32_t len_chunk_two,
+ char *buf_out, uint32_t len_buf_out,
+ uint32_t *len_compress_data)
+{
+ int32_t retval = -1;
+ int32_t zlib_retval;
+ int32_t workspace_size;
+ z_stream stream;
+
+ if (!len_compress_data) {
+ printk(KERN_ERR "%s: len_compress_data is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ *len_compress_data = 0;
+
+ workspace_size = zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL);
+ printk(KERN_ERR "%s: workspace_size = %d\n", __func__, workspace_size);
+
+ stream.workspace = kmalloc(workspace_size, GFP_ATOMIC);
+ if (!stream.workspace) {
+ printk(KERN_ERR "%s: Failed to allocate %d bytes for deflate workspace\n", __func__,
+ workspace_size);
+ return -ENOMEM;
+ }
+
+ /* Use zlib format because gzip is not available */
+ zlib_retval = zlib_deflateInit(&stream, Z_DEFAULT_COMPRESSION);
+ if (zlib_retval != Z_OK) {
+ printk(KERN_ERR "%s: zlib_deflateInit failed, zlib_retval = %d\n", __func__, zlib_retval);
+ kfree(stream.workspace);
+ return retval;
+ }
+
+ stream.next_out = (Byte *) buf_out;
+ stream.avail_out = len_buf_out;
+ stream.total_out = 0;
+
+ if (len_chunk_one) {
+ /* Compress the first chunk */
+ stream.next_in = (Byte *) buf_chunk_one;
+ stream.avail_in = len_chunk_one;
+ stream.total_in = 0;
+
+ if (compress_chunk(&stream, len_chunk_two ? false : true))
+ goto deflate_end;
+ }
+
+ if (len_chunk_two) {
+ /* Compress the second chunk */
+ stream.next_in = (Byte *) buf_chunk_two;
+ stream.avail_in = len_chunk_two;
+ stream.total_in = 0;
+
+ if (compress_chunk(&stream, true))
+ goto deflate_end;
+ }
+
+ *len_compress_data = stream.total_out;
+ printk(KERN_ERR "%s: compressed data length = %u\n", __func__, *len_compress_data);
+
+ retval = 0;
+
+deflate_end:
+ zlib_retval = zlib_deflateEnd(&stream);
+ if (zlib_retval != Z_OK) {
+ printk(KERN_WARNING "%s: zlib_deflateEnd failed, zlib_retval = %d\n", __func__, zlib_retval);
+ }
+
+ kfree(stream.workspace);
+
+ return retval;
+}
+
+/* Save the printk circular buffer to the SRAM safe area */
+void arc_save_to_sram_safe_area(const char *buf_chunk_one, uint32_t len_chunk_one,
+ const char *buf_chunk_two, uint32_t len_chunk_two,
+ uint32_t len_max_input)
+{
+ uint32_t extra_margin;
+ uint32_t len_compress_data;
+
+ /* Ensure that there is something in the printk circular buffer */
+ if (!(len_chunk_one + len_chunk_two)) {
+ printk(KERN_ERR "%s: len_chunk_one + len_chunk_two is 0\n", __func__);
+ return;
+ }
+
+ if (len_max_input < len_chunk_one + len_chunk_two) {
+ if (len_max_input <= len_chunk_two) {
+ buf_chunk_one = NULL;
+ len_chunk_one = 0;
+
+ buf_chunk_two += (len_chunk_two - len_max_input);
+ len_chunk_two = len_max_input;
+ } else {
+ len_max_input -= len_chunk_two;
+
+ buf_chunk_one += (len_chunk_one - len_max_input);
+ len_chunk_one = len_max_input;
+ }
+ }
+
+ /* Refer to include/linux/zlib.h */
+ extra_margin = (len_chunk_one + len_chunk_two) - (((len_chunk_one + len_chunk_two) * 1000) / 1001)
+ + 12;
+
+ if (extra_margin < len_chunk_one) {
+ buf_chunk_one += extra_margin;
+ len_chunk_one -= extra_margin;
+ } else {
+ extra_margin -= len_chunk_one;
+
+ buf_chunk_one = NULL;
+ len_chunk_one = 0;
+
+ buf_chunk_two += extra_margin;
+ len_chunk_two -= extra_margin;
+ }
+
+ /*
+ * Compress the printk circular buffer and store it in SRAM safe aread (so as to retrieve it on the
+ * next reboot)
+ */
+ compress_circular_buffer(buf_chunk_one, len_chunk_one, buf_chunk_two, len_chunk_two,
+ (char *) (sram_safe_start + 4), sram_safe_size - 4,
+ &len_compress_data);
+
+ *((uint16_t *) sram_safe_start) = HEADER_CORE_DUMP;
+ *((uint16_t *) (sram_safe_start + 2)) = (uint16_t) len_compress_data;
+
+ flush_cache_all();
+}
+
+static void kmsg_dumper_core_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason)
+{
+ char *buf;
+ uint32_t buf_in_len;
+ uint32_t buf_out_len = 0;
+
+ if (reason < KMSG_DUMP_PANIC)
+ return;
+
+ /*
+ * Format of buffer:
+ * 2 bytes: Header (HEADER_CORE_DUMP)
+ * 2 bytes: Length of the compressed logs (n)
+ * n bytes: Compressed logs
+ */
+
+ /* Expecting sram_safe_start to be 2 byte aligned */
+ if ((sram_safe_start & 0x1) != 0) {
+ printk(KERN_ERR "%s: sram_safe_start (%lu) is not 2 bytes aligned\n", __func__,
+ sram_safe_start);
+ return;
+ }
+
+ /* Needed to inform the owner that its memory is about to be used */
+ if (!troubleshoot_start) {
+ printk(KERN_ERR "%s: troubleshoot_start not set\n", __func__);
+ return;
+ }
+
+ /*
+ * Find the max input length that could be fed into the compression algo [remove the header (2b)
+ * and length (2b)]
+ */
+ buf_in_len = (CORE_DUMP_COMPRESS_RATIO * (sram_safe_size - 4)) / 100;
+
+ buf = kmalloc(buf_in_len, GFP_ATOMIC);
+ if (!buf) {
+ printk(KERN_ERR "%s: Failed to allocate %u bytes for core dump buffer\n", __func__,
+ buf_in_len);
+ return;
+ }
+
+ if (false == kmsg_dump_get_buffer(dumper, false, buf, buf_in_len, &buf_out_len)) {
+ printk(KERN_ERR "%s: kmsg_dump_get_buffer failed\n", __func__);
+ kfree(buf);
+ return;
+ }
+
+ (*troubleshoot_start)(troubleshoot_ctx);
+
+ arc_save_to_sram_safe_area(buf, buf_out_len, NULL, 0, buf_out_len);
+
+ kfree(buf);
+}
+
/************************************************************************
* API called by rest of kernel
***********************************************************************/
@@ -236,8 +485,32 @@
/* Show stack trace if this Fatality happened in kernel mode */
if (!user_mode(regs))
show_stacktrace(current, regs);
+
+ kmsg_dump(KMSG_DUMP_PANIC);
}
+void arc_set_sram_safe_area(unsigned long sram_start, unsigned long sram_end)
+{
+ int retval;
+
+ sram_safe_start = sram_start;
+ sram_safe_size = sram_end - sram_safe_start;
+
+ printk("%s: sram_safe_start=%p, size=%#x\n", sram_safe_start, sram_safe_size);
+ /* Register the kmsg dumper - will be called if LHost, MuC and/or AuC crashes */
+ retval = kmsg_dump_register(&dumper_core_dump);
+ if (retval)
+ printk(KERN_ERR "%s: Could not register dumper_core_dump\n", __func__);
+}
+EXPORT_SYMBOL(arc_set_sram_safe_area);
+
+void arc_set_troubleshoot_start_hook(arc_troubleshoot_start_hook_cbk start, void *ctx)
+{
+ troubleshoot_start = start;
+ troubleshoot_ctx = ctx;
+}
+EXPORT_SYMBOL(arc_set_troubleshoot_start_hook);
+
#ifdef CONFIG_DEBUG_FS
#include <linux/module.h>
diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c
index abd961f..5232050 100644
--- a/arch/arc/kernel/unaligned.c
+++ b/arch/arc/kernel/unaligned.c
@@ -206,7 +206,12 @@
char buf[TASK_COMM_LEN];
/* handle user mode only and only if enabled by sysadmin */
+/*#ifdef CONFIG_QTN_PLATFORM_MISALIGN_WAR*/
+#if 1
+ if (!unaligned_enabled)
+#else
if (!user_mode(regs) || !unaligned_enabled)
+#endif
return 1;
if (no_unaligned_warning) {
@@ -224,7 +229,7 @@
}
- disasm_instr(regs->ret, &state, 1, regs, cregs);
+ disasm_instr(regs->ret, &state, user_mode(regs), regs, cregs);
if (state.fault)
goto fault;
diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c
index 0587bf1..61fd1ce 100644
--- a/arch/arc/kernel/unwind.c
+++ b/arch/arc/kernel/unwind.c
@@ -111,6 +111,8 @@
#define DW_EH_PE_indirect 0x80
#define DW_EH_PE_omit 0xff
+#define CIE_ID 0
+
typedef unsigned long uleb128_t;
typedef signed long sleb128_t;
@@ -232,6 +234,7 @@
static const u32 bad_cie, not_fde;
static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
+static const u32 *__cie_for_fde(const u32 *fde);
static signed fde_pointer_type(const u32 *cie);
struct eh_frame_hdr_table_entry {
@@ -338,10 +341,9 @@
for (fde = table->address, tableSize = table->size, n = 0;
tableSize;
tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
- /* const u32 *cie = fde + 1 - fde[1] / sizeof(*fde); */
- const u32 *cie = (const u32 *)(fde[1]);
+ const u32 *cie = __cie_for_fde(fde);
- if (fde[1] == 0xffffffff)
+ if (fde[1] == CIE_ID)
continue; /* this is a CIE */
ptr = (const u8 *)(fde + 2);
header->table[n].start = read_pointer(&ptr,
@@ -504,6 +506,15 @@
return value;
}
+static const u32 *__cie_for_fde(const u32 *fde)
+{
+ const u32 *cie;
+
+ cie = fde + 1 - fde[1] / sizeof(*fde);
+
+ return cie;
+}
+
static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
{
const u32 *cie;
@@ -511,19 +522,18 @@
if (!*fde || (*fde & (sizeof(*fde) - 1)))
return &bad_cie;
- if (fde[1] == 0xffffffff)
+ if (fde[1] == CIE_ID)
return ¬_fde; /* this is a CIE */
if ((fde[1] & (sizeof(*fde) - 1)))
/* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
return NULL; /* this is not a valid FDE */
- /* cie = fde + 1 - fde[1] / sizeof(*fde); */
- cie = (u32 *) fde[1];
+ cie = __cie_for_fde(fde);
if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
|| (*cie & (sizeof(*cie) - 1))
- || (cie[1] != 0xffffffff))
+ || (cie[1] != CIE_ID))
return NULL; /* this is not a (valid) CIE */
return cie;
}
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 894e696..eb6fb24 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -10,6 +10,8 @@
#include <asm/cache.h>
#include <asm/page.h>
#include <asm/thread_info.h>
+#include <asm/board/plat_memmap.h>
+#include <asm/board/platform.h>
OUTPUT_ARCH(arc)
ENTRY(res_service)
@@ -28,7 +30,9 @@
* Essentially vector is also in ICCM.
*/
- . = CONFIG_LINUX_LINK_BASE;
+ . = RUBY_DRAM_BEGIN + CONFIG_ARC_KERNEL_BASE;
+ _img_start_addr = .;
+ . = ALIGN(PAGE_SIZE);
_int_vec_base_lds = .;
.vector : {
@@ -84,12 +88,56 @@
/*
* .exit.text is discard at runtime, not link time, to deal with
- * references from .debug_frame
+ * references from unwinding sections
* It will be init freed, being inside [__init_start : __init_end]
*/
.exit.text : { EXIT_TEXT }
.exit.data : { EXIT_DATA }
+ /* Added by Quantenna*/
+ . = ALIGN(L1_CACHE_BYTES);
+ __sram_load_addr = .;
+ .sram RUBY_SRAM_BEGIN + CONFIG_ARC_KERNEL_SRAM_B1_BASE : AT(__sram_load_addr) {
+ __sram_start = .;
+ __sram_datatext_start = .;
+
+ . = ALIGN(THREAD_SIZE);
+ *(.ksoftirqd.stack)
+ __irq_stack_begin = .;
+ . = . + THREAD_SIZE + TOPAZ_CACHE_WAR_OFFSET;
+ __irq_stack_end = .;
+ . = ALIGN(0x400);
+ __sram_text_start = .;
+#if 0
+ _int_vec_base_lds = .;
+ *(.vector)
+ . = ALIGN(PAGE_SIZE);
+#endif
+ *(.sram.text)
+ *(.text.arcfp)
+
+ __sram_text_end = .;
+
+ . = ALIGN(32);
+ __sram_data_start = .;
+ *(.sram.data)
+
+ __arc_dccm_base = .;
+ *(.data..shared_aligned)
+ *(.data.arcfp)
+ *(.sram.rodata)
+ __sram_data_end = .;
+
+ __sram_datatext_end = .;
+
+ __sram_bss_start = .;
+ *(.sram.bss)
+ __sram_bss_end = .;
+
+ __sram_end = .;
+ }
+ . = __sram_load_addr + MIN(SIZEOF(.sram), CONFIG_ARC_KERNEL_SRAM_B1_SIZE);
+ /* End */
. = ALIGN(PAGE_SIZE);
__init_end = .;
@@ -120,18 +168,13 @@
#ifdef CONFIG_ARC_DW2_UNWIND
. = ALIGN(PAGE_SIZE);
- .debug_frame : {
+ .eh_frame : {
__start_unwind = .;
- *(.debug_frame)
+ *(.eh_frame)
__end_unwind = .;
}
- /*
- * gcc 4.8 generates this for -fasynchonous-unwind-tables,
- * while we still use the .debug_frame based unwinder
- */
- /DISCARD/ : { *(.eh_frame) }
#else
- /DISCARD/ : { *(.debug_frame) }
+ /DISCARD/ : { *(.eh_frame) }
#endif
NOTES
@@ -148,7 +191,7 @@
}
#ifndef CONFIG_DEBUG_INFO
- /* open-coded because we need .debug_frame seperately for unwinding */
+ /DISCARD/ : { *(.debug_frame) }
/DISCARD/ : { *(.debug_aranges) }
/DISCARD/ : { *(.debug_pubnames) }
/DISCARD/ : { *(.debug_info) }
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index 73d7e4c..226fdab 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -19,17 +19,23 @@
#include <linux/dma-mapping.h>
#include <asm/cache.h>
#include <asm/cacheflush.h>
+#include <linux/io.h>
+#include <asm/dma-mapping.h>
+#include <common/common_mem.h>
static void *arc_dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
- unsigned long order = get_order(size);
+ unsigned long order;
struct page *page;
phys_addr_t paddr;
void *kvaddr;
int need_coh = 1, need_kvaddr = 0;
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
page = alloc_pages(gfp, order);
if (!page)
return NULL;
@@ -64,11 +70,37 @@
/* This is kernel Virtual address (0x7000_0000 based) */
if (need_kvaddr) {
+#if 0
kvaddr = ioremap_nocache(paddr, size);
if (kvaddr == NULL) {
__free_pages(page, order);
return NULL;
}
+#else
+ /*
+ * This is where we map physical memory to kernel virtual address (below 0x8000_0000).
+ * Special range of virtual memory is dedicated for this function.
+ * Size of dedicated virtual memory is full physical memory size, so we
+ * can map allocated memory 1:1.
+ * TODO: need to make virtual memory size smaller and keep list of allocated pages.
+ * We cannot allocate memory from 'vmalloc' virtual pages and run this function
+ * in atomic context, so let's have separated virtual addresses range.
+ */
+ kvaddr = (void*)(paddr - PAGE_OFFSET + DMA_NOCACHE_START);
+ if (ioremap_page_range((unsigned long)kvaddr,
+ (unsigned long)kvaddr + size,
+ (phys_addr_t)paddr,
+ PAGE_KERNEL_NO_CACHE)) {
+ free_pages((unsigned long) paddr, get_order(size));
+ kvaddr = NULL;
+ } else {
+ if (gfp & __GFP_ZERO)
+ memset(kvaddr, 0, size);
+ /* This is bus address, platform dependent */
+ *dma_handle = plat_phys_to_dma(dev, (void *)paddr);
+ }
+
+#endif
} else {
kvaddr = (void *)(u32)paddr;
}
@@ -99,9 +131,13 @@
(is_isa_arcv2() && ioc_exists);
if (PageHighMem(page) || !is_non_coh)
+#if 0
iounmap((void __force __iomem *)vaddr);
-
+#else
+ unmap_kernel_range((unsigned long)vaddr, PAGE_ALIGN(size));
+#endif
__free_pages(page, get_order(size));
+
}
/*
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index af63f4a..11fe132 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -78,8 +78,11 @@
* be in an interrupt or a critical region, and should
* only copy the information from the master page table,
* nothing more.
+ * Quantenna customization:VMALLOC_END->PAGE_OFFSET,
+ * we have VMALLOC, PCI_REMAP and DMA_NOCACHE kernel virtual memory regions,
+ * not only VMALLOC.
*/
- if (address >= VMALLOC_START) {
+ if (address >= VMALLOC_START && address <= PAGE_OFFSET) {
ret = handle_kernel_vaddr_fault(address);
if (unlikely(ret))
goto bad_area_nosemaphore;
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 8be9303..8a9e5b6 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -29,6 +29,8 @@
static const unsigned long low_mem_start = CONFIG_LINUX_LINK_BASE;
static unsigned long low_mem_sz;
+#define QTN_MM_DEBUG 1
+
#ifdef CONFIG_HIGHMEM
static unsigned long min_high_pfn, max_high_pfn;
static u64 high_mem_start;
@@ -72,6 +74,24 @@
pr_info("Memory @ %llx [%lldM] %s\n",
base, TO_MB(size), !in_use ? "Not used":"");
+
+#if QTN_MM_DEBUG
+ pr_info("mm_init: RUBY_MAX_DRAM_SIZE =%08x\n", RUBY_MAX_DRAM_SIZE);
+ pr_info("mm_init: DMA_NOCACHE_START =%08x\n", DMA_NOCACHE_START);
+ pr_info("mm_init: DMA_NOCACHE_END/PAGE offset =%08x\n", PAGE_OFFSET);
+
+ pr_info("mm_init: PCI_REMAP_SIZE =%08x\n", PCI_REMAP_SIZE);
+ pr_info("mm_init: PCI_REMAP_START =%08x\n", PCI_REMAP_START);
+ pr_info("mm_init: PCI_REMAP_END =%08x\n", PCI_REMAP_END);
+
+ pr_info("mm_init: TASK size =%08x\n", TASK_SIZE);
+ pr_info("mm_init: TASK_UNMAPPED_BASE =%08x\n", TASK_UNMAPPED_BASE);
+ pr_info("mm_init: PAGE offset =%08x\n", PAGE_OFFSET);
+ pr_info("mm_init: PCI_REMAP_START =%08x\n", PCI_REMAP_START);
+ pr_info("mm_init: vmalloc start =%08x, size=%08x, end=%08x\n", VMALLOC_START, VMALLOC_SIZE, VMALLOC_END);
+ pr_info("mm_init: User kernel gutter =%08x\n", USER_KERNEL_GUTTER);
+#endif
+
}
#ifdef CONFIG_BLK_DEV_INITRD
@@ -108,6 +128,13 @@
init_mm.end_data = (unsigned long)_edata;
init_mm.brk = (unsigned long)_end;
+#if QTN_MM_DEBUG
+ pr_info("init mm start code =%08x\n", init_mm.start_code);
+ pr_info("init mm end code =%08x\n", init_mm.end_code);
+ pr_info("init mm end data =%08x\n", init_mm.end_data);
+ pr_info("init mm brk =%08x\n", init_mm.brk);
+#endif
+
/* first page of system - kernel .vector starts here */
min_low_pfn = ARCH_PFN_OFFSET;
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index f1967ee..39330ff 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -41,6 +41,7 @@
#include <asm/pgtable.h>
#include <asm/arcregs.h>
#include <asm/cache.h>
+#include <asm/mem.h>
#include <asm/processor.h>
#include <asm/tlb-mmu1.h>
diff --git a/arch/arc/plat-qtn/Kconfig b/arch/arc/plat-qtn/Kconfig
new file mode 100644
index 0000000..a5434f1
--- /dev/null
+++ b/arch/arc/plat-qtn/Kconfig
@@ -0,0 +1,28 @@
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+
+menuconfig ARC_PLAT_QTN
+ bool "Quantenna Platforms"
+ select DW_APB_ICTL
+ select GPIO_DWAPB
+ select OF_GPIO
+ select GENERIC_IRQ_CHIP
+ select ARCH_REQUIRE_GPIOLIB
+ select MIGHT_HAVE_PCI
+ select ARC_PLAT_NEEDS_PHYS_TO_DMA
+ select QTN_PLATFORM_MISALIGN_WAR
+ help
+ Support for Quantenna platforms
+
+if ARC_PLAT_QTN
+
+config ARCH_QSR1000
+ depends on ISA_ARCOMPACT
+ bool "Quantenna QSR1000 architecture"
+ help
+ This adds support for Quantenna QSR1000 architecture
+
+endif
diff --git a/arch/arc/plat-qtn/Makefile b/arch/arc/plat-qtn/Makefile
new file mode 100644
index 0000000..54eba7a
--- /dev/null
+++ b/arch/arc/plat-qtn/Makefile
@@ -0,0 +1,7 @@
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+
+obj-$(CONFIG_ARCH_QSR1000) += qsr1000.o
diff --git a/arch/arc/plat-qtn/include/plat/dma.h b/arch/arc/plat-qtn/include/plat/dma.h
new file mode 100644
index 0000000..04829ed
--- /dev/null
+++ b/arch/arc/plat-qtn/include/plat/dma.h
@@ -0,0 +1,9 @@
+#ifndef ARC_PLAT_QTN_DMA_MAPPING_H
+#define ARC_PLAT_QTN_DMA_MAPPING_H
+
+#include <common/common_mem.h>
+
+#define plat_dma_to_phys(dev, dma_handle) ((phys_addr_t)virt_to_phys(bus_to_virt(dma_handle)))
+#define plat_phys_to_dma(dev, paddr) ((dma_addr_t)virt_to_bus(phys_to_virt(paddr)))
+
+#endif
diff --git a/arch/arc/plat-qtn/qsr1000.c b/arch/arc/plat-qtn/qsr1000.c
new file mode 100644
index 0000000..dce2310
--- /dev/null
+++ b/arch/arc/plat-qtn/qsr1000.c
@@ -0,0 +1,25 @@
+/*
+ * Quantenna QSR1000 platform
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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.
+ *
+ */
+
+#include <linux/of_platform.h>
+#include <asm/mach_desc.h>
+
+static const char *qsr1000_compat[] __initconst = {
+ "qtn,qsr1000",
+ NULL,
+};
+
+MACHINE_START(QSR1000, "Quantenna QSR1000")
+ .dt_compat = qsr1000_compat,
+MACHINE_END
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0158d3b..5a526b0 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -858,6 +858,20 @@
}
EXPORT_SYMBOL_GPL(add_input_randomness);
+void add_qtn_randomness(const unsigned int *random_buf, const unsigned int n)
+{
+ int entropy_estimate = 0;
+ int i;
+
+ mix_pool_bytes(&input_pool, (void *)random_buf, sizeof(int) * n);
+ /* trying to be conservative on estimate: shift by 2 and limit by 8 */
+ for (i = 0; i < n; i++) {
+ entropy_estimate += min_t(int, fls(random_buf[i] >> 2), 8);
+ }
+ credit_entropy_bits(&input_pool, entropy_estimate);
+}
+EXPORT_SYMBOL(add_qtn_randomness);
+
static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
#ifdef ADD_INTERRUPT_BENCH
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c5dc2c36..a07925a 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -77,6 +77,7 @@
PHY_STATE_STR(CHANGELINK)
PHY_STATE_STR(HALTED)
PHY_STATE_STR(RESUMING)
+ PHY_STATE_STR(QTNPM)
}
return NULL;
@@ -1071,6 +1072,9 @@
phydev->adjust_link(phydev->attached_dev);
}
break;
+ case PHY_QTNPM:
+ needs_aneg = 1;
+ break;
}
mutex_unlock(&phydev->lock);
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 965911d..8ee373b 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1189,7 +1189,7 @@
* */
int nvmem_device_write(struct nvmem_device *nvmem,
unsigned int offset,
- size_t bytes, void *buf)
+ size_t bytes, const void *buf)
{
int rc;
diff --git a/fs/open.c b/fs/open.c
index 93ae3cd..b936cf6 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1025,6 +1025,7 @@
putname(tmp);
return fd;
}
+EXPORT_SYMBOL_GPL(sys_open);
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
diff --git a/fs/read_write.c b/fs/read_write.c
index 933b53a..32aa8d6 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -319,6 +319,7 @@
fdput_pos(f);
return retval;
}
+EXPORT_SYMBOL_GPL(sys_read);
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned int, whence)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c..d873800 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -37,6 +37,12 @@
extern char __entry_text_start[], __entry_text_end[];
extern char __start_rodata[], __end_rodata[];
+#ifdef CONFIG_ARCH_RUBY_NUMA
+extern char __sram_start[], __sram_end[];
+extern char __sram_text_start[], __sram_text_end[];
+extern char __sram_data_start[], __sram_data_end[];
+#endif
+
/* Start and end of .ctors section - used for constructor calls. */
extern char __ctors_start[], __ctors_end[];
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0df4a51..bbe1d5f 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -408,6 +408,8 @@
*/
struct clk *clk_get_sys(const char *dev_id, const char *con_id);
+struct clk *qtn_clk_get(struct device *dev, const char *id);
+unsigned long qtn_clk_get_rate(struct clk *clk);
#else /* !CONFIG_HAVE_CLK */
static inline struct clk *clk_get(struct device *dev, const char *id)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 71c1b21..c17327e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -383,8 +383,10 @@
struct dma_map_ops *ops = get_dma_ops(dev);
BUG_ON(!ops);
- WARN_ON(irqs_disabled());
+#if 0
+ WARN_ON(irqs_disabled());
+#endif
if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
return;
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 37ff4a6..f609691 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -105,6 +105,21 @@
}
/**
+ * is_zero_ether_addr_unaligned - Determine if given Ethernet address is all zeros.
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is all zeroes.
+ */
+static inline bool is_zero_ether_addr_unaligned(const u8 *addr)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ return is_zero_ether_addr(addr);
+#else
+ return (addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == 0;
+#endif
+}
+
+/**
* is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index a5f6ce6..4cbb329 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -109,6 +109,7 @@
extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev,
__be16 vlan_proto, u16 vlan_id);
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
+extern int vlan_check_vlan_exist(struct net_device *dev, u16 vlan_id);
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
@@ -269,6 +270,13 @@
BUG();
return 0;
}
+
+static inline int
+vlan_check_vlan_exist(struct net_device *dev, u16 vlan_id)
+{
+ return 0;
+}
+
#endif
static inline bool vlan_hw_offload_capable(netdev_features_t features,
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 492bc65..5f2004f 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -20,6 +20,9 @@
#include <linux/skbuff.h>
#include <uapi/linux/ip.h>
+#define QTN_IP_REALIGN_MAX (4) /* Reserve tailroom for realignment on IP header */
+#define QTN_IP_REALIGN_BYTES (2) /* realignment bytes on IP header */
+
static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
{
return (struct iphdr *)skb_network_header(skb);
@@ -34,4 +37,35 @@
{
return (struct iphdr *)skb_transport_header(skb);
}
+
+static inline struct iphdr *ip_hdr_aligned(struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+#ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR
+ int err = 0;
+
+ if (unlikely(((uint32_t)iph & 0x3) == QTN_IP_REALIGN_BYTES)) {
+ if (unlikely((skb->end - skb->tail) < QTN_IP_REALIGN_BYTES)) {
+ err = pskb_expand_head(skb, 0, QTN_IP_REALIGN_MAX, GFP_ATOMIC);
+ if (err)
+ panic("###### QTN: %s over panic and expand fail\n", __func__);
+ }
+ M_FLAG_SET(skb, M_HAS_MISALIGN);
+ memmove(skb->head + QTN_IP_REALIGN_BYTES, skb->head, skb->end - skb->head - QTN_IP_REALIGN_BYTES);
+ skb->data += QTN_IP_REALIGN_BYTES;
+ skb->tail += QTN_IP_REALIGN_BYTES;
+ skb->mac_header += QTN_IP_REALIGN_BYTES;
+ if (skb->network_header)
+ skb->network_header += QTN_IP_REALIGN_BYTES;
+ if ( skb->transport_header)
+ skb->transport_header += QTN_IP_REALIGN_BYTES;
+ iph = ip_hdr(skb);
+ }
+#endif
+
+ return iph;
+}
+
+
#endif /* _LINUX_IP_H */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 5c91b0b..1a8e874 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -83,6 +83,43 @@
return (struct ipv6hdr *)skb_network_header(skb);
}
+#ifndef QTN_IP_REALIGN_MAX
+#define QTN_IP_REALIGN_MAX (4) /* Reserve tailroom for realignment on IP header */
+#endif
+
+#ifndef QTN_IP_REALIGN_BYTES
+#define QTN_IP_REALIGN_BYTES (2) /* realignment bytes on IP header */
+#endif
+
+static inline struct ipv6hdr *ipv6_hdr_aligned(struct sk_buff *skb)
+{
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+#ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR
+ int err = 0;
+
+ if (unlikely(((uint32_t)ip6h & 0x3) == QTN_IP_REALIGN_BYTES)) {
+ if (unlikely((skb->end - skb->tail) < QTN_IP_REALIGN_BYTES)) {
+ err = pskb_expand_head(skb, 0, QTN_IP_REALIGN_MAX, GFP_ATOMIC);
+ if (err)
+ panic("###### QTN: %s over panic and expand fail\n", __func__);
+ }
+
+ M_FLAG_SET(skb, M_HAS_MISALIGN);
+ memmove(skb->head + QTN_IP_REALIGN_BYTES, skb->head, skb->end - skb->head - QTN_IP_REALIGN_BYTES);
+ skb->data += QTN_IP_REALIGN_BYTES;
+ skb->tail += QTN_IP_REALIGN_BYTES;
+ skb->mac_header += QTN_IP_REALIGN_BYTES;
+ if (skb->network_header)
+ skb->network_header += QTN_IP_REALIGN_BYTES;
+ if ( skb->transport_header)
+ skb->transport_header += QTN_IP_REALIGN_BYTES;
+ ip6h = ipv6_hdr(skb);
+ }
+#endif
+
+ return ip6h;
+}
+
static inline struct ipv6hdr *inner_ipv6_hdr(const struct sk_buff *skb)
{
return (struct ipv6hdr *)skb_inner_network_header(skb);
diff --git a/include/linux/module.h b/include/linux/module.h
index 3daf2b3..93a3058 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -406,7 +406,9 @@
/* Core layout: rbtree is accessed frequently, so keep together. */
struct module_layout core_layout __module_layout_align;
struct module_layout init_layout;
-
+#ifdef CONFIG_ARCH_RUBY_NUMA
+ struct module_layout sram_layout;
+#endif
/* Arch-specific module values */
struct mod_arch_specific arch;
@@ -524,6 +526,15 @@
addr < (unsigned long)mod->init_layout.base + mod->init_layout.size;
}
+#ifdef CONFIG_ARCH_RUBY_NUMA
+static inline bool within_module_sram(unsigned long addr,
+ const struct module *mod)
+{
+ return (unsigned long)mod->sram_layout.base <= addr &&
+ addr < (unsigned long)mod->sram_layout.base + mod->sram_layout.size;
+}
+#endif
+
static inline bool within_module(unsigned long addr, const struct module *mod)
{
return within_module_init(addr, mod) || within_module_core(addr, mod);
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 4d0cb9b..ade49a6 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -28,6 +28,16 @@
/* Free memory returned from module_alloc. */
void module_memfree(void *module_region);
+#ifdef CONFIG_ARCH_RUBY_NUMA
+/* Allocator used for allocating SRAM sections (and not only). Returns NULL on
+ * failure. */
+void *heap_sram_alloc(unsigned long size);
+/* Free memory returned from heap_sram_alloc. */
+void heap_sram_free(void *ptr);
+/* Return true if pointer from this heap */
+int heap_sram_ptr(void *ptr);
+#endif
+
/*
* Apply the given relocation to the (simplified) ELF. Return -error
* or 0.
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index da4b33b..e5079e2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -180,6 +180,13 @@
unsigned long tx_window_errors;
unsigned long rx_compressed;
unsigned long tx_compressed;
+ /* for some specific packets counting*/
+ unsigned long rx_unicast_packets;
+ unsigned long tx_unicast_packets;
+ unsigned long tx_multicast_packets;
+ unsigned long rx_broadcast_packets;
+ unsigned long tx_broadcast_packets;
+ unsigned long rx_unknown_packets;
};
@@ -1363,6 +1370,7 @@
IFF_RXFH_CONFIGURED = 1<<25,
IFF_PHONY_HEADROOM = 1<<26,
IFF_MACSEC = 1<<27,
+ IFF_QTN_WLAN_DEV = 1<<28,
};
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
@@ -1392,6 +1400,7 @@
#define IFF_TEAM IFF_TEAM
#define IFF_RXFH_CONFIGURED IFF_RXFH_CONFIGURED
#define IFF_MACSEC IFF_MACSEC
+#define IFF_QTN_WLAN_DEV IFF_QTN_WLAN_DEV
/**
* struct net_device - The DEVICE structure.
@@ -1863,6 +1872,18 @@
struct phy_device *phydev;
struct lock_class_key *qdisc_tx_busylock;
bool proto_down;
+
+#define QTN_FLAG_WIFI_DEVICE 0x80000000
+#define QTN_FLAG_INTRA_BSS_ISOLATE 0x40000000
+#define QTN_FLAG_BSS_ISOLATE 0x20000000
+#define QTN_FLAG_WIFI_INTRA_BSS (QTN_FLAG_WIFI_DEVICE | QTN_FLAG_INTRA_BSS_ISOLATE)
+#define QTN_FLAG_WIFI_BSS_ISOLATE (QTN_FLAG_WIFI_DEVICE | QTN_FLAG_BSS_ISOLATE)
+
+#define QTN_FLAG_IS_INTRA_BSS(_flag_) \
+ (((_flag_) & QTN_FLAG_WIFI_INTRA_BSS) == QTN_FLAG_WIFI_INTRA_BSS)
+#define QTN_FLAG_IS_BSS_ISOLATE(_flag_) \
+ (((_flag_) & QTN_FLAG_WIFI_BSS_ISOLATE) == QTN_FLAG_WIFI_BSS_ISOLATE)
+ u32 qtn_flags;
};
#define to_net_dev(d) container_of(d, struct net_device, dev)
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 9bb77d3..066fa73 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -45,7 +45,7 @@
int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
size_t bytes, void *buf);
int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
- size_t bytes, void *buf);
+ size_t bytes, const void *buf);
ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
struct nvmem_cell_info *info, void *buf);
int nvmem_device_cell_write(struct nvmem_device *nvmem,
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 8f16299..8ec3c6b 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -115,6 +115,22 @@
#define DEFINE_PER_CPU(type, name) \
DEFINE_PER_CPU_SECTION(type, name, "")
+/* Variant for SRAM per-CPU variables*/
+#define DECLARE_SRAM_PER_CPU_SECTION(type, name, section) \
+ extern \
+ __attribute__((__section__(__sram_data_sect_name section))) \
+ PER_CPU_ATTRIBUTES __typeof__(type) name
+
+#define DEFINE_SRAM_PER_CPU_SECTION(type, name, section) \
+ __attribute__((__section__(__sram_data_sect_name section))) \
+ PER_CPU_ATTRIBUTES __typeof__(type) name
+
+#define DECLARE_SRAM_PER_CPU(type, name) \
+ DECLARE_SRAM_PER_CPU_SECTION(type, name, "")
+
+#define DEFINE_SRAM_PER_CPU(type, name) \
+ DEFINE_SRAM_PER_CPU_SECTION(type, name, "")
+
/*
* Declaration/definition used for per-CPU variables that must come first in
* the set of variables.
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 2d24b28..67fad42 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -311,7 +311,8 @@
PHY_FORCING,
PHY_CHANGELINK,
PHY_HALTED,
- PHY_RESUMING
+ PHY_RESUMING,
+ PHY_QTNPM
};
/**
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 0f65d36..a5cb833 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -16,6 +16,8 @@
PM_QOS_NETWORK_LATENCY,
PM_QOS_NETWORK_THROUGHPUT,
PM_QOS_MEMORY_BANDWIDTH,
+ PM_QOS_POWER_SAVE,
+ PM_QOS_POWER_EMAC,
/* insert new class ID */
PM_QOS_NUM_CLASSES,
@@ -72,7 +74,8 @@
PM_QOS_UNITIALIZED,
PM_QOS_MAX, /* return the largest value */
PM_QOS_MIN, /* return the smallest value */
- PM_QOS_SUM /* return the sum */
+ PM_QOS_SUM, /* return the sum */
+ PM_QOS_TGT /* return the target value */
};
/*
@@ -134,6 +137,15 @@
int pm_qos_request_active(struct pm_qos_request *req);
s32 pm_qos_read_value(struct pm_qos_constraints *c);
+void pm_qos_remove_requirement(int pm_qos_class, const char *name);
+
+int pm_qos_requirement(int pm_qos_class);
+int pm_qos_add_requirement(int pm_qos_class, const char *name, s32 value);
+int pm_qos_update_requirement(int pm_qos_class, const char *name,
+ s32 new_value);
+
+void pm_qos_refresh_notifiers(const int pm_qos_class);
+
#ifdef CONFIG_PM
enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
diff --git a/include/linux/random.h b/include/linux/random.h
index e47e533..64966c5 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -21,6 +21,7 @@
extern void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value);
extern void add_interrupt_randomness(int irq, int irq_flags);
+extern void add_qtn_randomness(const unsigned int *random_buf, const unsigned int n);
extern void get_random_bytes(void *buf, int nbytes);
extern int add_random_ready_callback(struct random_ready_callback *rdy);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f39b371..0e5e2ba 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -38,6 +38,25 @@
#include <linux/splice.h>
#include <linux/in6.h>
#include <net/flow.h>
+#include <include/qtn/qtn_skb_cb.h>
+#include <common/queue.h>
+
+#define QTN_SKB_ALLOC_TRACE 0
+#if QTN_SKB_ALLOC_TRACE
+#define QTN_SKB_ALLOC_TRACE_ARGNAMES(file, func, line) , \
+ const char *file, \
+ const char *func, \
+ const uint32_t line
+#define QTN_SKB_ALLOC_TRACE_ARGS \
+ QTN_SKB_ALLOC_TRACE_ARGNAMES(__qsat_file, __qsat_func, __qsat_line)
+#define QTN_SKB_ALLOC_TRACE_ARGVARS , __qsat_file, __qsat_func, __qsat_line
+#define QTN_SKB_ALLOC_TRACE_ARGSRC , __FILE__, __FUNCTION__, __LINE__
+#else
+#define QTN_SKB_ALLOC_TRACE_ARGNAMES(file, func, line)
+#define QTN_SKB_ALLOC_TRACE_ARGS
+#define QTN_SKB_ALLOC_TRACE_ARGVARS
+#define QTN_SKB_ALLOC_TRACE_ARGSRC
+#endif
/* The interface for checksum offload between the stack and networking drivers
* is as follows...
@@ -239,6 +258,7 @@
struct pipe_inode_info;
struct iov_iter;
struct napi_struct;
+struct skb_allocator;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack {
@@ -421,11 +441,18 @@
* Warning : all fields before dataref are cleared in __alloc_skb()
*/
atomic_t dataref;
+ const struct skb_allocator *allocator;
/* Intermediate layers must ensure that destructor_arg
* remains valid until skb destructor */
void * destructor_arg;
-
+#if QTN_SKB_ALLOC_TRACE
+ TAILQ_ENTRY(skb_shared_info) alloc_next;
+ const char *alloc_file;
+ const char *alloc_func;
+ uint32_t alloc_line;
+ uint32_t alloc_jiff;
+#endif
/* must be last field, see pskb_expand_head() */
skb_frag_t frags[MAX_SKB_FRAGS];
};
@@ -554,6 +581,8 @@
return diff > 0;
}
+struct qtn_skb_recycle_list;
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
@@ -563,6 +592,7 @@
* @sk: Socket we are owned by
* @dev: Device we arrived on/are leaving by
* @cb: Control buffer. Free for use by every layer. Put private vars here
+ * @qtn_cb: Quantenna control buffer
* @_skb_refdst: destination entry (with norefcount bit)
* @sp: the security path, used for xfrm
* @len: Length of actual data
@@ -639,6 +669,7 @@
};
struct sock *sk;
struct net_device *dev;
+ struct net_device *orig_dev;
/*
* This is the control buffer. It is free to use for every
@@ -647,6 +678,7 @@
* first. This is owned by whoever has the skb queued ATM.
*/
char cb[48] __aligned(8);
+ struct qtn_skb_cb qtn_cb;
unsigned long _skb_refdst;
void (*destructor)(struct sk_buff *skb);
@@ -676,6 +708,11 @@
head_frag:1,
xmit_more:1;
/* one bit hole */
+ __u8 is_recyclable:1,
+ cache_is_cleaned:1,
+ hbm_no_free:1;
+
+ __u8 ext_l2_filter:1;
kmemcheck_bitfield_end(flags1);
/* fields enclosed in headers_start/headers_end are copied
@@ -743,6 +780,17 @@
__u32 hash;
__be16 vlan_proto;
__u16 vlan_tci;
+ __u16 hw_vlan_id;
+
+ struct qtn_skb_recycle_list *recycle_list;
+
+ __u32 src_port;
+ __u32 dest_port;
+
+#ifdef CONFIG_TRACEPOINTS
+ struct sk_buff_trace_cookie *trace_cookie;
+#endif
+
#if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
union {
unsigned int napi_id;
@@ -788,6 +836,16 @@
*data;
unsigned int truesize;
atomic_t users;
+
+ const struct skb_allocator *allocator;
+ struct skb_shared_info *__shinfo;
+#if QTN_SKB_ALLOC_TRACE
+ TAILQ_ENTRY(sk_buff) alloc_next;
+ const char *alloc_file;
+ const char *alloc_func;
+ uint32_t alloc_line;
+ uint32_t alloc_jiff;
+#endif
};
#ifdef __KERNEL__
@@ -868,6 +926,23 @@
{
return (skb->_skb_refdst & SKB_DST_NOREF) && skb_dst(skb);
}
+struct skb_allocator {
+ const char *name;
+ struct sk_buff *(*skb_alloc)(gfp_t priority, int fclone, int node);
+ void (*skb_free)(struct sk_buff *skb, int fclone);
+ uint8_t *(*payload_alloc)(struct skb_shared_info **shinfo,
+ size_t size, gfp_t priority, int node);
+ void (*payload_free)(struct sk_buff *skb);
+ size_t max_size;
+};
+
+struct sk_buff *skb_allocator_kmem_caches_skb_alloc(gfp_t gfp_mask, int fclone, int node);
+void skb_allocator_kmem_caches_skb_free(struct sk_buff *skb, int fclone);
+
+#define SKB_ALLOCATORS_MAX 4
+#define SKB_ALLOCATOR_KMEM_CACHE 1
+extern void skb_allocator_register(uint8_t src,
+ const struct skb_allocator *allocator, int set_default);
static inline struct rtable *skb_rtable(const struct sk_buff *skb)
{
@@ -887,6 +962,9 @@
struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags,
int node);
+extern void __alloc_skb_init(struct sk_buff *skb, struct skb_shared_info *shinfo,
+ u8 *data, unsigned int size,
+ int fclone, const struct skb_allocator *allocator);
struct sk_buff *__build_skb(void *data, unsigned int frag_size);
struct sk_buff *build_skb(void *data, unsigned int frag_size);
static inline struct sk_buff *alloc_skb(unsigned int size,
@@ -1185,7 +1263,7 @@
#endif
/* Internal */
-#define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB)))
+#define skb_shinfo(SKB) ((SKB)->__shinfo)
static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
{
@@ -1671,6 +1749,12 @@
void skb_append(struct sk_buff *old, struct sk_buff *newsk,
struct sk_buff_head *list);
+static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk,
+ struct sk_buff_head *list)
+{
+ __skb_insert(newsk, old, old->next, list);
+}
+
static inline void __skb_queue_before(struct sk_buff_head *list,
struct sk_buff *next,
struct sk_buff *newsk)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index aeb3e6d..50300c9 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -127,6 +127,9 @@
struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
unsigned long,
void (*)(void *));
+struct kmem_cache *kmem_cache_find(const char *);
+void kmem_cache_calc_usage(struct kmem_cache *, unsigned int *, unsigned int *,
+ unsigned int *, unsigned int *);
void kmem_cache_destroy(struct kmem_cache *);
int kmem_cache_shrink(struct kmem_cache *);
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 8694f7a..268ebc6 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -2,6 +2,7 @@
#define _LINUX_SLAB_DEF_H
#include <linux/reciprocal_div.h>
+#include <include/qtn/qtn_skb_size.h>
/*
* Definitions unique to the original Linux SLAB allocator.
@@ -45,7 +46,9 @@
int align;
/* 5) statistics */
-#ifdef CONFIG_DEBUG_SLAB
+/* #ifdef CONFIG_DEBUG_SLAB */
+#define QTN_SLAB_STATS 1
+#ifdef QTN_SLAB_STATS
unsigned long num_active;
unsigned long num_allocations;
unsigned long high_mark;
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 1c8b682..2066fa7 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -208,7 +208,7 @@
struct rcu_head rcu;
};
-static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf)
+static inline void ipv6_eth_mc_map(const struct in6_addr *addr, uint8_t *buf)
{
/*
* +-------+-------+-------+-------+-------+-------+
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index e0f4109..0306b3e 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -257,6 +257,7 @@
/* Flags available in struct iw_request_info */
#define IW_REQUEST_FLAG_COMPAT 0x0001 /* Compat ioctl call */
+#define IW_REQUEST_FLAG_KILOBYTES 0x8000 /* Scan results, kilobytes*/
/* Type of headers we know about (basically union iwreq_data) */
#define IW_HEADER_TYPE_NULL 0 /* Not available */
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 2d8edaa..d0f847e 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -194,6 +194,17 @@
int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev,
int dir);
+extern int ndisc_addr_option_pad(unsigned short type);
+
+void ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data);
+
+struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
+ int len);
+
+void ip6_nd_hdr(struct sk_buff *skb,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ int hop_limit, int len);
/*
* IGMP
diff --git a/include/trace/ippkt.h b/include/trace/ippkt.h
new file mode 100755
index 0000000..2dc293c
--- /dev/null
+++ b/include/trace/ippkt.h
@@ -0,0 +1,51 @@
+#ifndef _TRACE_IPPKT_H_
+#define _TRACE_IPPKT_H_
+
+#include <linux/tracepoint.h>
+
+enum trace_ippkt_loc_id {
+ TRACE_IPPKT_LOC_ETH_RX,
+ TRACE_IPPKT_LOC_ETH_TX,
+ TRACE_IPPKT_LOC_WLAN_RX,
+ TRACE_IPPKT_LOC_WLAN_TX,
+ TRACE_IPPKT_LOC_MAX
+};
+
+enum trace_ippkt_drop_rsn {
+ TRACE_IPPKT_DROP_RSN_NONE,
+ TRACE_IPPKT_DROP_RSN_SCH,
+ TRACE_IPPKT_DROP_RSN_VSP,
+ TRACE_IPPKT_DROP_RSN_INVALID,
+ TRACE_IPPKT_DROP_RSN_AUTH,
+ TRACE_IPPKT_DROP_RSN_MAC_DEAD,
+ TRACE_IPPKT_DROP_RSN_AID_STALE,
+ TRACE_IPPKT_DROP_RSN_NO_DEST,
+ TRACE_IPPKT_DROP_RSN_NO_DESC,
+ TRACE_IPPKT_DROP_RSN_ETH_RX,
+ TRACE_IPPKT_DROP_RSN_AP_ISOLATE,
+ TRACE_IPPKT_DROP_RSN_NO_WDS,
+ TRACE_IPPKT_DROP_RSN_NO_WDS_BA,
+ TRACE_IPPKT_DROP_RSN_SHOULD_DROP,
+ TRACE_IPPKT_DROP_RSN_COPY,
+ TRACE_IPPKT_DROP_RSN_CTRL,
+ TRACE_IPPKT_DROP_RSN_3ADDR,
+ TRACE_IPPKT_DROP_RSN_RECONFIG,
+ TRACE_IPPKT_DROP_RSN_RGMII,
+ TRACE_IPPKT_DROP_RSN_MUC_TX_XATTEMPTS,
+ TRACE_IPPKT_DROP_RSN_MUC_TX_EXPIRED,
+ TRACE_IPPKT_DROP_RSN_MUC_TX_RESTRICT,
+ TRACE_IPPKT_DROP_RSN_MUC_RX_AGG_TIMEOUT,
+ TRACE_IPPKT_DROP_RSN_MUC_RX_AGG_EMPTY,
+ TRACE_IPPKT_DROP_RSN_PROXY_ARP,
+ TRACE_IPPKT_DROP_RSN_MAX
+};
+
+DECLARE_TRACE(ippkt_check,
+ TP_PROTO(void *pkt, uint32_t len, enum trace_ippkt_loc_id loc_id),
+ TP_ARGS(pkt, len, loc_id));
+
+DECLARE_TRACE(ippkt_dropped,
+ TP_PROTO(enum trace_ippkt_drop_rsn rsn, uint32_t cnt, uint8_t is_cumulative),
+ TP_ARGS(rsn, cnt, is_cumulative));
+
+#endif /* _TRACE_IPPKT_H_ */
diff --git a/include/trace/skb.h b/include/trace/skb.h
new file mode 100644
index 0000000..5e0dd07
--- /dev/null
+++ b/include/trace/skb.h
@@ -0,0 +1,33 @@
+#ifndef _TRACE_SKB_H_
+#define _TRACE_SKB_H_
+
+#include <linux/skbuff.h>
+#include <linux/tracepoint.h>
+
+DECLARE_TRACE(kfree_skb,
+ TP_PROTO(struct sk_buff *skb, void *location),
+ TP_ARGS(skb, location));
+
+DECLARE_TRACE(skb_perf_start,
+ TP_PROTO(struct sk_buff *skb, int path),
+ TP_ARGS(skb, path));
+
+DECLARE_TRACE(skb_perf_stamp,
+ TP_PROTO(struct sk_buff *skb, void *location),
+ TP_ARGS(skb, location));
+
+DECLARE_TRACE(skb_perf_finish,
+ TP_PROTO(struct sk_buff *skb),
+ TP_ARGS(skb));
+
+DECLARE_TRACE(skb_perf_copy,
+ TP_PROTO(struct sk_buff *new, struct sk_buff *old),
+ TP_ARGS(new, old));
+
+#ifdef CONFIG_TRACEPOINTS
+ #define trace_skb_perf_stamp_call(skb) do {__label__ addr; addr: trace_skb_perf_stamp(skb, &&addr);} while(0)
+#else
+ #define trace_skb_perf_stamp_call(skb) trace_skb_perf_stamp(skb, NULL)
+#endif
+
+#endif
diff --git a/include/uapi/linux/icmpv6.h b/include/uapi/linux/icmpv6.h
index 590beda..fa7e7a8 100644
--- a/include/uapi/linux/icmpv6.h
+++ b/include/uapi/linux/icmpv6.h
@@ -97,6 +97,9 @@
#define ICMPV6_MGM_REPORT 131
#define ICMPV6_MGM_REDUCTION 132
+#define ICMPV6_NEIGHBOUR_SOL 135
+#define ICMPV6_NEIGHBOUR_ADV 136
+
#define ICMPV6_NI_QUERY 139
#define ICMPV6_NI_REPLY 140
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index 397d503..02be45c 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -44,6 +44,10 @@
#define BRCTL_SET_PORT_PRIORITY 16
#define BRCTL_SET_PATH_COST 17
#define BRCTL_GET_FDB_ENTRIES 18
+#define BRCTL_SET_IGMP_SNOOP_STATE 19
+#define BRCTL_SET_SSDP_FLOOD_STATE 20
+#define BRCTL_SET_MC_DEBUG 21
+#define BRCTL_GET_MC_GROUP 22
#define BR_STATE_DISABLED 0
#define BR_STATE_LISTENING 1
@@ -51,6 +55,8 @@
#define BR_STATE_FORWARDING 3
#define BR_STATE_BLOCKING 4
+#define QTN_BR_SHOW_EXTRA 1
+
struct __bridge_info {
__u64 designated_root;
__u64 bridge_id;
@@ -93,9 +99,14 @@
__u8 mac_addr[ETH_ALEN];
__u8 port_no;
__u8 is_local;
+#ifdef QTN_BR_SHOW_EXTRA
+ __u16 sub_port;
+ __u16 vlan_id;
+#endif
__u32 ageing_timer_value;
__u8 port_hi;
- __u8 pad0;
+ __u8 is_wlan : 1;
+ __u8 pad0 : 7;
__u16 unused;
};
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index bb36bd5..529c36f 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -72,6 +72,14 @@
__u64 tx_compressed;
__u64 rx_nohandler; /* dropped, no handler found */
+
+ /* for some specific packets counting*/
+ __u64 rx_unicast_packets;
+ __u64 tx_unicast_packets;
+ __u64 tx_multicast_packets;
+ __u64 rx_broadcast_packets;
+ __u64 tx_broadcast_packets;
+ __u64 rx_unknown_packets;
};
/* The struct should be in sync with struct ifmap */
diff --git a/include/uapi/linux/sockios.h b/include/uapi/linux/sockios.h
index 8e7890b..aa01d5a 100644
--- a/include/uapi/linux/sockios.h
+++ b/include/uapi/linux/sockios.h
@@ -140,6 +140,8 @@
*/
#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */
+#define SIOCGDEVSTATS (SIOCDEVPRIVATE + 2)
+#define SIOCRDEVSTATS (SIOCDEVPRIVATE + 10) /* reset all the members of the net_device_stats to 0 */
/*
* These 16 ioctl calls are protocol private
diff --git a/include/uapi/linux/wireless.h b/include/uapi/linux/wireless.h
index c1592e3..5e9f823 100644
--- a/include/uapi/linux/wireless.h
+++ b/include/uapi/linux/wireless.h
@@ -538,6 +538,7 @@
#define IW_SCAN_TYPE_PASSIVE 1
/* Maximum size of returned data */
#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+#define DEFAULT_MAX_SCAN_RESULT_BUF (64 * 1024 - 1) /* In bytes */
/* Scan capability flags - in (struct iw_range *)->scan_capa */
#define IW_SCAN_CAPA_NONE 0x00
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 97b0df7..e2ca95d 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -121,6 +121,31 @@
.name = "memory_bandwidth",
};
+static BLOCKING_NOTIFIER_HEAD(power_save_notifier);
+static struct pm_qos_constraints power_save_constraints = {
+ .list = PLIST_HEAD_INIT(power_save_constraints.list),
+ .target_value = PM_QOS_DEFAULT_VALUE,
+ .default_value = PM_QOS_DEFAULT_VALUE,
+ .type = PM_QOS_TGT,
+ .notifiers = &power_save_notifier,
+};
+static struct pm_qos_object power_save_qos = {
+ .constraints = &power_save_constraints,
+ .name = "power_save",
+};
+
+static BLOCKING_NOTIFIER_HEAD(power_emac_notifier);
+static struct pm_qos_constraints power_emac_constraints = {
+ .list = PLIST_HEAD_INIT(power_emac_constraints.list),
+ .target_value = PM_QOS_DEFAULT_VALUE,
+ .default_value = PM_QOS_DEFAULT_VALUE,
+ .type = PM_QOS_TGT,
+ .notifiers = &power_emac_notifier,
+};
+static struct pm_qos_object power_emac_qos = {
+ .constraints = &power_emac_constraints,
+ .name = "power_emac",
+};
static struct pm_qos_object *pm_qos_array[] = {
&null_pm_qos,
@@ -128,6 +153,8 @@
&network_lat_pm_qos,
&network_throughput_pm_qos,
&memory_bandwidth_pm_qos,
+ &power_save_qos,
+ &power_emac_qos,
};
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
@@ -161,6 +188,9 @@
case PM_QOS_MAX:
return plist_last(&c->list)->prio;
+ case PM_QOS_TGT:
+ return c->target_value;
+
case PM_QOS_SUM:
plist_for_each(node, &c->list)
total_value += node->prio;
@@ -304,7 +334,12 @@
;
}
- curr_value = pm_qos_get_value(c);
+ if ((c == &power_save_constraints) || (c == &power_emac_constraints)) {
+ curr_value = new_value;
+ } else {
+ curr_value = pm_qos_get_value(c);
+ }
+
pm_qos_set_value(c, curr_value);
spin_unlock_irqrestore(&pm_qos_lock, flags);
@@ -585,6 +620,15 @@
}
EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
+void pm_qos_refresh_notifiers(const int pm_qos_class)
+{
+ blocking_notifier_call_chain(
+ pm_qos_array[pm_qos_class]->constraints->notifiers,
+/* atomic_read(&pm_qos_array[pm_qos_class]->target_value), NULL);*/
+ pm_qos_array[pm_qos_class]->constraints->target_value, NULL);
+}
+EXPORT_SYMBOL_GPL(pm_qos_refresh_notifiers);
+
/* User space interface to PM QoS classes via misc devices */
static int register_pm_qos_misc(struct pm_qos_object *qos, struct dentry *d)
{
diff --git a/mm/dmapool.c b/mm/dmapool.c
index abcbfe8..eda8b16 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -179,26 +179,30 @@
* device_create_file() and the second assumes that it has been done (I
* know it is a short window).
*/
- mutex_lock(&pools_reg_lock);
- mutex_lock(&pools_lock);
- if (list_empty(&dev->dma_pools))
- empty = true;
- list_add(&retval->pools, &dev->dma_pools);
- mutex_unlock(&pools_lock);
- if (empty) {
- int err;
- err = device_create_file(dev, &dev_attr_pools);
- if (err) {
- mutex_lock(&pools_lock);
- list_del(&retval->pools);
- mutex_unlock(&pools_lock);
- mutex_unlock(&pools_reg_lock);
- kfree(retval);
- return NULL;
+ if (dev) {
+ mutex_lock(&pools_reg_lock);
+ mutex_lock(&pools_lock);
+ if (list_empty(&dev->dma_pools))
+ empty = true;
+ list_add(&retval->pools, &dev->dma_pools);
+ mutex_unlock(&pools_lock);
+ if (empty) {
+ int err;
+
+ err = device_create_file(dev, &dev_attr_pools);
+ if (err) {
+ mutex_lock(&pools_lock);
+ list_del(&retval->pools);
+ mutex_unlock(&pools_lock);
+ mutex_unlock(&pools_reg_lock);
+ kfree(retval);
+ return NULL;
+ }
}
+ mutex_unlock(&pools_reg_lock);
}
- mutex_unlock(&pools_reg_lock);
+
return retval;
}
EXPORT_SYMBOL(dma_pool_create);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 82a116b..4f1bd87 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -709,6 +709,24 @@
},
};
+
+int vlan_check_vlan_exist(struct net_device *dev, u16 vlan_id)
+{
+ //TODO: Avinash.
+ //This function does not exist in 3.14. Need to check if its needed.
+#if 0
+ int ret;
+
+ rcu_read_lock();
+ ret = !!__find_vlan_dev(dev, vlan_id);
+ rcu_read_unlock();
+
+ return ret;
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(vlan_check_vlan_exist);
+
static int __net_init vlan_init_net(struct net *net)
{
struct vlan_net *vn = net_generic(net, vlan_net_id);
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 1270207..4393c8a 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -156,6 +156,8 @@
if (err < 0)
return err;
+ dev->if_port = real_dev->if_port;
+
return register_vlan_dev(dev);
}
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index a1cda5d..3e6b5d9 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -1,6 +1,10 @@
#
# Makefile for the IEEE 802.1d ethernet bridging layer.
#
+#
+EXTRA_CFLAGS += -Wall \
+ -I../drivers/include/shared \
+ -I../drivers/include/kernel
obj-$(CONFIG_BRIDGE) += bridge.o
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 3addc05..0373341 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -226,6 +226,12 @@
#if IS_ENABLED(CONFIG_ATM_LANE)
br_fdb_test_addr_hook = br_fdb_test_addr;
#endif
+ br_fdb_get_hook = br_fdb_get_ext;
+ br_fdb_put_hook = br_fdb_put;
+ br_fdb_get_attached_hook = br_fdb_get_attached;
+ br_fdb_delete_by_sub_port_hook = br_fdb_delete_by_sub_port;
+ br_fdb_update_const_hook = br_fdb_update_const;
+ br_fdb_fillbuf_hook = br_fdb_fillbuf;
pr_info("bridge: automatic filtering via arp/ip/ip6tables has been "
"deprecated. Update your scripts to load br_netfilter if you "
@@ -263,6 +269,12 @@
#if IS_ENABLED(CONFIG_ATM_LANE)
br_fdb_test_addr_hook = NULL;
#endif
+ br_fdb_get_hook = NULL;
+ br_fdb_put_hook = NULL;
+ br_fdb_get_attached_hook = NULL;
+ br_fdb_delete_by_sub_port_hook = NULL;
+ br_fdb_update_const_hook = NULL;
+ br_fdb_fillbuf_hook = NULL;
br_fdb_fini();
}
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 2c8095a..1ab3f82 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -73,15 +73,21 @@
goto out;
}
+#ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR
+ if (M_FLAG_ISSET(skb, M_HAS_MISALIGN))
+ dest = eth_hdr(skb)->h_dest;
+#endif
+
mdst = br_mdb_get(br, skb, vid);
if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
br_multicast_querier_exists(br, eth_hdr(skb)))
br_multicast_deliver(mdst, skb);
else
br_flood_deliver(br, skb, false);
- } else if ((dst = __br_fdb_get(br, dest, vid)) != NULL)
+ } else if ((dst = __br_fdb_get(br, dest, vid)) != NULL) {
+ skb->dest_port = dst->sub_port;
br_deliver(dst->dst, skb);
- else
+ } else
br_flood_deliver(br, skb, true);
out:
@@ -401,6 +407,9 @@
br->bridge_forward_delay = br->forward_delay = 15 * HZ;
br->ageing_time = BR_DEFAULT_AGEING_TIME;
+ br->igmp_snoop_enabled = BR_IGMP_SNOOP_ENABLED;
+ br->report_flood_interval = 1;
+
br_netfilter_rtable_init(br);
br_stp_timer_init(br);
br_multicast_init(br);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index c18080a..6348414 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -24,10 +24,25 @@
#include <linux/atomic.h>
#include <asm/unaligned.h>
#include <linux/if_vlan.h>
+#include <net/ip.h>
#include <net/switchdev.h>
#include "br_private.h"
+#include <qtn/iputil.h>
+#include <common/topaz_platform.h>
static struct kmem_cache *br_fdb_cache __read_mostly;
+/**
+ * Added by Quantenna
+ * Set cbk for each new bridge entry.
+ */
+#define BR_FWT_THRESH_HIGH (3 * TOPAZ_FWT_HW_TOTAL_ENTRIES / 4)
+#define BR_FWT_THRESH_CRITICAL (TOPAZ_FWT_HW_TOTAL_ENTRIES - 400)
+
+static br_add_entry_cbk g_add_fwt_entry_hook = NULL;
+static br_delete_entry_cbk g_delete_fwt_entry_hook = NULL;
+static br_fwt_ageing_time_cbk g_fwt_ageing_jiffies_hook = NULL;
+static br_fwt_get_ent_cnt g_fwt_get_ent_cnt_hook = NULL;
+
static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
const unsigned char *addr,
__u16 vid);
@@ -65,14 +80,28 @@
return br->topology_change ? br->forward_delay : br->ageing_time;
}
-static inline int has_expired(const struct net_bridge *br,
- const struct net_bridge_fdb_entry *fdb)
+static int br_get_timestamp_update_fwt(struct net_bridge_fdb_entry *fdb)
{
- return !fdb->is_static &&
- time_before_eq(fdb->updated + hold_time(br), jiffies);
+ int fwt_ageing_jiffies;
+
+ if (!fdb->is_static && !fdb->is_local && g_fwt_ageing_jiffies_hook) {
+ fwt_ageing_jiffies = g_fwt_ageing_jiffies_hook(fdb->addr.addr);
+ if (fwt_ageing_jiffies >= 0) {
+ fdb->updated = jiffies - fwt_ageing_jiffies;
+ return 1;
+ }
+ }
+ return 0;
}
-static inline int br_mac_hash(const unsigned char *mac, __u16 vid)
+static inline int has_expired(const struct net_bridge *br,
+ const struct net_bridge_fdb_entry *fdb)
+{
+ return !fdb->is_static &&
+ time_before_eq(fdb->updated + hold_time(br), jiffies);
+}
+
+static inline int br_mac_hash(const unsigned char *mac, u16 vid)
{
/* use 1 byte of OUI and 3 bytes of NIC */
u32 key = get_unaligned((u32 *)(mac + 2));
@@ -148,6 +177,18 @@
static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
{
+ /* Added by Quantenna */
+ if (f == br->br_fdb_attached) {
+ br->br_fdb_attached = NULL;
+ }
+
+ /*
+ * Added by Quantenna
+ * delete from fwt entry
+ */
+ if (f && g_delete_fwt_entry_hook && !f->is_local)
+ g_delete_fwt_entry_hook(f->addr.addr);
+
if (f->is_static)
fdb_del_hw_addr(br, f->addr.addr);
@@ -208,6 +249,22 @@
spin_unlock_bh(&br->hash_lock);
}
+void br_handle_fwt_capacity(struct net_bridge *br)
+{
+ uint16_t fwt_entries;
+
+ if (!g_fwt_get_ent_cnt_hook) {
+ return;
+ }
+ fwt_entries = g_fwt_get_ent_cnt_hook();
+ if (fwt_entries < BR_FWT_THRESH_CRITICAL) {
+ br->ageing_time = BR_AGE_MAX_SEC * HZ;
+ } else {
+ br->ageing_time = max((unsigned long)BR_AGE_MIN_SEC * HZ, br->ageing_time / 2);
+ mod_timer(&br->gc_timer, jiffies);
+ }
+}
+
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
{
struct net_bridge_vlan_group *vg;
@@ -241,7 +298,7 @@
insert:
/* insert new address, may fail if invalid address or dup. */
- fdb_insert(br, p, newaddr, 0);
+ fdb_insert(br, p, newaddr, br->vlan_id);
if (!vg || !vg->num_vlans)
goto done;
@@ -266,11 +323,11 @@
spin_lock_bh(&br->hash_lock);
/* If old entry was unassociated with any port, then delete it. */
- f = __br_fdb_get(br, br->dev->dev_addr, 0);
+ f = __br_fdb_get(br, br->dev->dev_addr, br->vlan_id);
if (f && f->is_local && !f->dst)
fdb_delete_local(br, NULL, f);
- fdb_insert(br, NULL, newaddr, 0);
+ fdb_insert(br, NULL, newaddr, br->vlan_id);
vg = br_vlan_group(br);
if (!vg || !vg->num_vlans)
goto out;
@@ -294,8 +351,16 @@
{
struct net_bridge *br = (struct net_bridge *)_data;
unsigned long delay = hold_time(br);
- unsigned long next_timer = jiffies + br->ageing_time;
int i;
+ uint16_t fwt_entries;
+
+ if (g_fwt_get_ent_cnt_hook && !br->topology_change) {
+ fwt_entries = g_fwt_get_ent_cnt_hook();
+ if (fwt_entries < BR_FWT_THRESH_HIGH) {
+ mod_timer(&br->gc_timer, jiffies + delay);
+ return;
+ }
+ }
spin_lock(&br->hash_lock);
for (i = 0; i < BR_HASH_SIZE; i++) {
@@ -304,20 +369,20 @@
hlist_for_each_entry_safe(f, n, &br->hash[i], hlist) {
unsigned long this_timer;
+
if (f->is_static)
continue;
if (f->added_by_external_learn)
continue;
+ br_get_timestamp_update_fwt(f);
this_timer = f->updated + delay;
if (time_before_eq(this_timer, jiffies))
fdb_delete(br, f);
- else if (time_before(this_timer, next_timer))
- next_timer = this_timer;
}
}
spin_unlock(&br->hash_lock);
- mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
+ mod_timer(&br->gc_timer, round_jiffies_up(jiffies + delay));
}
/* Completely flush all dynamic entries in forwarding database.*/
@@ -337,6 +402,35 @@
spin_unlock_bh(&br->hash_lock);
}
+/* Added by Quantenna */
+unsigned char br_fdb_delete_by_sub_port(struct net_bridge *br,
+ const struct net_bridge_port *p,
+ port_id sub_port)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&br->hash_lock, flags);
+ for (i = 0; i < BR_HASH_SIZE; i++) {
+ struct hlist_node *h, *g;
+
+ hlist_for_each_safe(h, g, &br->hash[i]) {
+ struct net_bridge_fdb_entry *f
+ = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
+ if ((f->dst == p) &&
+ (f->sub_port == sub_port) &&
+ !f->is_static) {
+ fdb_delete(br, f);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&br->hash_lock, flags);
+
+ br_mdb_delete_by_sub_port(br, p, sub_port);
+
+ return 0;
+}
+
/* Flush all entries referring to a specific port.
* if do_all is set also flush static entries
* if vid is set delete all entries that match the vlan_id
@@ -370,9 +464,10 @@
}
spin_unlock_bh(&br->hash_lock);
}
+EXPORT_SYMBOL_GPL(br_fdb_delete_by_port);
/* No locking or refcounting, assumes caller has rcu_read_lock */
-struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
+struct net_bridge_fdb_entry * __br_fdb_get(struct net_bridge *br,
const unsigned char *addr,
__u16 vid)
{
@@ -382,8 +477,11 @@
&br->hash[br_mac_hash(addr, vid)], hlist) {
if (ether_addr_equal(fdb->addr.addr, addr) &&
fdb->vlan_id == vid) {
- if (unlikely(has_expired(br, fdb)))
- break;
+ if (unlikely(has_expired(br, fdb))) {
+ br_get_timestamp_update_fwt(fdb);
+ if (time_before_eq(fdb->updated + hold_time(br), jiffies))
+ break;
+ }
return fdb;
}
}
@@ -415,6 +513,38 @@
}
#endif /* CONFIG_ATM_LANE */
+/* Interface used by ATM hook that keeps a ref count */
+struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
+ unsigned char *addr)
+{
+ struct net_bridge_fdb_entry *fdb = NULL;
+
+ rcu_read_lock();
+ fdb = __br_fdb_get(br, addr, 0);
+ rcu_read_unlock();
+ return fdb;
+}
+
+struct net_bridge_fdb_entry *br_fdb_get_ext(struct net_bridge *br,
+ struct sk_buff *skb,
+ unsigned char *addr)
+{
+ if (iputil_mac_is_v4_multicast(addr)
+#if defined(CONFIG_IPV6)
+ || iputil_mac_is_v6_multicast(addr)
+#endif
+ ) {
+ return (struct net_bridge_fdb_entry *)br_mdb_get(br, skb, 0);
+ }
+
+ return br_fdb_get(br, addr);
+}
+
+/* Set entry up for deletion with RCU */
+void br_fdb_put(struct net_bridge_fdb_entry *ent)
+{
+}
+
/*
* Fill buffer with forwarding table records in
* the API format.
@@ -425,6 +555,9 @@
struct __fdb_entry *fe = buf;
int i, num = 0;
struct net_bridge_fdb_entry *f;
+ struct net_bridge_mdb_entry *mp;
+ struct net_bridge_port_group *port_group;
+ char mac_addr[ETH_ALEN];
memset(buf, 0, maxnum*sizeof(struct __fdb_entry));
@@ -433,7 +566,7 @@
hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
if (num >= maxnum)
goto out;
-
+ br_get_timestamp_update_fwt(f);
if (has_expired(br, f))
continue;
@@ -452,6 +585,11 @@
/* due to ABI compat need to split into hi/lo */
fe->port_no = f->dst->port_no;
fe->port_hi = f->dst->port_no >> 8;
+#ifdef QTN_BR_SHOW_EXTRA
+ fe->sub_port = BR_SUBPORT_UNMAP(f->sub_port);
+ fe->vlan_id = f->vlan_id;
+#endif
+ fe->is_wlan = br_is_wlan_dev(f->dst->dev);
fe->is_local = f->is_local;
if (!f->is_static)
@@ -461,49 +599,119 @@
}
}
- out:
+ /* Print our mcast entries also */
+ if (br->mdb == 0)
+ goto out;
+
+ for (i = 0; i < BR_HASH_SIZE; i++) {
+ hlist_for_each_entry_rcu(mp, &br->mdb->mhash[i], hlist[br->mdb->ver]) {
+
+ if (mp->addr.proto == htons(ETH_P_IP)) {
+ ip_eth_mc_map(mp->addr.u.ip4, mac_addr);
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (mp->addr.proto == htons(ETH_P_IPV6)) {
+ ipv6_eth_mc_map(&mp->addr.u.ip6, mac_addr);
+#endif
+ } else {
+ printk("Unknown protocol\n");
+ continue;
+ }
+
+ for (port_group = mp->ports; port_group; port_group = port_group->next) {
+ if (num >= maxnum)
+ goto out;
+
+ if (skip) {
+ --skip;
+ continue;
+ }
+
+ memcpy(fe->mac_addr, mac_addr, ETH_ALEN);
+ fe->port_no = (port_group->port->port_no & 0xF) | ((port_group->sub_port & 0xF) << 4);
+ fe->is_local = 0;
+ fe->ageing_timer_value = port_group->timer.expires - jiffies;
+ ++fe;
+ ++num;
+ }
+ }
+ }
+
+out:
rcu_read_unlock();
return num;
}
static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
- const unsigned char *addr,
- __u16 vid)
+ const unsigned char *addr, u16 vid)
{
struct net_bridge_fdb_entry *fdb;
hlist_for_each_entry(fdb, head, hlist) {
if (ether_addr_equal(fdb->addr.addr, addr) &&
- fdb->vlan_id == vid)
+ fdb->vlan_id == vid)
return fdb;
}
return NULL;
}
static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head,
- const unsigned char *addr,
- __u16 vid)
+ const unsigned char *addr, u16 vid)
{
struct net_bridge_fdb_entry *fdb;
hlist_for_each_entry_rcu(fdb, head, hlist) {
if (ether_addr_equal(fdb->addr.addr, addr) &&
- fdb->vlan_id == vid)
+ fdb->vlan_id == vid)
return fdb;
}
return NULL;
}
-static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
- struct net_bridge_port *source,
- const unsigned char *addr,
- __u16 vid,
- unsigned char is_local,
- unsigned char is_static)
+/*
+ * Added by Quantenna
+ * Return the address of the attached device.
+ */
+unsigned char br_fdb_get_attached(struct net_bridge *br, unsigned char *addr)
+{
+ u_char rc = 0;
+
+ spin_lock_bh(&br->hash_lock);
+
+ if (br->br_fdb_attached) {
+ memcpy(addr, br->br_fdb_attached->addr.addr, ETH_ALEN);
+ rc = 1;
+ }
+
+ spin_unlock_bh(&br->hash_lock);
+
+ return rc;
+}
+
+static inline int fdb_is_invalid_source(struct net_bridge_port *source, port_id sub_port)
+{
+ /*
+ * Don't create/update the FDB if the source is a wlan device and
+ * the node does not exist.
+ */
+ return (br_is_wlan_dev(source->dev) &&
+ br_fdb_check_active_sub_port_hook &&
+ !br_fdb_check_active_sub_port_hook(source, sub_port));
+}
+
+static struct net_bridge_fdb_entry *fdb_create(struct net_bridge *br,
+ struct hlist_head *head,
+ struct net_bridge_port *source,
+ const unsigned char *addr,
+ __u16 vid, port_id sub_port,
+ unsigned char is_local,
+ unsigned char is_static)
{
struct net_bridge_fdb_entry *fdb;
+ if (!is_local && fdb_is_invalid_source(source, sub_port))
+ return NULL;
+
fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
if (fdb) {
memcpy(fdb->addr.addr, addr, ETH_ALEN);
@@ -514,7 +722,30 @@
fdb->added_by_user = 0;
fdb->added_by_external_learn = 0;
fdb->updated = fdb->used = jiffies;
+ fdb->sub_port = sub_port;
hlist_add_head_rcu(&fdb->hlist, head);
+ /*
+ * Added by Quantenna
+ * The most recently discovered address that was not heard from a
+ * wireless interface is treated as the 'attached' device for
+ * non-bridge mode.
+ */
+ if ((!fdb->is_local) &&
+ (strncmp(source->dev->name, "wifi", 4) != 0)) {
+
+ if (br->br_fdb_attached != fdb) {
+#if 0
+ printk(KERN_WARNING
+ "Using source %s addr %02x:%02x:%02x:%02x:%02x:%02x as the attached device\n",
+ source->dev->name,
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+#endif
+ br->br_fdb_attached = fdb;
+ }
+ }
+ if ((!fdb->is_local) && g_add_fwt_entry_hook)
+/* g_add_fwt_entry_hook(addr, vid, source->dev->if_port, sub_port, NULL);*/
+ g_add_fwt_entry_hook(addr, source->dev->if_port, sub_port, NULL);
}
return fdb;
}
@@ -541,7 +772,7 @@
fdb_delete(br, fdb);
}
- fdb = fdb_create(head, source, addr, vid, 1, 1);
+ fdb = fdb_create(br, head, source, addr, vid, 0, 1, 1);
if (!fdb)
return -ENOMEM;
@@ -562,8 +793,30 @@
return ret;
}
+/* TDLS-TODO This has been largely copied from br_fdb_update, refactor */
+void br_fdb_update_const(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *addr, u16 vid, bool added_by_user,
+ port_id sub_port)
+{
+ struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
+ struct net_bridge_fdb_entry *fdb;
+
+ spin_lock(&br->hash_lock);
+
+ fdb = fdb_find(head, addr, vid);
+ if (fdb) {
+ br_fdb_update(br, source, addr, vid, added_by_user, sub_port);
+ } else {
+ fdb = fdb_create(br, head, source, addr, vid, sub_port, 0, 0);
+ }
+
+ spin_unlock(&br->hash_lock);
+}
+
void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
- const unsigned char *addr, u16 vid, bool added_by_user)
+ const unsigned char *addr,
+ u16 vid, bool added_by_user,
+ port_id sub_port)
{
struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
struct net_bridge_fdb_entry *fdb;
@@ -578,6 +831,9 @@
source->state == BR_STATE_FORWARDING))
return;
+ if (fdb_is_invalid_source(source, sub_port))
+ return;
+
fdb = fdb_find_rcu(head, addr, vid);
if (likely(fdb)) {
/* attempt to update an entry for a local interface */
@@ -595,13 +851,14 @@
fdb->updated = jiffies;
if (unlikely(added_by_user))
fdb->added_by_user = 1;
+ fdb->sub_port = sub_port;
if (unlikely(fdb_modified))
fdb_notify(br, fdb, RTM_NEWNEIGH);
}
} else {
spin_lock(&br->hash_lock);
if (likely(!fdb_find(head, addr, vid))) {
- fdb = fdb_create(head, source, addr, vid, 0, 0);
+ fdb = fdb_create(br, head, source, addr, vid, 0, 0, 0);
if (fdb) {
if (unlikely(added_by_user))
fdb->added_by_user = 1;
@@ -613,6 +870,13 @@
*/
spin_unlock(&br->hash_lock);
}
+
+ if (fdb && (!fdb->is_local)) {
+ if (g_add_fwt_entry_hook) {
+/* g_add_fwt_entry_hook(addr, vid, source->dev->if_port, sub_port, NULL);*/
+ g_add_fwt_entry_hook(addr, source->dev->if_port, sub_port, NULL);
+ }
+ }
}
static int fdb_to_nud(const struct net_bridge *br,
@@ -765,7 +1029,7 @@
/* Update (create or replace) forwarding database entry */
static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
- __u16 state, __u16 flags, __u16 vid)
+ __u16 state, __u16 flags, __u16 vid, port_id sub_port)
{
struct net_bridge *br = source->br;
struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
@@ -783,7 +1047,7 @@
if (!(flags & NLM_F_CREATE))
return -ENOENT;
- fdb = fdb_create(head, source, addr, vid, 0, 0);
+ fdb = fdb_create(br, head, source, addr, vid, sub_port, 0, !!(state & NUD_PERMANENT));
if (!fdb)
return -ENOMEM;
@@ -822,6 +1086,7 @@
modified = true;
}
fdb->added_by_user = 1;
+ fdb->is_static = 1;
fdb->used = jiffies;
if (modified) {
@@ -832,6 +1097,18 @@
return 0;
}
+/* Added by Quantenna */
+void br_register_hooks_cbk_t(br_add_entry_cbk add_func, br_delete_entry_cbk delete_func,
+ br_fwt_ageing_time_cbk ageing_func, br_fwt_get_ent_cnt entries_num)
+{
+ g_add_fwt_entry_hook = add_func;
+ g_delete_fwt_entry_hook = delete_func;
+ g_fwt_ageing_jiffies_hook = ageing_func;
+ g_fwt_get_ent_cnt_hook = entries_num;
+}
+EXPORT_SYMBOL(br_register_hooks_cbk_t);
+
+
static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p,
const unsigned char *addr, u16 nlh_flags, u16 vid)
{
@@ -840,13 +1117,13 @@
if (ndm->ndm_flags & NTF_USE) {
local_bh_disable();
rcu_read_lock();
- br_fdb_update(p->br, p, addr, vid, true);
+ br_fdb_update(p->br, p, addr, vid, true, 0);
rcu_read_unlock();
local_bh_enable();
} else {
spin_lock_bh(&p->br->hash_lock);
err = fdb_add_entry(p, addr, ndm->ndm_state,
- nlh_flags, vid);
++ nlh_flags, vid, 0);
spin_unlock_bh(&p->br->hash_lock);
}
@@ -928,8 +1205,7 @@
return err;
}
-static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr,
- u16 vid)
+static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vid)
{
struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
struct net_bridge_fdb_entry *fdb;
@@ -1108,7 +1384,7 @@
head = &br->hash[br_mac_hash(addr, vid)];
fdb = fdb_find(head, addr, vid);
if (!fdb) {
- fdb = fdb_create(head, p, addr, vid, 0, 0);
+ fdb = fdb_create(br, head, p, addr, vid, 0, 0, 0);
if (!fdb) {
err = -ENOMEM;
goto err_unlock;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index f47759f..1e42b05 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -21,11 +21,63 @@
#include <linux/netfilter_bridge.h>
#include "br_private.h"
+static int br_ap_isolate_enabled = 0;
+static br_get_node_port_cbk br_forward_get_node_port_hook = NULL;
+
static int deliver_clone(const struct net_bridge_port *prev,
struct sk_buff *skb,
void (*__packet_hook)(const struct net_bridge_port *p,
struct sk_buff *skb));
+void br_set_ap_isolate(int enable) {
+
+ br_ap_isolate_enabled = !!enable;
+}
+EXPORT_SYMBOL(br_set_ap_isolate);
+
+int br_get_ap_isolate(void) {
+ return br_ap_isolate_enabled;
+}
+EXPORT_SYMBOL(br_get_ap_isolate);
+
+static int is_wireless_interface(const struct net_device *dev)
+{
+ const char *ifname = "wifi";
+ const char *wdsname = "wds";
+ if (!dev)
+ return 0;
+
+ return ((strncmp(dev->name, ifname, strlen(ifname)) == 0) ||
+ (strncmp(dev->name, wdsname, strlen(wdsname)) == 0));
+}
+
+static inline int br_ap_isolate_should_forward(const struct net_bridge_port *p,
+ const struct sk_buff *skb) {
+ if (br_ap_isolate_enabled &&
+ is_wireless_interface(p->dev) &&
+ is_wireless_interface(skb->dev)) {
+ return 0;
+ }
+
+ if (skb->dev == p->dev)
+ return !QTN_FLAG_IS_INTRA_BSS(skb->dev->qtn_flags);
+
+ if ((QTN_FLAG_IS_BSS_ISOLATE(skb->dev->qtn_flags) &&
+ (p->dev->qtn_flags & QTN_FLAG_WIFI_DEVICE)) ||
+ ((skb->dev->qtn_flags & QTN_FLAG_WIFI_DEVICE)
+ && QTN_FLAG_IS_BSS_ISOLATE(p->dev->qtn_flags)))
+ return 0;
+
+ return 1;
+}
+
+static inline int br_src_port_filter_check(const struct net_bridge_port *p,
+ const struct sk_buff *skb)
+{
+ return (p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev ||
+ (skb->dest_port && skb->src_port && skb->src_port != skb->dest_port);
+}
+
/* Don't forward packets to originating port or forwarding disabled */
static inline int should_deliver(const struct net_bridge_port *p,
const struct sk_buff *skb)
@@ -33,8 +85,11 @@
struct net_bridge_vlan_group *vg;
vg = nbp_vlan_group_rcu(p);
- return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
- br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING;
+
+ return br_src_port_filter_check(p, skb) &&
+ br_allowed_egress(vg, skb) &&
+ p->state == BR_STATE_FORWARDING &&
+ br_ap_isolate_should_forward(p, skb);
}
int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
@@ -203,6 +258,7 @@
prev = NULL;
+ skb->dest_port = 0;
list_for_each_entry_rcu(p, &br->port_list, list) {
/* Do not flood unicast traffic to ports that turn it off */
if (unicast && !(p->flags & BR_FLOOD))
@@ -234,7 +290,6 @@
kfree_skb(skb);
}
-
/* called with rcu_read_lock */
void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast)
{
@@ -249,6 +304,55 @@
}
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+static void br_multicast_bitmap_flood(struct net_bridge_port *port,
+ uint32_t *port_bitmap, struct sk_buff *skb, void (*__packet_hook)(
+ const struct net_bridge_port *p, struct sk_buff *skb))
+{
+ int idx;
+ int bit_idx;
+ uint32_t sub_port_bitmap;
+ uint8_t multiple_ports = (port == NULL);
+
+ for (idx = 0; idx < BR_SUB_PORT_BITMAP_SIZE; idx++) {
+ bit_idx = 0;
+ sub_port_bitmap = port_bitmap[idx];
+ while (sub_port_bitmap) {
+ if (sub_port_bitmap & 0x1) {
+ skb->dest_port = BR_SUBPORT_MAP(BR_SUBPORT(idx, bit_idx));
+ if (multiple_ports) {
+ if (br_forward_get_node_port_hook)
+ port = br_forward_get_node_port_hook(skb->dest_port);
+ else
+ port = NULL;
+ }
+ if (port)
+ maybe_deliver(port, port, skb, __packet_hook);
+ }
+ sub_port_bitmap >>= 1;
+ bit_idx++;
+ }
+ }
+}
+
+static inline int br_get_sub_port(const struct net_bridge_port *port,
+ uint32_t *sub_port_bitmap, int size)
+{
+ int is_active;
+
+ if (unlikely(!port || !port->dev))
+ return 0;
+
+ if (!br_is_wlan_dev(port->dev))
+ return 0;
+
+ if (!br_fdb_get_active_sub_port_hook)
+ return 0;
+
+ is_active = br_fdb_get_active_sub_port_hook(port, sub_port_bitmap, size);
+
+ return is_active;
+}
+
/* called with rcu_read_lock */
static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
struct sk_buff *skb, struct sk_buff *skb0,
@@ -274,7 +378,22 @@
port = (unsigned long)lport > (unsigned long)rport ?
lport : rport;
- prev = maybe_deliver(prev, port, skb, __packet_hook);
+ if (port == lport) {
+ if (p)
+ skb->dest_port = p->sub_port;
+ else
+ skb->dest_port = 0;
+ prev = maybe_deliver(prev, port, skb, __packet_hook);
+ } else if (BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
+ if (port && br_is_wlan_dev(port->dev)) {
+ br_multicast_bitmap_flood(port, port->router_port_bitmap,
+ skb, __packet_hook);
+ } else {
+ skb->dest_port = 0;
+ prev = maybe_deliver(prev, port, skb, __packet_hook);
+ }
+ }
+
if (IS_ERR(prev))
goto out;
@@ -311,4 +430,110 @@
{
br_multicast_flood(mdst, skb, skb2, __br_forward);
}
+
+static int br_should_exclude_mcast_member(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mp)
+{
+ if (!mp)
+ return 0;
+
+ if (br->report_flood_interval == BR_ALWAYS_FLOOD_REPORT)
+ return 0;
+
+ if (time_after(jiffies, mp->report_target_jiffies))
+ return 0;
+
+ if (mp->report_flood_indicator >= br->report_flood_interval &&
+ !mp->rx_specific_query)
+ return 0;
+
+ return 1;
+}
+
+static int br_exclude_mcast_member(struct net_bridge_mdb_entry *mp,
+ struct net_bridge_port *port, uint32_t* sub_port_bitmap)
+{
+ struct net_bridge_port_group *p;
+ struct net_bridge *br = port->br;
+ int is_wlan_dev;
+ int ret = 0;
+
+ is_wlan_dev = br_is_wlan_dev(port->dev);
+ spin_lock(&br->multicast_lock);
+ for (p = mp->ports; p; p = p->next) {
+ if (p->port == port) {
+ if (!is_wlan_dev) {
+ ret = 1;
+ break;
+ }
+ br_reset_sub_port_bitmap(sub_port_bitmap, p->sub_port);
+ }
+ }
+ spin_unlock(&br->multicast_lock);
+
+ return ret;
+}
+
+void br_report_flood(struct net_bridge *br, struct net_bridge_mdb_entry *mp,
+ struct sk_buff *skb)
+{
+ struct net_bridge_port *port;
+ uint32_t sub_port_bitmap[BR_SUB_PORT_BITMAP_SIZE];
+ int is_wlan_dev;
+ int idx;
+ uint8_t got_sub_port_bitmap = 0;
+
+ list_for_each_entry_rcu(port, &br->port_list, list) {
+ is_wlan_dev = br_is_wlan_dev(port->dev);
+ if (!hlist_unhashed(&port->rlist) && !is_wlan_dev)
+ continue;
+
+ if (is_wlan_dev) {
+ if (!got_sub_port_bitmap) {
+ if (!br_get_sub_port(port, sub_port_bitmap, sizeof(sub_port_bitmap)))
+ continue;
+ got_sub_port_bitmap = 1;
+ }
+ }
+
+ if (br_should_exclude_mcast_member(br, mp)) {
+ if (br_exclude_mcast_member(mp, port, sub_port_bitmap))
+ continue;
+ }
+
+ if (is_wlan_dev) {
+ if (!hlist_unhashed(&port->rlist)) {
+ /* Skip sub-ports handled by br_multicast_forward */
+ for (idx = 0; idx < ARRAY_SIZE(sub_port_bitmap); idx++) {
+ sub_port_bitmap[idx] |= port->router_port_bitmap[idx];
+ sub_port_bitmap[idx] ^= port->router_port_bitmap[idx];
+ }
+ }
+ } else {
+ skb->dest_port = 0;
+ maybe_deliver(port, port, skb, __br_forward);
+ }
+ }
+
+ if (got_sub_port_bitmap)
+ br_multicast_bitmap_flood(NULL, sub_port_bitmap, skb, __br_forward);
+}
+
+void br_multicast_copy_to_sub_ports(struct net_bridge *br, struct net_bridge_mdb_entry *mdst,
+ struct sk_buff *skb)
+{
+ struct net_bridge_port_group *pg;
+
+ for (pg = mdst->ports; pg != NULL; pg = pg->next) {
+ skb->dest_port = pg->sub_port;
+ maybe_deliver(pg->port, pg->port, skb, __br_forward);
+ }
+}
+
+void br_register_node_hooks_cbk_t(br_get_node_port_cbk get_node_port_func)
+{
+ br_forward_get_node_port_hook = get_node_port_func;
+}
+EXPORT_SYMBOL(br_register_node_hooks_cbk_t);
+
#endif
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 8217aec..64cd776 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -80,7 +80,12 @@
if (p->state == BR_STATE_DISABLED)
br_stp_enable_port(p);
} else {
- if (p->state != BR_STATE_DISABLED)
+ /*
+ * Do not disable port if dev in operstate dormant
+ * to let 802.1X packet go through
+ */
+ if (p->state != BR_STATE_DISABLED
+ && !netif_dormant(dev))
br_stp_disable_port(p);
}
spin_unlock_bh(&br->lock);
@@ -371,9 +376,10 @@
return p;
}
-int br_add_bridge(struct net *net, const char *name)
+int br_add_bridge(struct net *net, const char *name, const uint16_t vlan_id)
{
struct net_device *dev;
+ struct net_bridge *br;
int res;
dev = alloc_netdev(sizeof(struct net_bridge), name, NET_NAME_UNKNOWN,
@@ -382,9 +388,11 @@
if (!dev)
return -ENOMEM;
+ br = netdev_priv(dev);
+ br->vlan_id = vlan_id;
+
dev_net_set(dev, net);
dev->rtnl_link_ops = &br_link_ops;
-
res = register_netdev(dev);
if (res)
free_netdev(dev);
@@ -516,6 +524,7 @@
err = dev_set_allmulti(dev, 1);
if (err)
goto put_back;
+ dev->gflags ^= IFF_PROMISC;
err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
SYSFS_BRIDGE_PORT_ATTR);
@@ -555,7 +564,7 @@
else
netdev_set_rx_headroom(dev, br_hr);
- if (br_fdb_insert(br, p, dev->dev_addr, 0))
+ if (br_fdb_insert(br, p, dev->dev_addr, br->vlan_id))
netdev_err(dev, "failed insert local address bridge forwarding table\n");
err = nbp_vlan_init(p);
@@ -601,6 +610,7 @@
kobject_put(&p->kobj);
p = NULL; /* kobject_put frees */
err1:
+ dev->gflags ^= IFF_PROMISC;
dev_set_allmulti(dev, -1);
put_back:
dev_put(dev);
@@ -646,3 +656,10 @@
if (mask & BR_AUTO_MASK)
nbp_update_port_count(br);
}
+
+struct net_bridge_port *get_br_port(const struct net_device *dev)
+{
+ return dev->rx_handler_data;
+}
+EXPORT_SYMBOL(get_br_port);
+
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 43d2cd8..693f304 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -20,12 +20,46 @@
#include <net/arp.h>
#include <linux/export.h>
#include <linux/rculist.h>
+#include <linux/igmp.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/if_ether.h>
+#include <qtn/iputil.h>
#include "br_private.h"
+#ifndef ETH_P_80211_RAW
+# define ETH_P_80211_RAW 0x0019
+#endif
+
+static int br_vlan_promisc = 0;
+
+void br_vlan_set_promisc(int enable)
+{
+ printk("%s vlan promiscuous mode\n", enable ? "Enabling" : "Disabling");
+ br_vlan_promisc = enable;
+}
+EXPORT_SYMBOL(br_vlan_set_promisc);
+
/* Hook for brouter */
br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
EXPORT_SYMBOL(br_should_route_hook);
+#ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR
+static struct sk_buff *skb_aligned(struct sk_buff *skb)
+{
+ if ((unsigned int)skb->data & 0x3) {
+ int clen = 4 - ((unsigned int)skb->data & 0x3);
+ int err;
+
+ err = pskb_expand_head(skb, clen, 0, GFP_ATOMIC);
+ if (err)
+ panic("%s: skb alignment failure\n", __func__);
+ }
+
+ return skb;
+}
+#endif
+
static int
br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
{
@@ -61,11 +95,134 @@
if (!skb)
return NET_RX_DROP;
+#ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR
+ skb = skb_aligned(skb);
+#endif
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
dev_net(indev), NULL, skb, indev, NULL,
br_netif_receive_skb);
}
+static int br_handle_to_protoclstack(const unsigned char *dest, void *data)
+{
+ int retval;
+
+ retval = !iputil_mac_is_v4_multicast(dest) ||
+ iputil_is_v4_ssdp(dest, data) ||
+ iputil_is_lncb(dest, data);
+
+#ifdef CONFIG_IPV6
+ if (retval)
+ retval = (!iputil_mac_is_v6_multicast(dest) ||
+ iputil_mac_is_v6_local((struct ipv6hdr *)data));
+#endif
+
+ return retval;
+}
+
+static int br_handle_mcast_mgmt_frame(struct sk_buff *skb, struct net_bridge *br)
+{
+ uint8_t igmp_snoop;
+
+ igmp_snoop = (br->igmp_snoop_enabled == BR_IGMP_SNOOP_ENABLED ||
+ br->igmp_snoop_enabled == BR_IGMP_SNOOP_HYBRID);
+
+ return igmp_snoop && (!BR_INPUT_SKB_CB(skb)->igmp ||
+ BR_INPUT_SKB_CB_MROUTERS_ONLY(skb));
+}
+
+static int br_handle_mcast_exception(struct net_bridge *br,
+ const unsigned char *dest, void *data)
+{
+ struct iphdr *iph;
+ int retval;
+ int ssdp_check;
+#ifdef CONFIG_IPV6
+ struct ipv6hdr *ip6hdr;
+#endif
+
+ iph = data;
+ ssdp_check = (br->ssdp_flood_state == BR_SSDP_FLOOD_DISABLED);
+
+ retval = iputil_mac_is_v4_multicast(dest) &&
+ (!iputil_is_v4_ssdp(dest, iph) || ssdp_check);
+#ifdef CONFIG_IPV6
+ if (!retval) {
+ ip6hdr = data;
+ retval = iputil_mac_is_v6_multicast(dest) &&
+ (!iputil_is_v6_ssdp(dest, ip6hdr) || ssdp_check) &&
+ !iputil_mac_is_v6_local(ip6hdr);
+ }
+#endif
+
+ return retval;
+}
+
+int br_handle_frame_finish_multicast(struct sk_buff *skb, struct net_bridge *br,
+ const unsigned char *dest, u16 vid)
+{
+ struct net_bridge_mdb_entry *mdst;
+ struct sk_buff *skb2 = NULL;
+ struct ethhdr *eth = eth_hdr(skb);
+ void *data;
+
+ if (eth->h_proto != __constant_htons(ETH_P_8021Q))
+ data = (void *)(eth + 1);
+ else
+ data = (void *)((struct vlan_ethhdr *)eth + 1);
+
+ br->dev->stats.multicast++;
+ if (br_handle_to_protoclstack(dest, data))
+ skb2 = skb;
+
+ if (!iputil_is_lncb(dest, data) &&
+ br_handle_mcast_mgmt_frame(skb, br) &&
+ br_handle_mcast_exception(br, dest, data)) {
+ if (BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
+ mdst = br_mdb_get(br, skb, vid);
+ br_report_flood(br, mdst, skb);
+ br_multicast_forward(mdst, skb, skb2);
+ skb = NULL;
+ } else if(BR_INPUT_SKB_CB_UCAST_FWD(skb)) {
+ mdst = br_mdb_get_ext(br, skb, vid);
+ if (mdst) {
+ br_multicast_copy_to_sub_ports(br, mdst, skb);
+ if (skb2 == NULL)
+ kfree_skb(skb);
+ skb = NULL;
+ } else if (br->igmp_snoop_enabled == BR_IGMP_SNOOP_ENABLED) {
+ goto drop;
+ }
+ } else {
+ mdst = br_mdb_get(br, skb, vid);
+ if (mdst) {
+ br_multicast_forward(mdst, skb, skb2);
+ skb = NULL;
+ } else if (br->igmp_snoop_enabled == BR_IGMP_SNOOP_ENABLED) {
+ goto drop;
+ } else if (br->igmp_snoop_enabled == BR_IGMP_SNOOP_ENABLED) {
+ goto drop;
+ }
+ }
+ }
+
+ if (skb) {
+ bool unicast = true;
+ if (is_broadcast_ether_addr(dest))
+ unicast = false;
+ skb->dest_port = 0;
+ br_flood_forward(br, skb, skb2, unicast);
+ }
+ if (skb2)
+ return br_pass_frame_up(skb2);
+
+out:
+ return 0;
+drop:
+ kfree_skb(skb);
+ goto out;
+}
+
static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p)
{
@@ -132,7 +289,6 @@
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
struct net_bridge *br;
struct net_bridge_fdb_entry *dst;
- struct net_bridge_mdb_entry *mdst;
struct sk_buff *skb2;
bool unicast = true;
u16 vid = 0;
@@ -143,15 +299,36 @@
if (!br_allowed_ingress(p->br, nbp_vlan_group_rcu(p), skb, &vid))
goto out;
+ vid = skb->hw_vlan_id;
+
/* insert into forwarding database after filtering to avoid spoofing */
br = p->br;
+ /* ETH_P_80211_RAW */
+ /* This type of frame should be passed up the stack, not forwarded or flooded.
+ * Note that due to the nature of the skb with this protocol, the header is an
+ * 802.11 header, not an Ethernet header.
+ */
+ if (skb->protocol == __constant_htons(ETH_P_80211_RAW))
+ {
+ /* Pass it up, do not forward or add entries to the bridge table */
+ BR_INPUT_SKB_CB(skb)->brdev = br->dev;
+ br_pass_frame_up(skb);
+ goto out;
+ }
+
if (p->flags & BR_LEARNING)
- br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);
+ br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false, 0);
+ br_handle_fwt_capacity(br);
if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
br_multicast_rcv(br, p, skb, vid))
goto drop;
+#ifndef CONFIG_QTN_PLATFORM_MISALIGN_WAR
+ if (M_FLAG_ISSET(skb, M_HAS_MISALIGN))
+ dest = eth_hdr(skb)->h_dest;
+#endif
+
if (p->state == BR_STATE_LEARNING)
goto drop;
@@ -162,9 +339,17 @@
if (br->dev->flags & IFF_PROMISC)
skb2 = skb;
+ else if (unlikely(br_vlan_promisc && skb->protocol == __constant_htons(ETH_P_8021Q)))
+ skb2 = skb;
dst = NULL;
+#ifdef CONFIG_IPV6
+ if ((eth_hdr(skb)->h_proto == __constant_htons(ETH_P_IPV6)) &&
+ (skb->len < sizeof(struct ipv6hdr))) {
+ goto drop;
+ }
+#endif
if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP))
br_do_proxy_arp(skb, br, vid, p);
@@ -172,21 +357,7 @@
skb2 = skb;
unicast = false;
} else if (is_multicast_ether_addr(dest)) {
- mdst = br_mdb_get(br, skb, vid);
- if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
- br_multicast_querier_exists(br, eth_hdr(skb))) {
- if ((mdst && mdst->mglist) ||
- br_multicast_is_router(br))
- skb2 = skb;
- br_multicast_forward(mdst, skb, skb2);
- skb = NULL;
- if (!skb2)
- goto out;
- } else
- skb2 = skb;
-
- unicast = false;
- br->dev->stats.multicast++;
+ return br_handle_frame_finish_multicast(skb, br, dest, vid);
} else if ((dst = __br_fdb_get(br, dest, vid)) &&
dst->is_local) {
skb2 = skb;
@@ -197,9 +368,12 @@
if (skb) {
if (dst) {
dst->used = jiffies;
+ skb->dest_port = dst->sub_port;
br_forward(dst->dst, skb, skb2);
- } else
+ } else {
+ skb->dest_port = 0;
br_flood_forward(br, skb, skb2, unicast);
+ }
}
if (skb2)
@@ -220,7 +394,7 @@
/* check if vlan is allowed, to avoid spoofing */
if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid))
- br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
+ br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false, 0);
}
/* note: already called with rcu_read_lock */
@@ -249,15 +423,38 @@
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
return RX_HANDLER_PASS;
- if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
- goto drop;
+ /*
+ * EAP frames destined for a bridge port need no bridge
+ * handling.
+ */
+ if (unlikely(skb->protocol == __constant_htons(ETH_P_PAE)
+ && skb->pkt_type == PACKET_HOST))
+ return RX_HANDLER_PASS;
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
return RX_HANDLER_CONSUMED;
+ if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+ goto drop;
+
p = br_port_get_rcu(skb->dev);
+ /* For ETH_P_80211_RAW, any pointers to addresses are invalid, so
+ * simply pass the packet onto the br_handle_frame_finish to pass
+ * it up the stack.
+ */
+
+ if (skb->protocol == __constant_htons(ETH_P_80211_RAW)) {
+ if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
+ NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, dev_net(skb->dev), NULL, skb, skb->dev,
+ NULL, br_handle_frame_finish);
+ } else {
+ goto drop;
+ }
+ return RX_HANDLER_CONSUMED;
+ }
+
if (unlikely(is_link_local_ether_addr(dest))) {
u16 fwd_mask = p->br->group_fwd_mask_required;
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index d99b200..6110075 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -207,6 +207,15 @@
return -EPERM;
ret = br_set_ageing_time(br, args[1]);
+ /* TODO: set FWT ageing dynamiccaly up to 9 hours and change the
+ * following limitation */
+ if ((args[1] / USER_HZ) > BR_AGE_MAX_SEC) {
+ printk("BRIDGE: invalid age (%lu) - max is %u seconds\n",
+ args[1], BR_AGE_MAX_SEC);
+ } else {
+ br->ageing_time = clock_t_to_jiffies(args[1]);
+ mod_timer(&br->gc_timer, jiffies);
+ }
break;
case BRCTL_GET_PORT_INFO:
@@ -289,6 +298,29 @@
case BRCTL_GET_FDB_ENTRIES:
return get_fdb_entries(br, (void __user *)args[1],
args[2], args[3]);
+
+
+ case BRCTL_SET_IGMP_SNOOP_STATE:
+ if (args[1] <= BR_IGMP_SNOOP_HYBRID) {
+ br->igmp_snoop_enabled = args[1];
+ } else {
+ return -EINVAL;
+ }
+ if (br->igmp_snoop_enabled == BR_IGMP_SNOOP_HYBRID) {
+ printk("Hybrid IGMP snooping\n");
+ } else {
+ printk("%sbling IGMP snooping\n", args[1] ? "Ena" : "Disa");
+ }
+ return 0;
+
+ case BRCTL_SET_SSDP_FLOOD_STATE:
+ if (args[1]) {
+ br->ssdp_flood_state = BR_SSDP_FLOOD_ENABLED;
+ } else {
+ br->ssdp_flood_state = BR_SSDP_FLOOD_DISABLED;
+ }
+ printk("%sbling SSDP flooding\n", args[1] ? "Ena" : "Disa");
+ return 0;
}
if (!ret) {
@@ -346,7 +378,7 @@
buf[IFNAMSIZ-1] = 0;
if (args[0] == BRCTL_ADD_BRIDGE)
- return br_add_bridge(net, buf);
+ return br_add_bridge(net, buf, (uint16_t)args[2]);
return br_del_bridge(net, buf);
}
@@ -355,18 +387,35 @@
return -EOPNOTSUPP;
}
+/* The macro must be in sync with bridge-utils */
+#define BR_IOCTL_CMD_MAX (32)
int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
{
+ char buf[BR_IOCTL_CMD_MAX];
+ unsigned int vlan_id;
+
switch (cmd) {
case SIOCGIFBR:
case SIOCSIFBR:
return old_deviceless(net, uarg);
case SIOCBRADDBR:
+ {
+ if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(buf, uarg, sizeof(buf)))
+ return -EFAULT;
+
+ sscanf(buf + IFNAMSIZ, "%u", &vlan_id);
+ if (vlan_id >= VLAN_VID_MASK)
+ vlan_id = 0;
+
+ buf[IFNAMSIZ - 1] = 0;
+ return br_add_bridge(net, buf, (uint16_t)vlan_id);
+ }
case SIOCBRDELBR:
{
- char buf[IFNAMSIZ];
-
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
@@ -374,8 +423,6 @@
return -EFAULT;
buf[IFNAMSIZ-1] = 0;
- if (cmd == SIOCBRADDBR)
- return br_add_bridge(net, buf);
return br_del_bridge(net, buf);
}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 4384414..1ef798a 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -35,20 +35,33 @@
#include "br_private.h"
+/**
+ * Added by Quantenna
+ * Set cbks for handling multicast scenarios.
+ */
+static br_join_multicast_cbk g_fwt_mult_join_hook = NULL;
+static br_leave_multicast_cbk g_fwt_mult_leave_hook = NULL;
+
+static void br_ip4_multicast_leave_group(struct net_bridge *br,
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ __be32 group,
+ __u16 vid);
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_leave_group(struct net_bridge *br,
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ const struct in6_addr *group,
+ __u16 vid);
+#endif
+
static void br_multicast_start_querier(struct net_bridge *br,
struct bridge_mcast_own_query *query);
static void br_multicast_add_router(struct net_bridge *br,
struct net_bridge_port *port);
-static void br_ip4_multicast_leave_group(struct net_bridge *br,
- struct net_bridge_port *port,
- __be32 group,
- __u16 vid);
-#if IS_ENABLED(CONFIG_IPV6)
-static void br_ip6_multicast_leave_group(struct net_bridge *br,
- struct net_bridge_port *port,
- const struct in6_addr *group,
- __u16 vid);
-#endif
unsigned int br_mdb_rehash_seq;
static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -147,22 +160,20 @@
}
#endif
-struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
+struct net_bridge_mdb_entry *br_mdb_get_ext(struct net_bridge *br,
struct sk_buff *skb, u16 vid)
{
struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);
struct br_ip ip;
- if (br->multicast_disabled)
- return NULL;
-
- if (BR_INPUT_SKB_CB(skb)->igmp)
- return NULL;
-
- ip.proto = skb->protocol;
+ if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+ ip.proto = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+ } else {
+ ip.proto = skb->protocol;
+ }
ip.vid = vid;
- switch (skb->protocol) {
+ switch (ip.proto) {
case htons(ETH_P_IP):
ip.u.ip4 = ip_hdr(skb)->daddr;
break;
@@ -178,6 +189,18 @@
return br_mdb_ip_get(mdb, &ip);
}
+struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
+ struct sk_buff *skb, u16 vid)
+{
+ if (br->multicast_disabled)
+ return NULL;
+
+ if (BR_INPUT_SKB_CB(skb)->igmp)
+ return NULL;
+
+ return br_mdb_get_ext(br, skb, vid);
+}
+
static void br_mdb_free(struct rcu_head *head)
{
struct net_bridge_mdb_htable *mdb =
@@ -223,6 +246,15 @@
struct net_bridge_port_group *p =
container_of(head, struct net_bridge_port_group, rcu);
+ struct net_bridge_subport_req *sr;
+ struct net_bridge_subport_req *sr_tmp;
+
+ for (sr = p->subport_reqs.head; sr; sr = sr_tmp) {
+ sr_tmp = sr->next;
+ --p->subport_reqs.count;
+ kfree(sr);
+ }
+ WARN_ON(p->subport_reqs.count != 0);
kfree(p);
}
@@ -249,6 +281,11 @@
if (mp->ports)
goto out;
+ if (br->igmp_snoop_enabled == BR_IGMP_SNOOP_HYBRID) {
+ mod_timer(&mp->timer, jiffies + br->multicast_last_member_interval);
+ goto out;
+ }
+
mdb = mlock_dereference(br->mdb, br);
hlist_del_rcu(&mp->hlist[mdb->ver]);
@@ -260,6 +297,30 @@
spin_unlock(&br->multicast_lock);
}
+static void br_multicast_remove_pg(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mp,
+ struct net_bridge_port_group *p,
+ struct net_bridge_port_group **pp)
+{
+ rcu_assign_pointer(*pp, p->next);
+
+ hlist_del_init(&p->mglist);
+ del_timer(&p->timer);
+
+ br_mdb_notify(br->dev, p->port, &p->addr, RTM_DELMDB,
+ p->flags);
+ if (g_fwt_mult_leave_hook) {
+ /* FIXME-PEARL_VLAN add vlan id */
+ g_fwt_mult_leave_hook(p->sub_port, p->port->dev->if_port, &p->addr);
+ }
+
+ call_rcu_bh(&p->rcu, br_multicast_free_pg);
+
+ if (!mp->ports && hlist_unhashed(&p->mglist) &&
+ netif_running(br->dev))
+ mod_timer(&mp->timer, jiffies);
+}
+
static void br_multicast_del_pg(struct net_bridge *br,
struct net_bridge_port_group *pg)
{
@@ -277,20 +338,10 @@
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p != pg)
+ if (p != pg || p->sub_port != pg->sub_port)
continue;
- rcu_assign_pointer(*pp, p->next);
- hlist_del_init(&p->mglist);
- del_timer(&p->timer);
- br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB,
- p->flags);
- call_rcu_bh(&p->rcu, br_multicast_free_pg);
-
- if (!mp->ports && !mp->mglist &&
- netif_running(br->dev))
- mod_timer(&mp->timer, jiffies);
-
+ br_multicast_remove_pg(br, mp, p, pp);
return;
}
@@ -670,8 +721,63 @@
return p;
}
+static void br_multicast_add_group_subport_req(struct net_bridge_port_group *p,
+ const uint8_t *src_mac)
+{
+ struct net_bridge_subport_req *sr;
+ struct net_bridge_subport_req *first;
+ struct net_bridge_subport_req **srp;
+
+ for (srp = &p->subport_reqs.head; (sr = *srp); srp = &sr->next) {
+ if (memcmp(sr->src_mac, src_mac, sizeof(sr->src_mac)) == 0) {
+ /* entry exists, don't duplicate */
+ return;
+ }
+ }
+
+ sr = kmalloc(sizeof(*sr), GFP_ATOMIC);
+ if (sr) {
+ if (p->subport_reqs.count < BR_MCAST_SUBPORT_REQ_LIMIT) {
+ ++p->subport_reqs.count;
+ } else {
+ /* remove oldest entry when full */
+ first = p->subport_reqs.head;
+ BUG_ON(!first || !first->next);
+ p->subport_reqs.head = first->next;
+ kfree(first);
+ }
+
+ memcpy(sr->src_mac, src_mac, sizeof(sr->src_mac));
+ sr->next = NULL;
+ *srp = sr;
+ }
+}
+
+static void br_multicast_leave_subport_mac(struct net_bridge_port_group *p,
+ const uint8_t *src_mac)
+{
+ struct net_bridge_subport_req *sr;
+ struct net_bridge_subport_req **srp;
+
+ for (srp = &p->subport_reqs.head; (sr = *srp); srp = &sr->next) {
+ if (memcmp(sr->src_mac, src_mac, sizeof(sr->src_mac)) == 0) {
+ *srp = sr->next;
+ kfree(sr);
+ --p->subport_reqs.count;
+ break;
+ }
+ }
+}
+
+static int br_multicast_subport_empty(const struct net_bridge_port_group *p)
+{
+ return p->subport_reqs.head == NULL;
+}
+
static int br_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
struct br_ip *group)
{
struct net_bridge_mdb_entry *mp;
@@ -685,6 +791,11 @@
(port && port->state == BR_STATE_DISABLED))
goto out;
+ if (port && br_is_wlan_dev(port->dev) &&
+ br_fdb_check_active_sub_port_hook &&
+ !br_fdb_check_active_sub_port_hook(port, sub_port))
+ goto out;
+
mp = br_multicast_new_group(br, port, group);
err = PTR_ERR(mp);
if (IS_ERR(mp))
@@ -696,10 +807,15 @@
goto out;
}
+ /* hook up an update for the FWT entries */
+ if (g_fwt_mult_join_hook) {
+ g_fwt_mult_join_hook(sub_port, port->dev->if_port, group);
+ }
+
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port == port)
+ if (p->port == port && p->sub_port == sub_port)
goto found;
if ((unsigned long)p->port < (unsigned long)port)
break;
@@ -708,11 +824,17 @@
p = br_multicast_new_port_group(port, group, *pp, 0);
if (unlikely(!p))
goto err;
+ p->sub_port = sub_port;
+ p->subport_reqs.head = NULL;
+ p->subport_reqs.count = 0;
+
rcu_assign_pointer(*pp, p);
br_mdb_notify(br->dev, port, group, RTM_NEWMDB, 0);
found:
+ br_multicast_add_group_subport_req(p, src_mac);
mod_timer(&p->timer, now + br->multicast_membership_interval);
+ mod_timer(&mp->timer, now + br->multicast_membership_interval);
out:
err = 0;
@@ -722,9 +844,11 @@
}
static int br_ip4_multicast_add_group(struct net_bridge *br,
- struct net_bridge_port *port,
- __be32 group,
- __u16 vid)
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ __be32 group,
+ __u16 vid)
{
struct br_ip br_group;
@@ -735,14 +859,16 @@
br_group.proto = htons(ETH_P_IP);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, src_mac, sub_port, &br_group);
}
#if IS_ENABLED(CONFIG_IPV6)
static int br_ip6_multicast_add_group(struct net_bridge *br,
- struct net_bridge_port *port,
- const struct in6_addr *group,
- __u16 vid)
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ const struct in6_addr *group,
+ __u16 vid)
{
struct br_ip br_group;
@@ -753,7 +879,7 @@
br_group.proto = htons(ETH_P_IPV6);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, src_mac, sub_port, &br_group);
}
#endif
@@ -769,6 +895,7 @@
hlist_unhashed(&port->rlist))
goto out;
+ memset(port->router_port_bitmap, 0, sizeof(port->router_port_bitmap));
hlist_del_init_rcu(&port->rlist);
br_rtr_notify(br->dev, port, RTM_DELMDB);
/* Don't allow timer refresh if the router expired */
@@ -888,6 +1015,8 @@
{
struct net_bridge *br = port->br;
+ if (br->multicast_router == 0 || port->multicast_router == 0)
+ return;
spin_lock(&br->multicast_lock);
if (port->state == BR_STATE_DISABLED ||
port->state == BR_STATE_BLOCKING)
@@ -1001,11 +1130,18 @@
spin_unlock(&br->multicast_lock);
}
+static const uint8_t *br_ether_srcmac(const struct sk_buff *skb)
+{
+ const struct ethhdr *eth = (const void *) skb_mac_header(skb);
+ return eth->h_source;
+}
+
static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
struct net_bridge_port *port,
struct sk_buff *skb,
u16 vid)
{
+ const uint8_t *src_mac = br_ether_srcmac(skb);
struct igmpv3_report *ih;
struct igmpv3_grec *grec;
int i;
@@ -1041,17 +1177,17 @@
case IGMPV3_ALLOW_NEW_SOURCES:
case IGMPV3_BLOCK_OLD_SOURCES:
break;
-
default:
continue;
}
if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
type == IGMPV3_MODE_IS_INCLUDE) &&
- ntohs(grec->grec_nsrcs) == 0) {
- br_ip4_multicast_leave_group(br, port, group, vid);
+ ntohs(grec->grec_nsrcs) == 0) {
+ br_ip4_multicast_leave_group(br, port, src_mac,
+ skb->src_port, group, vid);
} else {
- err = br_ip4_multicast_add_group(br, port, group, vid);
+ err = br_ip4_multicast_add_group(br, port, src_mac, skb->src_port, group, vid);
if (err)
break;
}
@@ -1066,6 +1202,7 @@
struct sk_buff *skb,
u16 vid)
{
+ const uint8_t *src_mac = br_ether_srcmac(skb);
struct icmp6hdr *icmp6h;
struct mld2_grec *grec;
int i;
@@ -1073,8 +1210,13 @@
int num;
int err = 0;
+/*
+ * For some reason, we has to disable the following source code to pass MLDv2 test.
+ */
+#if 0
if (!pskb_may_pull(skb, sizeof(*icmp6h)))
return -EINVAL;
+#endif
icmp6h = icmp6_hdr(skb);
num = ntohs(icmp6h->icmp6_dataun.un_data16[1]);
@@ -1099,27 +1241,36 @@
len += sizeof(*grec) +
sizeof(struct in6_addr) * ntohs(*nsrcs);
- /* We treat these as MLDv1 reports for now. */
- switch (grec->grec_type) {
- case MLD2_MODE_IS_INCLUDE:
- case MLD2_MODE_IS_EXCLUDE:
- case MLD2_CHANGE_TO_INCLUDE:
- case MLD2_CHANGE_TO_EXCLUDE:
- case MLD2_ALLOW_NEW_SOURCES:
- case MLD2_BLOCK_OLD_SOURCES:
+ /* Add MLDv2 support as following */
+ if (__constant_ntohs(grec->grec_nsrcs)) {
+ err = br_ip6_multicast_add_group(br, port,
+ src_mac, skb->src_port, &grec->grec_mca, vid);
break;
-
- default:
- continue;
+ } else {
+ switch (grec->grec_type) {
+ case MLD2_MODE_IS_EXCLUDE:
+ case MLD2_CHANGE_TO_EXCLUDE:
+ case MLD2_ALLOW_NEW_SOURCES:
+ case MLD2_BLOCK_OLD_SOURCES:
+ err = br_ip6_multicast_add_group(br, port,
+ src_mac, skb->src_port, &grec->grec_mca, vid);
+ break;
+ case MLD2_MODE_IS_INCLUDE:
+ case MLD2_CHANGE_TO_INCLUDE:
+ br_ip6_multicast_leave_group(br, port, src_mac, skb->src_port, &grec->grec_mca, vid);
+ break;
+ default:
+ continue;
+ }
}
if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE ||
grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
ntohs(*nsrcs) == 0) {
- br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
+ br_ip6_multicast_leave_group(br, port, src_mac, skb->src_port, &grec->grec_mca,
vid);
} else {
- err = br_ip6_multicast_add_group(br, port,
+ err = br_ip6_multicast_add_group(br, port, src_mac, skb->src_port,
&grec->grec_mca, vid);
if (!err)
break;
@@ -1234,7 +1385,7 @@
}
static void br_multicast_mark_router(struct net_bridge *br,
- struct net_bridge_port *port)
+ struct net_bridge_port *port, port_id src_port)
{
unsigned long now = jiffies;
@@ -1249,6 +1400,9 @@
port->multicast_router == MDB_RTR_TYPE_PERM)
return;
+ if (src_port)
+ br_set_sub_port_bitmap(port->router_port_bitmap, src_port);
+
br_multicast_add_router(br, port);
mod_timer(&port->multicast_router_timer,
@@ -1257,6 +1411,7 @@
static void br_multicast_query_received(struct net_bridge *br,
struct net_bridge_port *port,
+ port_id src_port,
struct bridge_mcast_other_query *query,
struct br_ip *saddr,
unsigned long max_delay)
@@ -1265,7 +1420,50 @@
return;
br_multicast_update_query_timer(br, query, max_delay);
- br_multicast_mark_router(br, port);
+ br_multicast_mark_router(br, port, src_port);
+}
+
+static void _br_multicast_query_refresh(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mp,
+ unsigned long max_delay,
+ int group_specific)
+{
+ if (group_specific) {
+ mp->rx_specific_query = group_specific;
+ goto out;
+ }
+
+ mp->report_flood_indicator++;
+ if (mp->report_flood_indicator > br->report_flood_interval)
+ mp->report_flood_indicator = 0;
+ /*
+ * General Query: rx_specific_query refreshed only when
+ * 1. previous Query == General Query
+ * 2. previous Query != General Query, but its MRT has expired
+ */
+ if (!mp->rx_specific_query || time_after(jiffies, mp->report_target_jiffies))
+ mp->rx_specific_query = group_specific;
+out:
+ mp->report_target_jiffies = jiffies + max_delay;
+}
+
+static void br_multicast_query_refresh(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mp, unsigned long max_delay)
+{
+ struct net_bridge_mdb_htable *mdb = br->mdb;
+ struct net_bridge_mdb_entry *mp2;
+ int hash;
+
+ if (mp) {
+ _br_multicast_query_refresh(br, mp, max_delay, 1);
+ } else {
+ if (!mdb)
+ return;
+ for (hash = 0; hash < mdb->max; hash++) {
+ hlist_for_each_entry_rcu(mp2, &mdb->mhash[hash], hlist[mdb->ver])
+ _br_multicast_query_refresh(br, mp2, max_delay, 0);
+ }
+ }
}
static int br_ip4_multicast_query(struct net_bridge *br,
@@ -1275,12 +1473,13 @@
{
const struct iphdr *iph = ip_hdr(skb);
struct igmphdr *ih = igmp_hdr(skb);
- struct net_bridge_mdb_entry *mp;
+ struct net_bridge_mdb_entry *mp = NULL;
struct igmpv3_query *ih3;
struct net_bridge_port_group *p;
struct net_bridge_port_group __rcu **pp;
struct br_ip saddr;
unsigned long max_delay;
+ unsigned long mrt_delay;
unsigned long now = jiffies;
unsigned int offset = skb_transport_offset(skb);
__be32 group;
@@ -1315,14 +1514,24 @@
saddr.proto = htons(ETH_P_IP);
saddr.u.ip4 = iph->saddr;
- br_multicast_query_received(br, port, &br->ip4_other_query,
- &saddr, max_delay);
+ br_multicast_query_received(br, port, skb->src_port, &br->ip4_other_query, &saddr,
+ max_delay);
+ mrt_delay = max_delay;
+
+/* br_multicast_query_received(br, port, &br->ip4_other_query,*/
+/* &saddr, max_delay);*/
goto out;
}
mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid);
if (!mp)
- goto out;
+ goto query_refresh;
+
+ /*
+ * IGMP Group-specific Membership Query must be
+ * copied to each member in target multicast group
+ */
+ BR_INPUT_SKB_CB(skb)->ucast_fwd = 1;
max_delay *= br->multicast_last_member_count;
@@ -1341,11 +1550,49 @@
mod_timer(&p->timer, now + max_delay);
}
+query_refresh:
+ /*
+ * use Max Response Time derived from packet
+ */
+ br_multicast_query_refresh(br, mp, mrt_delay);
out:
spin_unlock(&br->multicast_lock);
return err;
}
+/* called with multicast lock held */
+static void br_multicast_leave_subport(struct net_bridge *br,
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ struct br_ip *group)
+{
+ struct net_bridge_mdb_entry *me;
+ struct net_bridge_port_group *p;
+
+ if (port == NULL)
+ return;
+
+ me = br_mdb_ip_get(br->mdb, group);
+ if (me == NULL)
+ return;
+
+ for (p = me->ports; p != NULL; p = p->next) {
+ if ((p->port != port) || (p->sub_port != sub_port))
+ continue;
+
+ br_multicast_leave_subport_mac(p, src_mac);
+
+ if (!br_multicast_subport_empty(p))
+ break;
+
+ if (g_fwt_mult_leave_hook)
+ g_fwt_mult_leave_hook(sub_port, port->dev->if_port, group);
+
+ br_multicast_del_pg(br, p);
+ }
+}
+
#if IS_ENABLED(CONFIG_IPV6)
static int br_ip6_multicast_query(struct net_bridge *br,
struct net_bridge_port *port,
@@ -1354,12 +1601,13 @@
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
struct mld_msg *mld;
- struct net_bridge_mdb_entry *mp;
+ struct net_bridge_mdb_entry *mp = NULL;
struct mld2_query *mld2q;
struct net_bridge_port_group *p;
struct net_bridge_port_group __rcu **pp;
struct br_ip saddr;
- unsigned long max_delay;
+ unsigned long max_delay = 10 * HZ;
+ unsigned long mrt_delay;
unsigned long now = jiffies;
unsigned int offset = skb_transport_offset(skb);
const struct in6_addr *group = NULL;
@@ -1398,11 +1646,12 @@
saddr.proto = htons(ETH_P_IPV6);
saddr.u.ip6 = ip6h->saddr;
- br_multicast_query_received(br, port, &br->ip6_other_query,
+ br_multicast_query_received(br, port, skb->src_port, &br->ip6_other_query,
&saddr, max_delay);
+ mrt_delay = max_delay;
goto out;
} else if (!group) {
- goto out;
+ goto query_refresh;
}
mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid);
@@ -1424,6 +1673,8 @@
try_to_del_timer_sync(&p->timer) >= 0)
mod_timer(&p->timer, now + max_delay);
}
+query_refresh:
+ br_multicast_query_refresh(br, mp, mrt_delay);
out:
spin_unlock(&br->multicast_lock);
@@ -1433,10 +1684,12 @@
static void
br_multicast_leave_group(struct net_bridge *br,
- struct net_bridge_port *port,
- struct br_ip *group,
- struct bridge_mcast_other_query *other_query,
- struct bridge_mcast_own_query *own_query)
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ struct br_ip *group,
+ struct bridge_mcast_querier *querier,
+ struct bridge_mcast_own_query *query)
{
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
@@ -1445,6 +1698,7 @@
unsigned long time;
spin_lock(&br->multicast_lock);
+ br_multicast_leave_subport(br, port, src_mac, sub_port, group);
if (!netif_running(br->dev) ||
(port && port->state == BR_STATE_DISABLED))
goto out;
@@ -1460,7 +1714,7 @@
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port != port)
+ if (p->port != port || p->sub_port != sub_port)
continue;
rcu_assign_pointer(*pp, p->next);
@@ -1477,7 +1731,7 @@
goto out;
}
- if (timer_pending(&other_query->timer))
+ if (timer_pending(&query->timer))
goto out;
if (br->multicast_querier) {
@@ -1486,13 +1740,13 @@
time = jiffies + br->multicast_last_member_count *
br->multicast_last_member_interval;
- mod_timer(&own_query->timer, time);
+ mod_timer(&query->timer, time);
for (p = mlock_dereference(mp->ports, br);
p != NULL;
p = mlock_dereference(p->next, br)) {
- if (p->port != port)
- continue;
+ if (p->port != port || p->sub_port != sub_port)
+ continue;
if (!hlist_unhashed(&p->mglist) &&
(timer_pending(&p->timer) ?
@@ -1523,8 +1777,12 @@
for (p = mlock_dereference(mp->ports, br);
p != NULL;
p = mlock_dereference(p->next, br)) {
- if (p->port != port)
- continue;
+ if (p->port != port || p->sub_port != sub_port)
+ continue;
+
+ if (!br_multicast_subport_empty(p)) {
+ break;
+ }
if (!hlist_unhashed(&p->mglist) &&
(timer_pending(&p->timer) ?
@@ -1540,9 +1798,11 @@
}
static void br_ip4_multicast_leave_group(struct net_bridge *br,
- struct net_bridge_port *port,
- __be32 group,
- __u16 vid)
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ __be32 group,
+ __u16 vid)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1556,15 +1816,19 @@
br_group.proto = htons(ETH_P_IP);
br_group.vid = vid;
- br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
- own_query);
+ br_multicast_leave_group(br, port, src_mac, sub_port, &br_group,
+ &br->ip4_querier, own_query);
+
}
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
- struct net_bridge_port *port,
- const struct in6_addr *group,
- __u16 vid)
+ struct net_bridge_port *port,
+ const uint8_t *src_mac,
+ u32 sub_port,
+ const struct in6_addr *group,
+ __u16 vid)
+
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1578,17 +1842,26 @@
br_group.proto = htons(ETH_P_IPV6);
br_group.vid = vid;
- br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
- own_query);
+ br_multicast_leave_group(br, port, src_mac, sub_port, &br_group,
+ &br->ip6_querier, own_query);
}
#endif
+/* Added by Quantenna */
+void br_register_mult_cbk_t(br_leave_multicast_cbk leave_func, br_join_multicast_cbk join_func)
+{
+ g_fwt_mult_leave_hook = leave_func;
+ g_fwt_mult_join_hook = join_func;
+}
+EXPORT_SYMBOL(br_register_mult_cbk_t);
+
static int br_multicast_ipv4_rcv(struct net_bridge *br,
struct net_bridge_port *port,
struct sk_buff *skb,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const uint8_t *src_mac = br_ether_srcmac(skb);
struct igmphdr *ih;
int err;
@@ -1609,7 +1882,8 @@
case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT:
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip4_multicast_add_group(br, port, ih->group, vid);
+ err = br_ip4_multicast_add_group(br, port,
+ src_mac, skb->src_port, ih->group, vid);
break;
case IGMPV3_HOST_MEMBERSHIP_REPORT:
err = br_ip4_multicast_igmp3_report(br, port, skb_trimmed, vid);
@@ -1618,7 +1892,8 @@
err = br_ip4_multicast_query(br, port, skb_trimmed, vid);
break;
case IGMP_HOST_LEAVE_MESSAGE:
- br_ip4_multicast_leave_group(br, port, ih->group, vid);
+ br_ip4_multicast_leave_group(br, port,
+ src_mac, skb->src_port, ih->group, vid);
break;
}
@@ -1635,6 +1910,7 @@
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const uint8_t *src_mac = br_ether_srcmac(skb);
struct mld_msg *mld;
int err;
@@ -1654,7 +1930,8 @@
switch (mld->mld_type) {
case ICMPV6_MGM_REPORT:
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid);
+ err = br_ip6_multicast_add_group(br, port,
+ src_mac, skb->src_port, &mld->mld_mca, vid);
break;
case ICMPV6_MLD2_REPORT:
err = br_ip6_multicast_mld2_report(br, port, skb_trimmed, vid);
@@ -1663,13 +1940,17 @@
err = br_ip6_multicast_query(br, port, skb_trimmed, vid);
break;
case ICMPV6_MGM_REDUCTION:
- br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
+ br_ip6_multicast_leave_group(br, port, src_mac, skb->src_port, &mld->mld_mca, vid);
break;
}
if (skb_trimmed && skb_trimmed != skb)
kfree_skb(skb_trimmed);
+#if 0
+442 + if ((skb2 != skb) && BR_INPUT_SKB_CB(skb2)->ucast_fwd)
+443 + BR_INPUT_SKB_CB(skb)->ucast_fwd = 1;
+#endif
return err;
}
#endif
@@ -1679,11 +1960,9 @@
{
BR_INPUT_SKB_CB(skb)->igmp = 0;
BR_INPUT_SKB_CB(skb)->mrouters_only = 0;
+ BR_INPUT_SKB_CB(skb)->ucast_fwd = 0;
- if (br->multicast_disabled)
- return 0;
-
- switch (skb->protocol) {
+ switch (skb->protocol) {
case htons(ETH_P_IP):
return br_multicast_ipv4_rcv(br, port, skb, vid);
#if IS_ENABLED(CONFIG_IPV6)
@@ -1699,6 +1978,9 @@
struct bridge_mcast_own_query *query,
struct bridge_mcast_querier *querier)
{
+ if (br->multicast_router == 0)
+ return;
+
spin_lock(&br->multicast_lock);
if (query->startup_sent < br->multicast_startup_query_count)
query->startup_sent++;
@@ -1740,7 +2022,12 @@
br->multicast_startup_query_interval = 125 * HZ / 4;
br->multicast_query_interval = 125 * HZ;
br->multicast_querier_interval = 255 * HZ;
- br->multicast_membership_interval = 260 * HZ;
+ /*
+ * Fix Me: Quantenna
+ * Some types of STB don't send out IGMP report even on receiving one IGMP query.
+ * The worst case is 384 seconds. We enlarge this value to enhance system robust.
+ */
+ br->multicast_membership_interval = 760 * HZ;
br->ip4_other_query.delay_time = 0;
br->ip4_querier.port = NULL;
@@ -1895,7 +2182,8 @@
break;
case MDB_RTR_TYPE_TEMP:
p->multicast_router = MDB_RTR_TYPE_TEMP;
- br_multicast_mark_router(br, p);
+ //TODO: Avinash for now set port as 0.
+ br_multicast_mark_router(br, p, 0);
break;
default:
goto unlock;
@@ -2185,3 +2473,40 @@
return ret;
}
EXPORT_SYMBOL_GPL(br_multicast_has_querier_adjacent);
+
+
+/* Added by Quantenna */
+void br_mdb_delete_by_sub_port(struct net_bridge *br,
+ const struct net_bridge_port *port,
+ port_id sub_port)
+{
+ struct net_bridge_mdb_htable *mdb;
+ struct net_bridge_mdb_entry *mp;
+ struct net_bridge_port_group *p;
+ struct net_bridge_port_group **pp;
+ struct hlist_node *node;
+
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&br->multicast_lock, flags);
+
+ mdb = br->mdb;
+ if (mdb == NULL) {
+ spin_unlock_irqrestore(&br->multicast_lock, flags);
+ return;
+ }
+
+ for (i = 0; i < mdb->max; i++) {
+ hlist_for_each_entry_safe(mp, node, &mdb->mhash[i], hlist[mdb->ver]) {
+ for (pp = &mp->ports; (p = *pp); pp = &p->next) {
+ if (p->port != port || p->sub_port != sub_port)
+ continue;
+ br_multicast_remove_pg(br, mp, p, pp);
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&br->multicast_lock, flags);
+}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 52edecf..b74e00c 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -21,9 +21,7 @@
#include <net/ip6_fib.h>
#include <linux/if_vlan.h>
#include <linux/rhashtable.h>
-
-#define BR_HASH_BITS 8
-#define BR_HASH_SIZE (1 << BR_HASH_BITS)
+#include "br_public.h"
#define BR_HOLD_TIME (1*HZ)
@@ -42,40 +40,8 @@
/* Path to usermode spanning tree program */
#define BR_STP_PROG "/sbin/bridge-stp"
-typedef struct bridge_id bridge_id;
-typedef struct mac_addr mac_addr;
-typedef __u16 port_id;
-
-struct bridge_id
-{
- unsigned char prio[2];
- unsigned char addr[ETH_ALEN];
-};
-
-struct mac_addr
-{
- unsigned char addr[ETH_ALEN];
-};
-
-#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
-/* our own querier */
-struct bridge_mcast_own_query {
- struct timer_list timer;
- u32 startup_sent;
-};
-
-/* other querier */
-struct bridge_mcast_other_query {
- struct timer_list timer;
- unsigned long delay_time;
-};
-
-/* selected querier */
-struct bridge_mcast_querier {
- struct br_ip addr;
- struct net_bridge_port __rcu *port;
-};
-#endif
+#define BR_AGE_MAX_SEC (60 * 60 * 2)
+#define BR_AGE_MIN_SEC (30 * 60)
struct br_vlan_stats {
u64 rx_bytes;
@@ -144,20 +110,22 @@
u16 pvid;
};
-struct net_bridge_fdb_entry
+enum
{
- struct hlist_node hlist;
- struct net_bridge_port *dst;
+ MCAST_FWD_BLOCK = 0,
+ MCAST_FWD_ALLOW = 1,
+};
- unsigned long updated;
- unsigned long used;
- mac_addr addr;
- __u16 vlan_id;
- unsigned char is_local:1,
- is_static:1,
- added_by_user:1,
- added_by_external_learn:1;
- struct rcu_head rcu;
+struct net_bridge_mcast_reqs
+{
+ mac_addr ucast_req_addr;
+ unsigned char forward;
+ struct list_head list;
+};
+
+struct net_bridge_subport_req {
+ uint8_t src_mac[ETH_ALEN];
+ struct net_bridge_subport_req *next;
};
#define MDB_PG_FLAGS_PERMANENT BIT(0)
@@ -171,6 +139,11 @@
struct timer_list timer;
struct br_ip addr;
unsigned char flags;
+ u32 sub_port;
+ struct {
+ struct net_bridge_subport_req *head;
+ unsigned int count;
+ } subport_reqs;
};
struct net_bridge_mdb_entry
@@ -182,6 +155,9 @@
struct timer_list timer;
struct br_ip addr;
bool mglist;
+ u32 report_flood_indicator;
+ unsigned long report_target_jiffies;
+ u32 rx_specific_query;
};
struct net_bridge_mdb_htable
@@ -195,56 +171,6 @@
u32 ver;
};
-struct net_bridge_port
-{
- struct net_bridge *br;
- struct net_device *dev;
- struct list_head list;
-
- /* STP */
- u8 priority;
- u8 state;
- u16 port_no;
- unsigned char topology_change_ack;
- unsigned char config_pending;
- port_id port_id;
- port_id designated_port;
- bridge_id designated_root;
- bridge_id designated_bridge;
- u32 path_cost;
- u32 designated_cost;
- unsigned long designated_age;
-
- struct timer_list forward_delay_timer;
- struct timer_list hold_timer;
- struct timer_list message_age_timer;
- struct kobject kobj;
- struct rcu_head rcu;
-
- unsigned long flags;
-
-#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
- struct bridge_mcast_own_query ip4_own_query;
-#if IS_ENABLED(CONFIG_IPV6)
- struct bridge_mcast_own_query ip6_own_query;
-#endif /* IS_ENABLED(CONFIG_IPV6) */
- unsigned char multicast_router;
- struct timer_list multicast_router_timer;
- struct hlist_head mglist;
- struct hlist_node rlist;
-#endif
-
-#ifdef CONFIG_SYSFS
- char sysfs_name[IFNAMSIZ];
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
- struct netpoll *np;
-#endif
-#ifdef CONFIG_BRIDGE_VLAN_FILTERING
- struct net_bridge_vlan_group __rcu *vlgrp;
-#endif
-};
#define br_auto_port(p) ((p)->flags & BR_AUTO_MASK)
#define br_promisc_port(p) ((p)->flags & BR_PROMISC)
@@ -262,102 +188,6 @@
rtnl_dereference(dev->rx_handler_data) : NULL;
}
-struct net_bridge
-{
- spinlock_t lock;
- struct list_head port_list;
- struct net_device *dev;
-
- struct pcpu_sw_netstats __percpu *stats;
- spinlock_t hash_lock;
- struct hlist_head hash[BR_HASH_SIZE];
-#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
- union {
- struct rtable fake_rtable;
- struct rt6_info fake_rt6_info;
- };
- bool nf_call_iptables;
- bool nf_call_ip6tables;
- bool nf_call_arptables;
-#endif
- u16 group_fwd_mask;
- u16 group_fwd_mask_required;
-
- /* STP */
- bridge_id designated_root;
- bridge_id bridge_id;
- u32 root_path_cost;
- unsigned long max_age;
- unsigned long hello_time;
- unsigned long forward_delay;
- unsigned long bridge_max_age;
- unsigned long ageing_time;
- unsigned long bridge_hello_time;
- unsigned long bridge_forward_delay;
-
- u8 group_addr[ETH_ALEN];
- bool group_addr_set;
- u16 root_port;
-
- enum {
- BR_NO_STP, /* no spanning tree */
- BR_KERNEL_STP, /* old STP in kernel */
- BR_USER_STP, /* new RSTP in userspace */
- } stp_enabled;
-
- unsigned char topology_change;
- unsigned char topology_change_detected;
-
-#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
- unsigned char multicast_router;
-
- u8 multicast_disabled:1;
- u8 multicast_querier:1;
- u8 multicast_query_use_ifaddr:1;
- u8 has_ipv6_addr:1;
-
- u32 hash_elasticity;
- u32 hash_max;
-
- u32 multicast_last_member_count;
- u32 multicast_startup_query_count;
-
- unsigned long multicast_last_member_interval;
- unsigned long multicast_membership_interval;
- unsigned long multicast_querier_interval;
- unsigned long multicast_query_interval;
- unsigned long multicast_query_response_interval;
- unsigned long multicast_startup_query_interval;
-
- spinlock_t multicast_lock;
- struct net_bridge_mdb_htable __rcu *mdb;
- struct hlist_head router_list;
-
- struct timer_list multicast_router_timer;
- struct bridge_mcast_other_query ip4_other_query;
- struct bridge_mcast_own_query ip4_own_query;
- struct bridge_mcast_querier ip4_querier;
-#if IS_ENABLED(CONFIG_IPV6)
- struct bridge_mcast_other_query ip6_other_query;
- struct bridge_mcast_own_query ip6_own_query;
- struct bridge_mcast_querier ip6_querier;
-#endif /* IS_ENABLED(CONFIG_IPV6) */
-#endif
-
- struct timer_list hello_timer;
- struct timer_list tcn_timer;
- struct timer_list topology_change_timer;
- struct timer_list gc_timer;
- struct kobject *ifobj;
- u32 auto_cnt;
-#ifdef CONFIG_BRIDGE_VLAN_FILTERING
- struct net_bridge_vlan_group __rcu *vlgrp;
- u8 vlan_enabled;
- u8 vlan_stats_enabled;
- __be16 vlan_proto;
- u16 default_pvid;
-#endif
-};
struct br_input_skb_cb {
struct net_device *brdev;
@@ -367,6 +197,7 @@
int mrouters_only;
#endif
+ int ucast_fwd;
bool proxyarp_replied;
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
@@ -378,8 +209,10 @@
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (BR_INPUT_SKB_CB(__skb)->mrouters_only)
+# define BR_INPUT_SKB_CB_UCAST_FWD(__skb) (BR_INPUT_SKB_CB(__skb)->ucast_fwd)
#else
# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (0)
+# define BR_INPUT_SKB_CB_UCAST_FWD(__skb) (0)
#endif
#define br_printk(level, br, format, args...) \
@@ -470,17 +303,38 @@
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr);
void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr);
void br_fdb_cleanup(unsigned long arg);
+extern void br_handle_fwt_capacity(struct net_bridge *br);
void br_fdb_delete_by_port(struct net_bridge *br,
const struct net_bridge_port *p, u16 vid, int do_all);
struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
const unsigned char *addr, __u16 vid);
+struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
+ unsigned char *addr);
+struct net_bridge_fdb_entry *br_fdb_get_ext(struct net_bridge *br,
+ struct sk_buff *skb,
+ unsigned char *addr);
+void br_fdb_put(struct net_bridge_fdb_entry *ent);
int br_fdb_test_addr(struct net_device *dev, unsigned char *addr);
+unsigned char br_fdb_get_attached(struct net_bridge *br, unsigned char *addr);
+unsigned char br_fdb_delete_by_sub_port(struct net_bridge *br,
+ const struct net_bridge_port *p,
+ port_id sub_port);
int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count,
unsigned long off);
int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
const unsigned char *addr, u16 vid);
+extern void br_fdb_update_const(struct net_bridge *br,
+ struct net_bridge_port *source,
+ const unsigned char *addr,
+ u16 vid, bool added_by_user,
+ port_id sub_port);
void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
- const unsigned char *addr, u16 vid, bool added_by_user);
+ const unsigned char *addr, u16 vid, bool added_by_user,
+ port_id sub_port);
+
+void br_mcast_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *mcast_addr, const unsigned char *ucast_addr,port_id sub_port,
+ int op_join);
int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev, const unsigned char *addr, u16 vid);
@@ -507,7 +361,7 @@
/* br_if.c */
void br_port_carrier_check(struct net_bridge_port *p);
-int br_add_bridge(struct net *net, const char *name);
+int br_add_bridge(struct net *net, const char *name, const uint16_t vlan_id);
int br_del_bridge(struct net *net, const char *name);
int br_add_if(struct net_bridge *br, struct net_device *dev);
int br_del_if(struct net_bridge *br, struct net_device *dev);
@@ -580,6 +434,9 @@
#define mlock_dereference(X, br) \
rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
+void br_mdb_delete_by_sub_port(struct net_bridge *br, const struct net_bridge_port *port,
+ port_id sub_port);
+
static inline bool br_multicast_is_router(struct net_bridge *br)
{
return br->multicast_router == 2 ||
@@ -587,6 +444,20 @@
timer_pending(&br->multicast_router_timer));
}
+static inline void br_reset_sub_port_bitmap(uint32_t *sub_port_map, port_id sub_port)
+{
+ port_id unmap_sub_port;
+
+ unmap_sub_port = BR_SUBPORT_UNMAP(sub_port);
+ sub_port_map[BR_SUBPORT_IDX(unmap_sub_port)] &= ~BR_SUBPORT_BITMAP(unmap_sub_port);
+}
+
+extern void br_report_flood(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mp, struct sk_buff *skb);
+extern struct net_bridge_mdb_entry *br_mdb_get_ext(struct net_bridge *br,
+ struct sk_buff *skb, u16 vid);
+extern void br_multicast_copy_to_sub_ports(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mdst, struct sk_buff *skb);
static inline bool
__br_multicast_querier_exists(struct net_bridge *br,
struct bridge_mcast_other_query *querier,
@@ -680,10 +551,27 @@
struct sk_buff *skb2)
{
}
+
+static inline void br_report_flood(struct net_bridge *br,
+ struct net_bridge_mdb_entry *mp, struct sk_buff *skb)
+{
+}
+
static inline bool br_multicast_is_router(struct net_bridge *br)
{
return 0;
}
+
+static inline void br_reset_sub_port_bitmap(uint32_t *sub_port_map, port_id sub_port)
+{
+}
+
+static inline struct net_bridge_mdb_entry *br_mdb_get_ext(struct net_bridge *br,
+ struct sk_buff *skb, u16 vid)
+{
+ return NULL;
+}
+
static inline bool br_multicast_querier_exists(struct net_bridge *br,
struct ethhdr *eth)
{
@@ -972,7 +860,8 @@
#if IS_ENABLED(CONFIG_ATM_LANE)
extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr);
#endif
-
+extern int (*br_fdb_get_active_sub_port_hook)(const struct net_bridge_port *p,
+ uint32_t *sub_port_bitmap, int size);
/* br_netlink.c */
extern struct rtnl_link_ops br_link_ops;
int br_netlink_init(void);
diff --git a/net/bridge/br_public.h b/net/bridge/br_public.h
new file mode 100644
index 0000000..0ddce55
--- /dev/null
+++ b/net/bridge/br_public.h
@@ -0,0 +1,353 @@
+/*
+ * Public APIs declaration.
+ *
+ * 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.
+ */
+
+#ifndef _BR_PUBLIC_H
+#define _BR_PUBLIC_H
+
+#include <linux/netdevice.h>
+#include <linux/if_bridge.h>
+/*
+ * Move some structure and APIs from br_private.h to here
+ * and define QTN specific bridge APIs here
+ * to accommodate QTN bridge changes and
+ * allow QTN modules to refer to bridge private
+ * structure without referring to br_private.h.
+ *
+ * Need to delete the same definition in br_private.h
+ * if already been moved here to avoid duplicate declaration.
+ */
+
+#define BR_HASH_BITS 8
+#define BR_HASH_SIZE (1 << BR_HASH_BITS)
+
+typedef struct bridge_id bridge_id;
+typedef struct mac_addr mac_addr;
+typedef __u16 port_id;
+
+
+struct bridge_id
+{
+ unsigned char prio[2];
+ unsigned char addr[6];
+};
+
+struct mac_addr
+{
+ unsigned char addr[6];
+};
+
+
+struct net_bridge_fdb_entry
+{
+ struct hlist_node hlist;
+ struct net_bridge_port *dst;
+
+
+ unsigned long updated;
+ unsigned long used;
+ mac_addr addr;
+ __u16 vlan_id;
+ unsigned char is_local:1,
+ is_static:1,
+ added_by_user:1,
+ added_by_external_learn:1;
+ struct rcu_head rcu;
+ port_id sub_port;
+};
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+/* our own querier */
+struct bridge_mcast_own_query {
+ struct timer_list timer;
+ u32 startup_sent;
+};
+
+/* other querier */
+struct bridge_mcast_other_query {
+ struct timer_list timer;
+ unsigned long delay_time;
+};
+
+/* selected querier */
+struct bridge_mcast_querier {
+ struct br_ip addr;
+ struct net_bridge_port __rcu *port;
+};
+#endif
+
+struct net_bridge
+{
+ spinlock_t lock;
+ struct list_head port_list;
+ struct net_device *dev;
+ struct net_device_stats statistics;
+
+ struct pcpu_sw_netstats __percpu *stats;
+ spinlock_t hash_lock;
+ struct hlist_head hash[BR_HASH_SIZE];
+ struct hlist_head mcast_hash[BR_HASH_SIZE];
+ unsigned long feature_mask;
+#ifdef CONFIG_BRIDGE_NETFILTER
+ struct rtable fake_rtable;
+ bool nf_call_iptables;
+ bool nf_call_ip6tables;
+ bool nf_call_arptables;
+#endif
+ u16 group_fwd_mask;
+ u16 group_fwd_mask_required;
+
+ /* STP */
+ bridge_id designated_root;
+ bridge_id bridge_id;
+ u32 root_path_cost;
+ unsigned long max_age;
+ unsigned long hello_time;
+ unsigned long forward_delay;
+ unsigned long bridge_max_age;
+ unsigned long ageing_time;
+ unsigned long bridge_hello_time;
+ unsigned long bridge_forward_delay;
+
+ u8 group_addr[ETH_ALEN];
+ bool group_addr_set;
+ u16 root_port;
+
+ enum {
+ BR_NO_STP, /* no spanning tree */
+ BR_KERNEL_STP, /* old STP in kernel */
+ BR_USER_STP, /* new RSTP in userspace */
+ } stp_enabled;
+
+ unsigned char topology_change;
+ unsigned char topology_change_detected;
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+ unsigned char multicast_router;
+
+ u8 multicast_disabled:1;
+ u8 multicast_querier:1;
+ u8 multicast_query_use_ifaddr:1;
+ u8 has_ipv6_addr:1;
+
+ u32 hash_elasticity;
+ u32 hash_max;
+#define BR_ALWAYS_FLOOD_REPORT (-1U)
+ u32 report_flood_interval;
+ u32 wlan_report_flood_enable;
+
+ u32 multicast_last_member_count;
+ u32 multicast_startup_query_count;
+
+ unsigned long multicast_last_member_interval;
+ unsigned long multicast_membership_interval;
+ unsigned long multicast_querier_interval;
+ unsigned long multicast_query_interval;
+ unsigned long multicast_query_response_interval;
+ unsigned long multicast_startup_query_interval;
+
+ spinlock_t multicast_lock;
+ struct net_bridge_mdb_htable *mdb;
+ struct hlist_head router_list;
+
+ struct timer_list multicast_router_timer;
+ struct bridge_mcast_other_query ip4_other_query;
+ struct bridge_mcast_querier ip4_querier;
+ struct bridge_mcast_own_query ip4_own_query;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct bridge_mcast_other_query ip6_other_query;
+ struct bridge_mcast_querier ip6_querier;
+ struct bridge_mcast_own_query ip6_own_query;
+#endif
+#endif
+
+ struct timer_list hello_timer;
+ struct timer_list tcn_timer;
+ struct timer_list topology_change_timer;
+ struct timer_list gc_timer;
+ struct kobject *ifobj;
+ u32 auto_cnt;
+ uint16_t vlan_id;
+#ifdef CONFIG_BRIDGE_VLAN_FILTERING
+ u8 vlan_enabled;
+ struct net_port_vlans __rcu *vlan_info;
+#endif
+ /* address of attached device when in 3-addr mode */
+ struct net_bridge_fdb_entry *br_fdb_attached;
+ enum {
+ BR_IGMP_SNOOP_DISABLED,
+ BR_IGMP_SNOOP_ENABLED,
+ BR_IGMP_SNOOP_HYBRID,
+ } igmp_snoop_enabled;
+ enum {
+ BR_SSDP_FLOOD_DISABLED,
+ BR_SSDP_FLOOD_ENABLED
+ } ssdp_flood_state;
+};
+
+#define BR_MCAST_SUBPORT_REQ_LIMIT 32
+#define BR_SUB_PORT_BITMAP_SIZE (16) /* holds QTN_NODE_NUMBER bits */
+
+struct net_bridge_port
+{
+ struct net_bridge *br;
+ struct net_device *dev;
+ struct list_head list;
+
+ /* STP */
+ u8 priority;
+ u8 state;
+ u16 port_no;
+ unsigned char topology_change_ack;
+ unsigned char config_pending;
+ port_id port_id;
+ port_id designated_port;
+ bridge_id designated_root;
+ bridge_id designated_bridge;
+ u32 path_cost;
+ u32 designated_cost;
+ unsigned long designated_age;
+
+ struct timer_list forward_delay_timer;
+ struct timer_list hold_timer;
+ struct timer_list message_age_timer;
+ struct kobject kobj;
+ struct rcu_head rcu;
+
+ unsigned long flags;
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+ struct bridge_mcast_own_query ip4_own_query;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct bridge_mcast_own_query ip6_own_query;
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+ unsigned char multicast_router;
+ struct timer_list multicast_router_timer;
+ struct hlist_head mglist;
+ struct hlist_node rlist;
+ u32 router_port_bitmap[BR_SUB_PORT_BITMAP_SIZE];
+#endif
+
+#ifdef CONFIG_SYSFS
+ char sysfs_name[IFNAMSIZ];
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ struct netpoll *np;
+#endif
+#ifdef CONFIG_BRIDGE_VLAN_FILTERING
+ struct net_port_vlans __rcu *vlan_info;
+#endif
+};
+
+#define BR_SUBPORT_UNMAP(__SUB_PORT__) ((__SUB_PORT__) &~ 0x8000)
+#define BR_SUBPORT_MAP(__SUB_PORT__) ((__SUB_PORT__) | 0x8000)
+
+#define BR_SUBPORT_IDX(__SUB_PORT__) (((__SUB_PORT__) >> 5) & 0x7)
+#define BR_SUBPORT_BITMAP(__SUB_PORT__) (1U << ((__SUB_PORT__) & 0x1F))
+#define BR_SUBPORT(__IDX__, __BIT__) (((__IDX__) << 5) + (__BIT__))
+
+
+/* br.c */
+extern void (*br_fdb_update_const_hook)(struct net_bridge *br,
+ struct net_bridge_port *source,
+ const unsigned char *addr, u16 vid, bool added_by_user,
+ port_id sub_port);
+
+extern unsigned char (*br_fdb_get_attached_hook)(struct net_bridge *br,
+ unsigned char *addr);
+extern unsigned char (*br_fdb_update_hook)(struct net_bridge *br,
+ struct net_bridge_port *source,
+ const unsigned char *addr, uint32_t sub_port);
+extern unsigned char (*br_fdb_delete_by_sub_port_hook)(struct net_bridge *br,
+ const struct net_bridge_port *p,
+ port_id sub_port);
+extern int (*br_fdb_get_active_sub_port_hook)(const struct net_bridge_port *p,
+ uint32_t *sub_port_bitmap, int size);
+extern int (*br_fdb_check_active_sub_port_hook)(const struct net_bridge_port *p,
+ const uint32_t sub_port);
+extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
+ struct sk_buff *skb,
+ unsigned char *addr);
+extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
+
+extern int (*br_fdb_fillbuf_hook)(struct net_bridge *br,
+ void *buf,
+ unsigned long maxnum,
+ unsigned long skip);
+/* new added APIs */
+void br_vlan_set_promisc(int enable);
+void br_set_ap_isolate(int enable);
+int br_get_ap_isolate(void);
+
+#if 1
+typedef int (*br_add_entry_cbk)(const uint8_t *mac_be, uint8_t port_id,
+ uint8_t sub_port, const struct br_ip *group);
+typedef int (*br_delete_entry_cbk)(const uint8_t *mac_be);
+typedef int (*br_fwt_ageing_time_cbk)(const uint8_t *mac_be);
+typedef int (*br_mult_get_fwt_ts_hook)(const struct br_ip *group);
+typedef int (*br_acquire_time_res_cbk)(void);
+typedef int (*br_join_multicast_cbk)(uint8_t sub_port, uint8_t port_id, const struct br_ip *group);
+typedef int (*br_leave_multicast_cbk)(uint8_t sub_port, uint8_t port_id, const struct br_ip *group);
+typedef uint16_t(*br_fwt_get_ent_cnt)(void);
+
+/* register CBK for copying bridge database to fwt interface */
+void br_register_hooks_cbk_t(br_add_entry_cbk add_func, br_delete_entry_cbk delete_func,
+ br_fwt_ageing_time_cbk ageing_func, br_fwt_get_ent_cnt entries_cnt);
+void br_register_mult_cbk_t(br_leave_multicast_cbk leave_func, br_join_multicast_cbk join_func);
+
+typedef struct net_bridge_port *(*br_get_node_port_cbk)(const uint16_t sub_port);
+void br_register_node_hooks_cbk_t(br_get_node_port_cbk get_node_port_func);
+#else
+typedef int (*br_add_entry_cbk)(const uint8_t *mac_be, uint16_t vid, uint8_t port_id,
+ uint16_t sub_port, const struct br_ip *group);
+typedef int(*br_delete_entry_cbk)(const uint8_t *mac_be, uint16_t vid);
+typedef int (*br_fwt_ageing_time_cbk)(const uint8_t *mac_be, const uint16_t vid);
+typedef int(*br_mult_get_fwt_ts_hook)(const struct br_ip *group);
+typedef int(*br_acquire_time_res_cbk)(void);
+typedef int(*br_join_multicast_cbk)(uint16_t sub_port, uint8_t port_id, uint16_t vid,
+ const struct br_ip *group);
+typedef int(*br_leave_multicast_cbk)(uint16_t sub_port, uint8_t port_id, uint16_t vid,
+ const struct br_ip *group);
+typedef uint16_t(*br_fwt_get_ent_cnt)(void);
+typedef struct net_bridge_port *(*br_get_node_port_cbk)(const uint16_t sub_port);
+
+/* register CBK for copying bridge database to fwt interface */
+void br_register_hooks_cbk_t(br_add_entry_cbk add_func, br_delete_entry_cbk delete_func,
+ br_fwt_ageing_time_cbk ageing_func, br_fwt_get_ent_cnt entries_cnt);
+void br_register_mult_cbk_t(br_leave_multicast_cbk leave_func, br_join_multicast_cbk join_func);
+
+void br_register_node_hooks_cbk_t(br_get_node_port_cbk get_node_port_func);
+#endif
+
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+static inline void br_set_sub_port_bitmap(uint32_t *sub_port_map, port_id sub_port)
+{
+ port_id unmap_sub_port;
+
+ unmap_sub_port = BR_SUBPORT_UNMAP(sub_port);
+ BUG_ON(BR_SUB_PORT_BITMAP_SIZE < BR_SUBPORT_IDX(unmap_sub_port));
+ sub_port_map[BR_SUBPORT_IDX(unmap_sub_port)] |= BR_SUBPORT_BITMAP(unmap_sub_port);
+}
+#else
+static inline void br_set_sub_port_bitmap(uint32_t *sub_port_map, port_id sub_port)
+{
+}
+#endif
+static inline int br_is_wlan_dev(struct net_device *dev)
+{
+ return !!(dev->qtn_flags & QTN_FLAG_WIFI_DEVICE);
+}
+void br_set_ap_isolate(int enable);
+int br_get_ap_isolate(void);
+
+struct net_bridge_port *get_br_port(const struct net_device *dev);
+
+uint16_t br_get_vlan_id(struct net_device *dev);
+int br_set_vlan_id(struct net_device *dev, uint16_t vlan_id);
+#endif
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index beb4707..f8ec79e 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -142,6 +142,72 @@
}
static DEVICE_ATTR_RW(stp_state);
+static ssize_t igmp_snoop_state_show(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+ return sprintf(buf, "%d\n", br->igmp_snoop_enabled);
+}
+
+static ssize_t igmp_snoop_state_store(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t len)
+{
+ struct net_bridge *br = to_bridge(d);
+ char *endp;
+ unsigned long val;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+
+ rtnl_lock();
+ br->igmp_snoop_enabled = val;
+ if (br->igmp_snoop_enabled == BR_IGMP_SNOOP_HYBRID) {
+ printk("Hybrid IGMP snooping\n");
+ } else {
+ printk("%sbling IGMP snooping\n", val ? "Ena" : "Disa");
+ }
+ rtnl_unlock();
+
+ return len;
+}
+static DEVICE_ATTR_RW(igmp_snoop_state);
+
+static ssize_t ssdp_flood_state_show(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+ return sprintf(buf, "%d\n", br->ssdp_flood_state);
+}
+
+static ssize_t ssdp_flood_state_store(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t len)
+{
+ struct net_bridge *br = to_bridge(d);
+ char *endp;
+ unsigned long val;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+
+ rtnl_lock();
+ br->ssdp_flood_state = !val;
+ printk("%sbling SSDP flooding\n", val ? "Ena" : "Disa");
+ rtnl_unlock();
+
+ return len;
+}
+static DEVICE_ATTR_RW(ssdp_flood_state);
+
static ssize_t group_fwd_mask_show(struct device *d,
struct device_attribute *attr,
char *buf)
@@ -169,6 +235,43 @@
}
static DEVICE_ATTR_RW(group_fwd_mask);
+static ssize_t report_flood_interval_show(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+ return sprintf(buf, "%d\n", br->report_flood_interval);
+}
+
+static ssize_t report_flood_interval_store(struct device *d,
+ struct device_attribute *attr, const char *buf,
+ size_t len)
+{
+ struct net_bridge *br = to_bridge(d);
+ char *endp;
+ long val;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ val = simple_strtol(buf, &endp, 0);
+ if (endp == buf)
+ return -EINVAL;
+
+ rtnl_lock();
+ br->report_flood_interval = val;
+ if (br->report_flood_interval == 0)
+ printk("BRIDGE: report flood-forwarding disabled\n");
+ else if (br->report_flood_interval == BR_ALWAYS_FLOOD_REPORT)
+ printk("BRIDGE: report flood-forwarding enabled\n");
+ else
+ printk("BRIDGE: report flood-forwarding interval set to %u\n",
+ br->report_flood_interval);
+ rtnl_unlock();
+
+ return len;
+}
+static DEVICE_ATTR_RW(report_flood_interval);
+
static ssize_t priority_show(struct device *d, struct device_attribute *attr,
char *buf)
{
@@ -755,6 +858,7 @@
&dev_attr_max_age.attr,
&dev_attr_ageing_time.attr,
&dev_attr_stp_state.attr,
+ &dev_attr_ssdp_flood_state.attr,
&dev_attr_group_fwd_mask.attr,
&dev_attr_priority.attr,
&dev_attr_bridge_id.attr,
@@ -769,6 +873,7 @@
&dev_attr_gc_timer.attr,
&dev_attr_group_addr.attr,
&dev_attr_flush.attr,
+ &dev_attr_igmp_snoop_state.attr,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
&dev_attr_multicast_router.attr,
&dev_attr_multicast_snooping.attr,
@@ -784,6 +889,7 @@
&dev_attr_multicast_query_interval.attr,
&dev_attr_multicast_query_response_interval.attr,
&dev_attr_multicast_startup_query_interval.attr,
+ &dev_attr_report_flood_interval.attr,
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
&dev_attr_nf_call_iptables.attr,
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index b6de4f4..b84ed4d 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1081,3 +1081,34 @@
stats->tx_packets += txpackets;
}
}
+
+uint16_t br_get_vlan_id(struct net_device *dev)
+{
+ struct net_bridge *br;
+
+ if (!(dev->priv_flags & IFF_EBRIDGE))
+ return 0;
+
+ br = netdev_priv(dev);
+
+ return br->vlan_id;
+}
+EXPORT_SYMBOL(br_get_vlan_id);
+
+int br_set_vlan_id(struct net_device *dev, uint16_t vlan_id)
+{
+ struct net_bridge *br;
+ int ret;
+
+ if (!(dev->priv_flags & IFF_EBRIDGE))
+ return -EINVAL;
+
+ br = netdev_priv(dev);
+ if (br->vlan_id == vlan_id)
+ return 0;
+
+ br->vlan_id = vlan_id;
+
+ return 0;
+}
+EXPORT_SYMBOL(br_set_vlan_id);
diff --git a/net/core/dev.c b/net/core/dev.c
index 904ff43..4b667b0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3450,7 +3450,7 @@
EXPORT_SYMBOL(netdev_max_backlog);
int netdev_tstamp_prequeue __read_mostly = 1;
-int netdev_budget __read_mostly = 300;
+int netdev_budget __read_mostly = 256;
int weight_p __read_mostly = 64; /* old backlog weight */
/* Called with irq disabled */
@@ -3926,6 +3926,32 @@
EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
#endif
+#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE))
+typedef __u16 port_id;
+struct net_bridge;
+struct net_bridge_port;
+
+unsigned char (*br_fdb_get_attached_hook)(struct net_bridge *br,
+ unsigned char *addr);
+void (*br_fdb_update_const_hook)(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *addr, u16 vid, bool added_by_user,
+ port_id sub_port);
+unsigned char (*br_fdb_delete_by_sub_port_hook)(struct net_bridge *br,
+ const struct net_bridge_port *p,
+ u16 sub_port);
+int (*br_fdb_get_active_sub_port_hook)(const struct net_bridge_port *p,
+ uint32_t *sub_port_bitmap, int size);
+int (*br_fdb_check_active_sub_port_hook)(const struct net_bridge_port *p,
+ const uint32_t sub_port);
+struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
+ unsigned char *addr);
+void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly;
+int (*br_fdb_fillbuf_hook)(struct net_bridge *br,
+ void *buf,
+ unsigned long maxnum,
+ unsigned long skip);
+#endif
+
static inline struct sk_buff *
sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
struct net_device *orig_dev)
@@ -8200,3 +8226,14 @@
}
subsys_initcall(net_dev_init);
+
+#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE))
+EXPORT_SYMBOL(br_fdb_get_hook);
+EXPORT_SYMBOL(br_fdb_put_hook);
+EXPORT_SYMBOL(br_fdb_get_attached_hook);
+EXPORT_SYMBOL(br_fdb_delete_by_sub_port_hook);
+EXPORT_SYMBOL(br_fdb_update_const_hook);
+EXPORT_SYMBOL(br_fdb_get_active_sub_port_hook);
+EXPORT_SYMBOL(br_fdb_check_active_sub_port_hook);
+EXPORT_SYMBOL(br_fdb_fillbuf_hook);
+#endif
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index b94b1d2..900aeb9 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -38,7 +38,7 @@
return 0;
}
-static gifconf_func_t *gifconf_list[NPROTO];
+static gifconf_func_t __attribute__((section(".sram.data"))) *gifconf_list[NPROTO];
/**
* register_gifconf - register a SIOCGIF handler
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index eb12d21..3314ca3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -151,6 +151,54 @@
return obj;
}
+static const struct skb_allocator * skb_allocators[SKB_ALLOCATORS_MAX];
+static uint8_t __skb_allocator_default;
+
+static inline const struct skb_allocator * skb_allocator_get_default(void)
+{
+ return skb_allocators[__skb_allocator_default];
+}
+
+void skb_allocator_register(uint8_t src, const struct skb_allocator *allocator, int set_default)
+{
+ if (src < SKB_ALLOCATORS_MAX) {
+ skb_allocators[src] = allocator;
+ if (set_default) {
+ __skb_allocator_default = src;
+ }
+ }
+}
+EXPORT_SYMBOL(skb_allocator_register);
+
+static void skb_allocator_skb_free(struct sk_buff *skb, int flags)
+{
+ const struct skb_allocator *allocator = skb->allocator;
+
+ if (unlikely(!allocator)) {
+ if (printk_ratelimit()) {
+ printk(KERN_CRIT "%s:%u: skb 0x%p data 0x%p shinfo has null allocator\n",
+ __FUNCTION__, __LINE__, skb, skb->data);
+ }
+ allocator = skb_allocator_get_default();
+ }
+
+ allocator->skb_free(skb, flags);
+}
+
+static void skb_allocator_payload_free(struct sk_buff *skb)
+{
+ const struct skb_allocator *allocator = skb_shinfo(skb)->allocator;
+
+ if (unlikely(!allocator)) {
+ if (printk_ratelimit())
+ printk(KERN_CRIT "%s:%u: skb 0x%p data 0x%p has null allocator\n",
+ __FUNCTION__, __LINE__, skb, skb->data);
+ allocator = skb_allocator_get_default();
+ }
+
+ allocator->payload_free(skb);
+}
+
/* Allocate a new skbuff. We do this ourselves so we can fill in a few
* 'private' fields and also do memory statistics to find all the
* [BEEP] leaks.
@@ -199,14 +247,11 @@
* Buffers may only be allocated from interrupts using a @gfp_mask of
* %GFP_ATOMIC.
*/
-struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
- int flags, int node)
+
+struct sk_buff *skb_allocator_kmem_caches_skb_alloc(gfp_t gfp_mask, int flags, int node)
{
struct kmem_cache *cache;
- struct skb_shared_info *shinfo;
struct sk_buff *skb;
- u8 *data;
- bool pfmemalloc;
cache = (flags & SKB_ALLOC_FCLONE)
? skbuff_fclone_cache : skbuff_head_cache;
@@ -217,9 +262,44 @@
/* Get the HEAD */
skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);
if (!skb)
- goto out;
+ return NULL;
prefetchw(skb);
+ return skb;
+}
+void skb_allocator_kmem_caches_skb_free(struct sk_buff *skb, int flags)
+{
+ struct kmem_cache *cache = (flags & SKB_ALLOC_FCLONE)
+ ? skbuff_fclone_cache : skbuff_head_cache;
+ kmem_cache_free(cache, skb);
+}
+
+
+static uint8_t *skb_allocator_kmem_caches_payload_alloc(struct skb_shared_info **shinfo,
+ size_t size, gfp_t gfp_mask, int node)
+{
+ uint8_t *data;
+
+ size = SKB_DATA_ALIGN(size);
+ data = kmalloc_node_track_caller(size + sizeof(**shinfo), gfp_mask, node);
+ if (data)
+ *shinfo = (void *) (data + size);
+ else
+ *shinfo = NULL;
+
+ return data;
+}
+
+static void skb_allocator_kmem_caches_payload_free(struct sk_buff *skb)
+{
+ kfree(skb->head);
+}
+
+void __alloc_skb_init(struct sk_buff *skb, struct skb_shared_info *shinfo,
+ u8 *data, unsigned int size,
+ int flags, const struct skb_allocator *allocator)
+{
+#if 0
/* We do our best to align skb_shared_info on a separate cache
* line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives
* aligned memory blocks, unless SLUB/SLAB debug is enabled.
@@ -236,7 +316,7 @@
*/
size = SKB_WITH_OVERHEAD(ksize(data));
prefetchw(data + size);
-
+#endif
/*
* Only clear those fields we need to clear, not those that we will
* actually initialise below. Hence, don't put any more fields after
@@ -245,7 +325,6 @@
memset(skb, 0, offsetof(struct sk_buff, tail));
/* Account for allocated memory : skb + skb->head */
skb->truesize = SKB_TRUESIZE(size);
- skb->pfmemalloc = pfmemalloc;
atomic_set(&skb->users, 1);
skb->head = data;
skb->data = data;
@@ -255,9 +334,12 @@
skb->transport_header = (typeof(skb->transport_header))~0U;
/* make sure we initialize shinfo sequentially */
- shinfo = skb_shinfo(skb);
+ skb->allocator = allocator;
+ skb_shinfo(skb) = shinfo;
+
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&shinfo->dataref, 1);
+ shinfo->allocator = allocator;
kmemcheck_annotate_variable(shinfo->destructor_arg);
if (flags & SKB_ALLOC_FCLONE) {
@@ -270,12 +352,34 @@
atomic_set(&fclones->fclone_ref, 1);
fclones->skb2.fclone = SKB_FCLONE_CLONE;
- fclones->skb2.pfmemalloc = pfmemalloc;
+ fclones->skb2.allocator = allocator;
}
+}
+
+struct sk_buff * __alloc_skb(unsigned int size,
+ gfp_t gfp_mask, int flags, int node)
+{
+ const struct skb_allocator *allocator;
+ struct sk_buff *skb;
+ struct skb_shared_info *shinfo;
+ uint8_t *data;
+
+ size = SKB_DATA_ALIGN(size);
+
+ allocator = skb_allocator_get_default();
+ skb = allocator->skb_alloc(gfp_mask, flags, node);
+ if (!skb)
+ goto out;
+
+ data = allocator->payload_alloc(&shinfo, size, gfp_mask, node);
+ if (!data)
+ goto nodata;
+
+ __alloc_skb_init(skb, shinfo, data, size, flags, allocator);
out:
return skb;
nodata:
- kmem_cache_free(cache, skb);
+ allocator->skb_free(skb, flags);
skb = NULL;
goto out;
}
@@ -321,11 +425,14 @@
skb->end = skb->tail + size;
skb->mac_header = (typeof(skb->mac_header))~0U;
skb->transport_header = (typeof(skb->transport_header))~0U;
+ skb->allocator = skb_allocators[SKB_ALLOCATOR_KMEM_CACHE];
/* make sure we initialize shinfo sequentially */
+ skb_shinfo(skb) = ((struct skb_shared_info *)(skb_end_pointer(skb)));
shinfo = skb_shinfo(skb);
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
atomic_set(&shinfo->dataref, 1);
+ shinfo->allocator = skb_allocators[SKB_ALLOCATOR_KMEM_CACHE];
kmemcheck_annotate_variable(shinfo->destructor_arg);
return skb;
@@ -576,19 +683,27 @@
if (skb->head_frag)
skb_free_frag(head);
else
- kfree(head);
+ skb_allocator_payload_free(skb);
}
static void skb_release_data(struct sk_buff *skb)
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
int i;
+ int nr_frags;
if (skb->cloned &&
atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
&shinfo->dataref))
return;
+ if (unlikely(shinfo->nr_frags >= MAX_SKB_FRAGS)) {
+ printk(KERN_CRIT "%s: skb 0x%p skb->head 0x%p end 0x%p "
+ "datasz %d shinfo 0x%p corrupt. nr_frags = %u\n",
+ __FUNCTION__, skb, skb->head, skb->end,
+ skb->end - skb->head, skb_shinfo(skb), nr_frags);
+ BUG();
+ }
for (i = 0; i < shinfo->nr_frags; i++)
__skb_frag_unref(&shinfo->frags[i]);
@@ -619,7 +734,7 @@
switch (skb->fclone) {
case SKB_FCLONE_UNAVAILABLE:
- kmem_cache_free(skbuff_head_cache, skb);
+ skb_allocator_skb_free(skb, 0);
return;
case SKB_FCLONE_ORIG:
@@ -639,8 +754,9 @@
}
if (!atomic_dec_and_test(&fclones->fclone_ref))
return;
+
fastpath:
- kmem_cache_free(skbuff_fclone_cache, fclones);
+ skb_allocator_skb_free(skb, SKB_ALLOC_FCLONE);
}
static void skb_release_head_state(struct sk_buff *skb)
@@ -836,8 +952,13 @@
new->tstamp = old->tstamp;
/* We do not copy old->sk */
new->dev = old->dev;
- memcpy(new->cb, old->cb, sizeof(old->cb));
skb_dst_copy(new, old);
+ memcpy(new->cb, old->cb, sizeof(old->cb));
+ memcpy(&new->qtn_cb, &old->qtn_cb, sizeof(old->qtn_cb));
+ new->src_port = old->src_port;
+ new->dest_port = old->dest_port;
+ new->hw_vlan_id = old->hw_vlan_id;
+ new->cache_is_cleaned = 0;
#ifdef CONFIG_XFRM
new->sp = secpath_get(old->sp);
#endif
@@ -909,6 +1030,11 @@
C(head_frag);
C(data);
C(truesize);
+ C(__shinfo);
+ C(dest_port);
+ C(src_port);
+ n->cache_is_cleaned = 0;
+ n->hbm_no_free = 0;
atomic_set(&n->users, 1);
atomic_inc(&(skb_shinfo(skb)->dataref));
@@ -1034,6 +1160,7 @@
kmemcheck_annotate_bitfield(n, flags1);
n->fclone = SKB_FCLONE_UNAVAILABLE;
+ n->allocator = skb_allocators[SKB_ALLOCATOR_KMEM_CACHE];
}
return __skb_clone(n, skb);
@@ -1198,6 +1325,8 @@
u8 *data;
int size = nhead + skb_end_offset(skb) + ntail;
long off;
+ const struct skb_allocator *allocator;
+ struct skb_shared_info *shinfo;
BUG_ON(nhead < 0);
@@ -1206,10 +1335,9 @@
size = SKB_DATA_ALIGN(size);
- if (skb_pfmemalloc(skb))
- gfp_mask |= __GFP_MEMALLOC;
- data = kmalloc_reserve(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
- gfp_mask, NUMA_NO_NODE, NULL);
+ allocator = skb_allocator_get_default();
+ data = allocator->payload_alloc(&shinfo, size, gfp_mask, -1);
+
if (!data)
goto nodata;
size = SKB_WITH_OVERHEAD(ksize(data));
@@ -1219,9 +1347,8 @@
*/
memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head);
- memcpy((struct skb_shared_info *)(data + size),
- skb_shinfo(skb),
- offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
+ memcpy(shinfo, skb_shinfo(skb),
+ offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
/*
* if shinfo is shared we must drop the old head gracefully, but if it
@@ -1258,7 +1385,9 @@
skb->cloned = 0;
skb->hdr_len = 0;
skb->nohdr = 0;
+ skb_shinfo(skb) = shinfo;
atomic_set(&skb_shinfo(skb)->dataref, 1);
+ skb_shinfo(skb)->allocator = allocator;
return 0;
nofrags:
@@ -3421,8 +3550,17 @@
return 0;
}
+static const struct skb_allocator kmem_caches_skb_allocator = {
+ .name = "kmem_caches",
+ .skb_alloc = &skb_allocator_kmem_caches_skb_alloc,
+ .skb_free = &skb_allocator_kmem_caches_skb_free,
+ .payload_alloc = &skb_allocator_kmem_caches_payload_alloc,
+ .payload_free = &skb_allocator_kmem_caches_payload_free,
+};
+
void __init skb_init(void)
{
+ skb_allocator_register(SKB_ALLOCATOR_KMEM_CACHE, &kmem_caches_skb_allocator, 1);
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
sizeof(struct sk_buff),
0,
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 66dff5e..090163a 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -152,7 +152,7 @@
* assume 802.3 if the type field is short enough to be a length.
* This is normal practice and works for any 'now in use' protocol.
*/
-__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+__be16 __sram_text eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
unsigned short _service_access_point;
const unsigned short *sap;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 4b351af..73c33de 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -395,6 +395,17 @@
return dst_input(skb);
drop:
+ /*
+ * Fix me: Some corrupt packets will get here, and it's unaligned
+ * We shall find the root casue of this, instead of do an extra
+ * alignment here.
+ */
+ if (unlikely((uint32_t)skb->head & 0x3)) {
+ int alen = skb->tail - skb->head;
+ /* memove is safe here because we don't care the content */
+ skb->head = memmove(skb->head - 2, skb->head, alen);
+ }
+
kfree_skb(skb);
return NET_RX_DROP;
}
@@ -427,7 +438,7 @@
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto inhdr_error;
- iph = ip_hdr(skb);
+ iph = ip_hdr_aligned(skb);
/*
* RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 94611e4..c8ca25a1 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -111,7 +111,7 @@
if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
goto err;
- hdr = ipv6_hdr(skb);
+ hdr = ipv6_hdr_aligned(skb);
if (hdr->version != 6)
goto err;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index c245895..8dcff3f 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -150,7 +150,7 @@
};
EXPORT_SYMBOL_GPL(nd_tbl);
-static void ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data)
+void ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data)
{
int pad = ndisc_addr_option_pad(skb->dev->type);
int data_len = skb->dev->addr_len;
@@ -171,6 +171,7 @@
if (space > 0)
memset(opt, 0, space);
}
+EXPORT_SYMBOL(ndisc_fill_addr_option);
static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
struct nd_opt_hdr *end)
@@ -377,7 +378,7 @@
ipv6_dev_mc_dec(dev, &maddr);
}
-static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
+struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
int len)
{
int hlen = LL_RESERVED_SPACE(dev);
@@ -405,8 +406,9 @@
return skb;
}
+EXPORT_SYMBOL(ndisc_alloc_skb);
-static void ip6_nd_hdr(struct sk_buff *skb,
+void ip6_nd_hdr(struct sk_buff *skb,
const struct in6_addr *saddr,
const struct in6_addr *daddr,
int hop_limit, int len)
@@ -426,6 +428,7 @@
hdr->saddr = *saddr;
hdr->daddr = *daddr;
}
+EXPORT_SYMBOL(ip6_nd_hdr);
static void ndisc_send_skb(struct sk_buff *skb,
const struct in6_addr *daddr,
@@ -594,6 +597,7 @@
ndisc_send_skb(skb, daddr, saddr);
}
+EXPORT_SYMBOL(ndisc_send_ns);
void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
const struct in6_addr *daddr)
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index dbb2738..4ea39f5 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -720,7 +720,7 @@
iw_handler handler, struct net_device *dev,
struct iw_request_info *info)
{
- int err, extra_size, user_length = 0, essid_compat = 0;
+ int err, extra_size, user_length = iwp->length, essid_compat = 0;
char *extra;
/* Calculate space needed by arguments. Always allocate
@@ -775,19 +775,43 @@
/* Save user space buffer size for checking */
user_length = iwp->length;
+
+ /*
+ * Quantenna, 01-2011:
+ *
+ * For some reason, iwp->length has been decremented by
+ * essid_compat (see above). Then user_length was set to
+ * this decremented value; it did NOT represent the
+ * actual amount of space available in the user's program.
+ * A test below (user_length vs iwp->length) could then
+ * fail where it should have succeeded, because user_length
+ * no longer represented the actual amount of available space.
+ *
+ * Instead of referring to user_length in the below block,
+ * reference iwp->length. That way user_length remains
+ * unchanged, storing the actual amount of available space.
+ */
+
/* Don't check if user_length > max to allow forward
* compatibility. The test user_length < min is
* implied by the test at the end.
*/
+ if ((cmd == SIOCGIWSCAN) && (iwp->flags & IW_REQUEST_FLAG_KILOBYTES)) {
+ user_length = iwp->length << 10;
+ }
/* Support for very large requests */
if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
- (user_length > descr->max_tokens)) {
+ ((iwp->length > descr->max_tokens) ||
+ ((cmd == SIOCGIWSCAN) && (user_length > descr->max_tokens)))) {
/* Allow userspace to GET more than max so
* we can support any size GET requests.
* There is still a limit : -ENOMEM.
*/
- extra_size = user_length * descr->token_size;
+ extra_size = iwp->length * descr->token_size;
+ if (cmd == SIOCGIWSCAN) {
+ extra_size = user_length * descr->token_size;
+ }
/* Note : user_length is originally a __u16,
* and token_size is controlled by us,
@@ -843,13 +867,25 @@
/* If we have something to return to the user */
if (!err && IW_IS_GET(cmd)) {
+ uint32_t ret_buf_len = iwp->length;
+ if ((cmd == SIOCGIWSCAN) && (iwp->flags & IW_REQUEST_FLAG_KILOBYTES)) {
+ ret_buf_len = iwp->length << 10;
+ }
+
/* Check if there is enough buffer up there */
- if (user_length < iwp->length) {
+ if (user_length < ret_buf_len) {
err = -E2BIG;
goto out;
}
if (copy_to_user(iwp->pointer, extra,
+ ret_buf_len *
+ descr->token_size)) {
+ err = -EFAULT;
+ goto out;
+ }
+ } else if (cmd == SIOCGIWSCAN && err == -E2BIG) {
+ if (copy_to_user(iwp->pointer, extra,
iwp->length *
descr->token_size)) {
err = -EFAULT;
@@ -1069,10 +1105,15 @@
ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
ioctl_standard_call,
ioctl_private_call);
+
if (ret >= 0 &&
IW_IS_GET(cmd) &&
copy_to_user(arg, ifr, sizeof(struct iwreq)))
return -EFAULT;
+ else if (cmd == SIOCGIWSCAN && ret == -E2BIG &&
+ copy_to_user(arg, ifr, sizeof(struct iwreq))) {
+ return -EFAULT;
+ }
return ret;
}
diff --git a/qtn_optfilter.pl b/qtn_optfilter.pl
new file mode 100755
index 0000000..e971343
--- /dev/null
+++ b/qtn_optfilter.pl
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+use strict;
+use warnings;
+
+my $src = $ARGV[0];
+if (defined($src)) {
+ @_ = `cat $src | grep __sram_text`;
+ if ($#_ > 0) {
+ print "-O3";
+ } else {
+ print "-Os -mno-millicode";
+ }
+}
+
diff --git a/quantenna.modified b/quantenna.modified
new file mode 100644
index 0000000..e05cd79
--- /dev/null
+++ b/quantenna.modified
@@ -0,0 +1,22 @@
+Changes to core bridging code for IGMP snooping and multicast conversion
+Adding in SoC specific routines and drivers.
+ - LED
+ - GPIO
+ - unaligned access handler
+ - UART
+Support for IPV6
+ - Compliance with test plan.
+ - MLD support.
+ - SSDP6 support.
+Adding in various debugging aids.
+ - Improved stacktrace.
+ - iperf connection tracing.
+ - Cache performance aids.
+ - Load monitoring.
+ - Text section snapshotting.
+Support for different hardwares such as SPI flashes, Ethernet switches.
+Performance enhancements.
+ - Changes to core skb allocation routines for performance enhancements.
+ - Move stack to SRAM.
+ - Modifications to allow userspace interactivity under heavy system load.
+Various bugfixes.
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 297b079..3f727a1 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -988,6 +988,8 @@
conf_write_heading(out_h, &header_printer_cb, NULL);
+ fprintf(out_h, "#define AUTOCONF_INCLUDED\n");
+
for_all_symbols(i, sym) {
sym_calc_value(sym);
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)