Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zealic/a3592fbac0dfc6784eab to your computer and use it in GitHub Desktop.
Save zealic/a3592fbac0dfc6784eab to your computer and use it in GitHub Desktop.
Fix RXBUF_SIZE to avoid skb_put crash by exceding buffer - as described in https://www.fsl.cs.sunysb.edu/kernel-api/re511.html - the original patch crashed at 300bytes packet, so i found the 10300 bytes for a jumbo-frame buffer-compat.
diff -puNrb openwrt/target/linux/mr-mips/base-files/etc/hotplug2-init.rules openwrt-new/target/linux/mr-mips/base-files/etc/hotplug2-init.rules
--- openwrt/target/linux/mr-mips/base-files/etc/hotplug2-init.rules 1970-01-01 01:00:00.000000000 +0100
+++ openwrt-new/target/linux/mr-mips/base-files/etc/hotplug2-init.rules 2014-01-09 14:06:32.000000000 +0000
@@ -0,0 +1,8 @@
+$include /etc/hotplug2-common.rules
+
+DEVICENAME ~~ (hvc) {
+ nothrottle
+ makedev /dev/%DEVICENAME% 0666
+ next
+}
+
diff -puNrb openwrt/target/linux/mr-mips/base-files/etc/inittab openwrt-new/target/linux/mr-mips/base-files/etc/inittab
--- openwrt/target/linux/mr-mips/base-files/etc/inittab 1970-01-01 01:00:00.000000000 +0100
+++ openwrt-new/target/linux/mr-mips/base-files/etc/inittab 2014-01-09 14:05:57.000000000 +0000
@@ -0,0 +1,4 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K stop
+hvc0::askfirst:/bin/ash --login
+
diff -puNrb openwrt/target/linux/mr-mips/config-3.10 openwrt-new/target/linux/mr-mips/config-3.10
--- openwrt/target/linux/mr-mips/config-3.10 1970-01-01 01:00:00.000000000 +0100
+++ openwrt-new/target/linux/mr-mips/config-3.10 2014-01-11 10:24:10.000000000 +0000
@@ -0,0 +1,1528 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/mips 3.10.49 Kernel Configuration
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_MIPS_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_ATH79 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_JZ4740 is not set
+# CONFIG_LANTIQ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MACH_LOONGSON is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_POWERTV is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+CONFIG_MIPS_MIKROTIK=y
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_NLM_XLR_BOARD is not set
+# CONFIG_NLM_XLP_BOARD is not set
+# CONFIG_SOFT_PCI_IO is not set
+CONFIG_MAPPED_KERNEL=y
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+# CONFIG_MIPS_MACHINE is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=4
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_SECCOMP=y
+# CONFIG_USE_OF is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_IRQ_FORCED_THREADING=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# 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=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+# CONFIG_AIO 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_PERF_COUNTERS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_PCI_QUIRKS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_DEBUG 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_MMU=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+# CONFIG_DEFAULT_TCP_CONG is not set
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+# CONFIG_NETFILTER_XT_MARK is not set
+# CONFIG_NETFILTER_XT_CONNMARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_REDIRECT is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES 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_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET 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
+
+#
+# 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_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_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+# CONFIG_AX25 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_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# 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
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# 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
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_VIRTIO_BLK is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_INTEL_MID_PTI is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_PCH_PHUB is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+
+#
+# Altera FPGA firmware download module
+#
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI_MOD is not set
+# 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_I2O is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_MII is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN 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_VETH is not set
+# CONFIG_VIRTIO_NET is not set
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_ACENIC is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_PCNET32 is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_B44 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2X is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_BNA is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_ENIC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_BE2NET is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_NET_VENDOR_I825XX is not set
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+# CONFIG_RBKORINA is not set
+# CONFIG_ADM5120_ETH is not set
+# CONFIG_CRETHER is not set
+CONFIG_MT_VETH=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_NET_VENDOR_8390 is not set
+# CONFIG_AX88796 is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_PCH_GBE is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_PACKET_ENGINE=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R8169 is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_R6040 is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_SEEQ8005 is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_SC92031 is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SFC is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_STMMAC_ETH is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_TLAN is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_TC35815 is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_MICREL_KS8995MA is not set
+CONFIG_PPP=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_DEFLATE is not set
+CONFIG_PPP_FILTER=y
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP 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_ISDN_I4L is not set
+# CONFIG_ISDN_CAPI is not set
+# CONFIG_ISDN_DRV_GIGASET is not set
+# CONFIG_HYSDN is not set
+# CONFIG_MISDN is not set
+# CONFIG_PHONE 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
+
+#
+# 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
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+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_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_NR_UARTS is not set
+# CONFIG_SERIAL_8250_RUNTIME_UARTS is not set
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_ADM5120 is not set
+# CONFIG_SERIAL_AR9330 is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+# CONFIG_SERIAL_MFD_HSU is not set
+# CONFIG_SERIAL_CORE is not set
+# CONFIG_SERIAL_CORE_CONSOLE is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_META=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_RAMOOPS is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_SPI_DEBUG is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_RB400 is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_TOPCLIFF_PCH is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_VX855 is not set
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_ML_IOH is not set
+# CONFIG_GPIO_RDC321X is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_SSB_POSSIBLE is not set
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+# CONFIG_BCMA_POSSIBLE is not set
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_TIMBERDALE is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGA_ARB is not set
+# CONFIG_VGA_ARB_MAX_GPUS= is not set
+# CONFIG_DRM is not set
+# CONFIG_STUB_POULSBO is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_RB400 is not set
+# CONFIG_LEDS_RB_MIPSEL is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_OT200 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_RING=y
+
+#
+# Virtio drivers
+#
+CONFIG_VIRTIO_PCI=y
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_ET131X is not set
+# CONFIG_ECHO is not set
+# CONFIG_R8187SE is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_DX_SEP is not set
+# CONFIG_IIO is not set
+# CONFIG_XVMALLOC is not set
+# CONFIG_ZRAM is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_STAGING_MEDIA is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+
+#
+# Hardware Spinlock drivers
+#
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ 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_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# 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
+
+#
+# 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 is not set
+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_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_LOGFS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_XATTR is not set
+CONFIG_SQUASHFS_ZLIB=y
+# CONFIG_SQUASHFS_LZO is not set
+# CONFIG_SQUASHFS_XZ is not set
+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_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_META_FS=y
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER 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_STACKTRACE is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+CONFIG_CMDLINE_BOOL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_SPINLOCK_TEST 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_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD 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_SEQIV 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
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH 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 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# 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_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 is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+#
+
+CONFIG_CMDLINE="init=/etc/preinit"
+# CONFIG_CMDLINE_OVERRIDE is not set
diff -puNrb openwrt/target/linux/mr-mips/image/Makefile openwrt-new/target/linux/mr-mips/image/Makefile
--- openwrt/target/linux/mr-mips/image/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ openwrt-new/target/linux/mr-mips/image/Makefile 2014-01-09 14:00:54.000000000 +0000
@@ -0,0 +1,15 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+define Image/BuildKernel
+ cp $(KDIR)/vmlinux.elf $(TARGET_DIR)/kernel
+endef
+
+$(eval $(call BuildImage))
+
diff -puNrb openwrt/target/linux/mr-mips/Makefile openwrt-new/target/linux/mr-mips/Makefile
--- openwrt/target/linux/mr-mips/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ openwrt-new/target/linux/mr-mips/Makefile 2014-01-09 14:09:04.000000000 +0000
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2007-2008 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=mips
+BOARD:=mr-mips
+BOARDNAME:=Mikrotik MetaROUTER MIPS
+FEATURES:=targz
+
+LINUX_VERSION:=3.10.49
+
+include $(INCLUDE_DIR)/target.mk
+$(eval $(call BuildTarget))
+
diff -puNrb openwrt/target/linux/mr-mips/patches-3.10/000-linux-metarouter.patch openwrt-new/target/linux/mr-mips/patches-3.10/000-linux-metarouter.patch
--- openwrt/target/linux/mr-mips/patches-3.10/000-linux-metarouter.patch 1970-01-01 01:00:00.000000000 +0100
+++ openwrt-new/target/linux/mr-mips/patches-3.10/000-linux-metarouter.patch 2014-01-11 08:49:06.000000000 +0000
@@ -0,0 +1,3265 @@
+diff -puNrb linux-3.10.49/arch/mips/include/asm/checksum.h linux-3.10.49-minimal/arch/mips/include/asm/checksum.h
+--- linux-3.10.49/arch/mips/include/asm/checksum.h 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/checksum.h 2014-01-11 07:00:34.000000000 +0000
+@@ -14,6 +14,7 @@
+ #include <linux/in6.h>
+
+ #include <asm/uaccess.h>
++#include <asm/unaligned.h>
+
+ /*
+ * computes the checksum of a memory block at buff, length len,
+@@ -105,23 +106,23 @@ static inline __sum16 ip_fast_csum(const
+ unsigned int csum;
+ int carry;
+
+- csum = word[0];
+- csum += word[1];
+- carry = (csum < word[1]);
++ csum = get_unaligned(word + 0);
++ csum += get_unaligned(word + 1);
++ carry = (csum < get_unaligned(word + 1));
+ csum += carry;
+
+- csum += word[2];
+- carry = (csum < word[2]);
++ csum += get_unaligned(word + 2);
++ carry = (csum < get_unaligned(word + 2));
+ csum += carry;
+
+- csum += word[3];
+- carry = (csum < word[3]);
++ csum += get_unaligned(word + 3);
++ carry = (csum < get_unaligned(word + 3));
+ csum += carry;
+
+ word += 4;
+ do {
+- csum += *word;
+- carry = (csum < *word);
++ csum += get_unaligned(word);
++ carry = (csum < get_unaligned(word));
+ csum += carry;
+ word++;
+ } while (word != stop);
+@@ -208,42 +209,90 @@ static __inline__ __sum16 csum_ipv6_magi
+
+ " addu %0, %6 # csum\n"
+ " sltu $1, %0, %6 \n"
+- " lw %1, 0(%2) # four words source address\n"
++#ifdef __MIPSEL__
++ " lwl %1, 3(%2) # four words source address\n"
++ " lwr %1, 0(%2) # four words source address\n"
++#else
++ " lwl %1, 0(%2) # four words source address\n"
++ " lwr %1, 3(%2) # four words source address\n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 4(%2) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 7(%2) \n"
++ " lwr %1, 4(%2) \n"
++#else
++ " lwl %1, 4(%2) \n"
++ " lwr %1, 7(%2) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 8(%2) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 11(%2) \n"
++ " lwr %1, 8(%2) \n"
++#else
++ " lwl %1, 8(%2) \n"
++ " lwr %1, 11(%2) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 12(%2) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 15(%2) \n"
++ " lwr %1, 12(%2) \n"
++#else
++ " lwl %1, 12(%2) \n"
++ " lwr %1, 15(%2) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 0(%3) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 3(%3) \n"
++ " lwr %1, 0(%3) \n"
++#else
++ " lwl %1, 0(%3) \n"
++ " lwr %1, 3(%3) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 4(%3) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 7(%3) \n"
++ " lwr %1, 4(%3) \n"
++#else
++ " lwl %1, 4(%3) \n"
++ " lwr %1, 7(%3) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 8(%3) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 11(%3) \n"
++ " lwr %1, 8(%3) \n"
++#else
++ " lwl %1, 8(%3) \n"
++ " lwr %1, 11(%3) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+
+- " lw %1, 12(%3) \n"
++#ifdef __MIPSEL__
++ " lwl %1, 15(%3) \n"
++ " lwr %1, 12(%3) \n"
++#else
++ " lwl %1, 12(%3) \n"
++ " lwr %1, 15(%3) \n"
++#endif
+ " addu %0, $1 \n"
+ " addu %0, %1 \n"
+ " sltu $1, %0, %1 \n"
+diff -puNrb linux-3.10.49/arch/mips/include/asm/io.h linux-3.10.49-minimal/arch/mips/include/asm/io.h
+--- linux-3.10.49/arch/mips/include/asm/io.h 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/io.h 2014-01-11 07:01:40.000000000 +0000
+@@ -206,6 +206,7 @@ static inline void __iomem * __ioremap_m
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
++#ifndef CONFIG_MAPPED_KERNEL
+ /*
+ * Map uncached objects in the low 512MB of address
+ * space using KSEG1.
+@@ -213,6 +214,7 @@ static inline void __iomem * __ioremap_m
+ flags == _CACHE_UNCACHED)
+ return (void __iomem *)
+ (unsigned long)CKSEG1ADDR(phys_addr);
++#endif
+ }
+
+ return __ioremap(offset, size, flags);
+@@ -625,4 +627,41 @@ extern void (*_dma_cache_inv)(unsigned l
+ */
+ #define xlate_dev_kmem_ptr(p) p
+
++#ifdef CONFIG_SOFT_PCI_IO
++
++unsigned _pci_inb(unsigned long port);
++unsigned _pci_inw(unsigned long port);
++unsigned _pci_inl(unsigned long port);
++void _pci_outb(unsigned char value, unsigned long port);
++void _pci_outw(unsigned short value, unsigned long port);
++void _pci_outl(unsigned value, unsigned long port);
++
++#define inb _pci_inb
++#define inb_p _pci_inb
++#define __mem_inb _pci_inb
++#define __mem_inb_p _pci_inb
++#define inw _pci_inw
++#define inw_p _pci_inw
++#define __mem_inw _pci_inw
++#define __mem_inw_p _pci_inw
++#define inl _pci_inl
++#define inl_p _pci_inl
++#define __mem_inl _pci_inl
++#define __mem_inl_p _pci_inl
++
++#define outb _pci_outb
++#define outb_p _pci_outb
++#define __mem_outb _pci_outb
++#define __mem_outb_p _pci_outb
++#define outw _pci_outw
++#define outw_p _pci_outw
++#define __mem_outw _pci_outw
++#define __mem_outw_p _pci_outw
++#define outl _pci_outl
++#define outl_p _pci_outl
++#define __mem_outl _pci_outl
++#define __mem_outl_p _pci_outl
++
++#endif
++
+ #endif /* _ASM_IO_H */
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/cpu-feature-overrides.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/cpu-feature-overrides.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/cpu-feature-overrides.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,6 @@
++#ifndef __ASM_MACH_RB_CPU_FEATURE_OVERRIDES_H
++#define __ASM_MACH_RB_CPU_FEATURE_OVERRIDES_H
++
++#define cpu_has_dsp 0
++
++#endif /* __ASM_MACH_RB_CPU_FEATURE_OVERRIDES_H */
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/irq.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/irq.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/irq.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,16 @@
++/*
++ * 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 by Ralf Baechle
++ */
++#ifndef __ASM_MACH_RB_IRQ_H
++#define __ASM_MACH_RBC_IRQ_H
++
++#define I8259A_IRQ_BASE 0
++#define MIPS_CPU_IRQ_BASE 0
++
++#define NR_IRQS 168
++
++#endif /* __ASM_MACH_RB_IRQ_H */
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/kernel-entry-init.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/kernel-entry-init.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/kernel-entry-init.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/kernel-entry-init.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,44 @@
++#ifndef __ASM_MACH_RB_KERNEL_ENTRY_H
++#define __ASM_MACH_RB_KERNEL_ENTRY_H
++
++.macro kernel_entry_setup
++#ifdef CONFIG_MAPPED_KERNEL
++ .set push
++ .set mips32r2
++ /* check whether we are running under 0xc0000000 address space */
++ lui t0, 0xf000
++ bal 1f
++1: and t1, ra, t0
++ li t0, 0xc0000000
++ beq t0, t1, 2f
++ /* set up 0xc0000000 address space */
++ mtc0 t0, CP0_ENTRYHI
++ li t0, 0x1f
++ mtc0 t0, CP0_ENTRYLO0
++ li t0, 0x0010001f
++ mtc0 t0, CP0_ENTRYLO1
++ li t0, PM_64M
++ mtc0 t0, CP0_PAGEMASK
++ li t0, 0
++ mtc0 t0, CP0_INDEX
++ li t0, 2
++ mtc0 t0, CP0_WIRED
++ ehb
++ tlbwi
++
++ li t0, 0xc8000000
++ mtc0 t0, CP0_ENTRYHI
++ li t0, 0x0020001f
++ mtc0 t0, CP0_ENTRYLO0
++ li t0, 0x0030001f
++ mtc0 t0, CP0_ENTRYLO1
++ li t0, 1
++ mtc0 t0, CP0_INDEX
++ ehb
++ tlbwi
++2:
++ .set pop
++#endif
++.endm
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/kmalloc.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/kmalloc.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/kmalloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/kmalloc.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,4 @@
++#ifndef __ASM_MACH_RB_KMALLOC_H
++#define __ASM_MACH_RB_KMALLOC_H
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/mangle-port.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/mangle-port.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/mangle-port.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/mangle-port.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,36 @@
++/*
++ * 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, 2004 Ralf Baechle
++ */
++#ifndef __ASM_MACH_GENERIC_MANGLE_PORT_H
++#define __ASM_MACH_GENERIC_MANGLE_PORT_H
++
++#ifdef CONFIG_CPU_LITTLE_ENDIAN
++
++#define __swizzle_addr_b(port) (port)
++#define __swizzle_addr_w(port) (port)
++#define __swizzle_addr_l(port) (port)
++#define __swizzle_addr_q(port) (port)
++
++#else
++
++#define __swizzle_addr_b(port) ((port) ^ 3)
++#define __swizzle_addr_w(port) ((port) ^ 2)
++#define __swizzle_addr_l(port) (port)
++#define __swizzle_addr_q(port) (port)
++
++#endif
++
++#define ioswabb(a,x) (x)
++#define __mem_ioswabb(a,x) (x)
++#define ioswabw(a,x) (x)
++#define __mem_ioswabw(a,x) cpu_to_le16(x)
++#define ioswabl(a,x) (x)
++#define __mem_ioswabl(a,x) cpu_to_le32(x)
++#define ioswabq(a,x) (x)
++#define __mem_ioswabq(a,x) cpu_to_le32(x)
++
++#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/spaces.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/spaces.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/spaces.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/spaces.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,30 @@
++#ifndef _ASM_MACH_RB_SPACES_H
++#define _ASM_MACH_RB_SPACES_H
++
++#include <linux/const.h>
++
++#define PHYS_OFFSET _AC(0, UL)
++
++#ifdef CONFIG_MAPPED_KERNEL
++#define CAC_BASE _AC(0xc0000000, UL)
++#else
++#define CAC_BASE _AC(0x80000000, UL)
++#endif
++#define IO_BASE _AC(0xa0000000, UL)
++#define UNCAC_BASE _AC(0xa0000000, UL)
++
++#ifndef MAP_BASE
++#define MAP_BASE _AC(0xd0000000, UL)
++#endif
++
++#define HIGHMEM_START _AC(0x20000000, UL)
++
++#define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET)
++
++#ifndef CONFIG_MAPPED_KERNEL
++#define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000)
++#else
++#define FIXADDR_TOP ((unsigned long)(long)(int)0xdffe0000)
++#endif
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/include/asm/mach-rb/war.h linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/war.h
+--- linux-3.10.49/arch/mips/include/asm/mach-rb/war.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/mach-rb/war.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,18 @@
++#ifndef __ASM_MIPS_MACH_RB_WAR_H
++#define __ASM_MIPS_MACH_RB_WAR_H
++
++#define R4600_V1_INDEX_ICACHEOP_WAR 0
++#define R4600_V1_HIT_CACHEOP_WAR 0
++#define R4600_V2_HIT_CACHEOP_WAR 0
++#define R5432_CP0_INTERRUPT_WAR 0
++#define BCM1250_M3_WAR 0
++#define SIBYTE_1956_WAR 0
++#define MIPS4K_ICACHE_REFILL_WAR 0
++#define MIPS_CACHE_SYNC_WAR 0
++#define TX49XX_ICACHE_INDEX_INV_WAR 0
++#define RM9000_CDEX_SMP_WAR 0
++#define ICACHE_REFILLS_WORKAROUND_WAR 0
++#define R10000_LLSC_WAR 0
++#define MIPS34K_MISSED_ITLB_WAR 0
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/include/asm/rb/boards.h linux-3.10.49-minimal/arch/mips/include/asm/rb/boards.h
+--- linux-3.10.49/arch/mips/include/asm/rb/boards.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/rb/boards.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,66 @@
++#ifndef _ASM_RB_BOARDS_H
++#define _ASM_RB_BOARDS_H
++
++#define MACH_GROUP_MT_RB500 1 /* Mikrotik RB500 */
++#define MACH_GROUP_MT_RB100 2 /* Mikrotik RB100 */
++#define MACH_GROUP_MT_CR 3 /* Mikrotik CR */
++#define MACH_GROUP_MT_RB400 4
++#define MACH_GROUP_MT_VM 6
++#define MACH_GROUP_MT_RB700 7
++
++
++#define MACH_MT_RB500 0
++#define MACH_MT_RB500R5 1
++#define MACH_MT_RB100 2
++#define MACH_MT_RB150 3
++#define MACH_MT_RB133 4
++#define MACH_MT_RB133C 5
++#define MACH_MT_MR 6
++#define MACH_MT_RB192 7
++#define MACH_MT_CR1 8
++#define MACH_MT_RB411 10
++#define MACH_MT_RB433 11
++#define MACH_MT_RB433U 12 /* RB433 + USB */
++#define MACH_MT_RB450 13
++#define MACH_MT_RB493 15
++#define MACH_MT_RB450G 16
++#define MACH_MT_RB411U 17
++#define MACH_MT_RB493G 18
++#define MACH_MT_RB750G 19
++#define MACH_MT_RB435G 20
++#define MACH_MT_RB750 23
++#define MACH_MT_RB711 24
++#define MACH_MT_RB_OMNI 25
++#define MACH_MT_RB_SXT5D 26
++#define MACH_MT_RB_GROOVE 27
++#define MACH_MT_RB_OMNI_5FE 28 /* OmniTIK U-5HnD */
++#define MACH_MT_RB711R3 29
++#define MACH_MT_RB751G 30
++#define MACH_MT_RB711G 31
++#define MACH_MT_RB411L 33
++#define MACH_MT_RB750GL 35
++#define MACH_MT_RB411G 36
++#define MACH_MT_RB951 37
++#define MACH_MT_GROOVE52 38
++#define MACH_MT_RB2011G 39
++#define MACH_MT_RB912G 40
++#define MACH_MT_RB433GL 41
++#define MACH_MT_RB433UL 42
++#define MACH_MT_RB_SXTG 43
++#define MACH_MT_RB751 44
++#define MACH_MT_RB_GROOVE_5S 45
++#define MACH_MT_RB433L 46
++#define MACH_MT_RB411UL 47
++#define MACH_MT_RB2011L 49
++#define MACH_MT_RB2011LS 50
++#define MACH_MT_RB951G 52
++#define MACH_MT_RB2011US 53
++#define MACH_MT_SXT2D 58
++#define MACH_MT_SXT5N 59
++#define MACH_MT_RB2011R5 61
++#define MACH_MT_CRS125G 63
++
++extern unsigned long mips_machgroup;
++extern unsigned long mips_machtype;
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/include/asm/rb/booter.h linux-3.10.49-minimal/arch/mips/include/asm/rb/booter.h
+--- linux-3.10.49/arch/mips/include/asm/rb/booter.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/rb/booter.h 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,19 @@
++#ifndef _ASM_BOOTER_H
++#define _ASM_BOOTER_H
++
++#define ID_HW_OPTIONS 0x00000015
++
++#define HW_OPT_UART_ABSENT (1 << 0)
++#define HW_OPT_HAS_VOLTAGE (1 << 1)
++#define HW_OPT_HAS_USB (1 << 2)
++#define HW_OPT_HAS_ATTINY (1 << 3)
++#define HW_OPT_NO_NAND (1 << 14)
++#define HW_OPT_HAS_LCD (1 << 15)
++#define HW_OPT_HAS_POE_OUT (1 << 16)
++#define HW_OPT_HAS_uSD (1 << 17)
++#define HW_OPT_HAS_SFP (1 << 20)
++#define HW_OPT_HAS_WIFI (1 << 21)
++
++int read_booter_cfg(unsigned id, void *buf, int amount);
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/include/asm/string.h linux-3.10.49-minimal/arch/mips/include/asm/string.h
+--- linux-3.10.49/arch/mips/include/asm/string.h 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/include/asm/string.h 2014-01-11 07:04:24.000000000 +0000
+@@ -108,8 +108,9 @@ strncmp(__const__ char *__cs, __const__
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n"
+- "1:\tlbu\t%3,(%0)\n\t"
+- "beqz\t%2,2f\n\t"
++ "1:\tbeqz\t%2,2f\n\t"
++ "nop\n\t"
++ "lbu\t%3,(%0)\n\t"
+ "lbu\t$1,(%1)\n\t"
+ "subu\t%2,1\n\t"
+ "bne\t$1,%3,3f\n\t"
+diff -puNrb linux-3.10.49/arch/mips/include/asm/vm.h linux-3.10.49-minimal/arch/mips/include/asm/vm.h
+--- linux-3.10.49/arch/mips/include/asm/vm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/include/asm/vm.h 2014-01-11 07:04:31.000000000 +0000
+@@ -0,0 +1,43 @@
++#ifndef MT_VM_H
++#define MT_VM_H
++
++#define VIRQ_BASE 64
++
++#define hypercall(name, nr, ...) \
++ asm( \
++ ".global " #name ";" \
++ ".align 2;" \
++ ".set push;" \
++ ".set noreorder;" \
++ ".type " #name ",@function;" \
++ ".ent " #name ",0;" \
++ #name ": .frame $sp,0,$ra;" \
++ "li $3, " #nr ";" \
++ "li $2, -22;" \
++ "mtc0 $0, $1;" \
++ "jr $ra;" \
++ "nop;" \
++ ".end " #name ";" \
++ ".size " #name ",.-" #name ";" \
++ ".set pop" \
++ ); \
++ asmlinkage extern int name(__VA_ARGS__);
++
++/* NOTE: do not allow vdma_descr to span multiple pages, so align it */
++struct vdma_descr {
++ unsigned addr;
++ unsigned size;
++ unsigned next;
++} __attribute__((aligned(16)));
++
++#define DONE 0x80000000
++
++static inline unsigned get_virq_nr(unsigned hwirq)
++{
++ return VIRQ_BASE + hwirq;
++}
++
++extern int vm_running(void);
++#define hc_yield() asm volatile ("wait")
++
++#endif
+diff -puNrb linux-3.10.49/arch/mips/Kbuild.platforms linux-3.10.49-minimal/arch/mips/Kbuild.platforms
+--- linux-3.10.49/arch/mips/Kbuild.platforms 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/Kbuild.platforms 2014-01-11 07:04:57.000000000 +0000
+@@ -31,6 +31,7 @@ platforms += sni
+ platforms += txx9
+ platforms += vr41xx
+ platforms += wrppmc
++platforms += rb
+
+ # include the platform specific files
+ include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
+diff -puNrb linux-3.10.49/arch/mips/Kconfig linux-3.10.49-minimal/arch/mips/Kconfig
+--- linux-3.10.49/arch/mips/Kconfig 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/Kconfig 2014-01-11 07:08:23.000000000 +0000
+@@ -713,6 +713,23 @@ config MIKROTIK_RB532
+ Support the Mikrotik(tm) RouterBoard 532 series,
+ based on the IDT RC32434 SoC.
+
++config MIPS_MIKROTIK
++ bool "Support for Mikrotik RB boards"
++ select CEVT_R4K
++ select CSRC_R4K
++ select DMA_NONCOHERENT
++ select HW_HAS_PCI
++ select IRQ_CPU
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_HAS_CPU_MIPS32_R2
++ select SYS_SUPPORTS_LITTLE_ENDIAN
++ select SYS_SUPPORTS_BIG_ENDIAN
++ select SYS_SUPPORTS_32BIT_KERNEL
++ select ZONE_DMA
++ select ARCH_REQUIRE_GPIOLIB
++ help
++ Say Y here to support all Mikrotik mips based routerboards
++
+ config WR_PPMC
+ bool "Wind River PPMC board"
+ select CEVT_R4K
+@@ -838,6 +855,14 @@ config NLM_XLP_BOARD
+
+ endchoice
+
++config SOFT_PCI_IO
++ bool "PCI IO software emulation on RB4xx"
++ depends on MIPS_MIKROTIK
++
++config MAPPED_KERNEL
++ bool "Mapped kernel support"
++ depends on MIPS_MIKROTIK
++
+ source "arch/mips/alchemy/Kconfig"
+ source "arch/mips/ath79/Kconfig"
+ source "arch/mips/bcm47xx/Kconfig"
+@@ -1164,6 +1189,7 @@ config MIPS_L1_CACHE_SHIFT
+ default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X
+ default "6" if MIPS_CPU_SCACHE
+ default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
++ default "4" if MIPS_MIKROTIK
+ default "5"
+
+ config HAVE_STD_PC_SERIAL_PORT
+@@ -1230,7 +1256,7 @@ config CPU_LOONGSON2F
+ config CPU_MIPS32_R1
+ bool "MIPS32 Release 1"
+ depends on SYS_HAS_CPU_MIPS32_R1
+- select CPU_HAS_PREFETCH
++# select CPU_HAS_PREFETCH
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+ help
+@@ -1247,7 +1273,7 @@ config CPU_MIPS32_R1
+ config CPU_MIPS32_R2
+ bool "MIPS32 Release 2"
+ depends on SYS_HAS_CPU_MIPS32_R2
+- select CPU_HAS_PREFETCH
++# select CPU_HAS_PREFETCH
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+ select HAVE_KVM
+diff -puNrb linux-3.10.49/arch/mips/kernel/backtrace.c linux-3.10.49-minimal/arch/mips/kernel/backtrace.c
+--- linux-3.10.49/arch/mips/kernel/backtrace.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/kernel/backtrace.c 2014-01-11 07:08:45.000000000 +0000
+@@ -0,0 +1,156 @@
++#include <linux/module.h>
++#include <linux/oprofile.h>
++#include <linux/mm.h>
++#include <asm/page.h>
++#include <asm/processor.h>
++#include <asm/uaccess.h>
++
++#define INSTR_JR_RA 0x03e00008
++#define INSTR_JRHB_RA 0x03e00408
++#define INSTR_ADDIU_SP 0x241d0000
++#define INSTR_SW_RA_SP 0xafbf0000
++#define INSTR_MOVE_RA_ZERO 0x0000f821
++#define REGS_MASK 0x03e00000
++#define IMM16_MASK 0x0000ffff
++
++#define REG_SP 29
++#define TO_REGS(x) ((x) << 21)
++
++static inline int fetch_u32(void *val, void *ptr, int usermode)
++{
++ if (((unsigned) ptr & 3) != 0)
++ return -EFAULT;
++
++ if (usermode)
++ return get_user(*(unsigned *) val, (unsigned *) ptr);
++
++ if (KSEGX(ptr) == KSEG3)
++ return __get_user(*(unsigned *) val, (unsigned *) ptr);
++
++ if (KSEGX(ptr) != KSEG0 && KSEGX(ptr) != KSEG2)
++ return -EFAULT;
++
++ if ((unsigned long) ptr < PAGE_OFFSET)
++ return -EFAULT;
++ if ((unsigned long) ptr > (unsigned long) high_memory)
++ return -EFAULT;
++
++ return __get_user(*(unsigned *) val, (unsigned *) ptr);
++}
++
++static inline int is_bcond(unsigned i)
++{
++ unsigned c = (i >> 26) & 7;
++ switch (i >> 29) {
++ case 0:
++ if (c == 1)
++ return (i & (1 << 19)) == 0;
++ /* fall trough */
++ case 2:
++ return c >= 4;
++ }
++ return 0;
++}
++
++static inline unsigned *find_prev_branch(unsigned *instr, unsigned *limit,
++ int usermode)
++{
++ unsigned i = 0;
++ unsigned *target = instr;
++
++ for (--instr; instr > limit; --instr) {
++ if (fetch_u32(&i, instr, usermode))
++ return 0;
++
++ if (is_bcond(i)) {
++ if (instr + 1 + (short) i == target) {
++ return instr;
++ }
++ } else if ((i & ~(IMM16_MASK | REGS_MASK)) == INSTR_ADDIU_SP) {
++ if ((i & REGS_MASK) != TO_REGS(REG_SP)) {
++ /* not simple sp adjustment, probably switching stack here */
++ return 0;
++ }
++ /* check if frame start has been hit */
++ if ((short) (i & IMM16_MASK) < 0) {
++ return 0;
++ }
++ }
++ }
++ return 0;
++}
++
++unsigned long find_prev_frame(unsigned long pc, unsigned long ra,
++ unsigned long *sp, int usermode)
++{
++ int storedRA = -1;
++ int frameSize = 0;
++ unsigned *instr;
++ unsigned *limit = (unsigned *) (pc - 4096);
++ unsigned i = 0;
++ int imm;
++
++ if (!fetch_u32(&i, (unsigned *) pc, usermode)) {
++ if ((i & ~(IMM16_MASK | REGS_MASK)) == INSTR_ADDIU_SP
++ && (short) (i & IMM16_MASK) < 0) {
++ /* we are at the beging of function, reserving stack */
++ return ra;
++ }
++ }
++
++ for (instr = (unsigned *) pc - 1; instr > limit; --instr) {
++ if (fetch_u32(&i, instr, usermode))
++ break;
++
++ if (i == INSTR_JR_RA || i == INSTR_JRHB_RA) {
++ /* found prev func end */
++ break;
++ } else if ((i & ~IMM16_MASK) == INSTR_SW_RA_SP) {
++ /* remember where previous RA was stored */
++ storedRA = (short) (i & IMM16_MASK);
++ } else if ((i & ~(IMM16_MASK | REGS_MASK)) == INSTR_ADDIU_SP) {
++ if ((i & REGS_MASK) != TO_REGS(REG_SP)) {
++ /* not simple sp adjustment, probably switching stack here */
++ return 0;
++ }
++
++ imm = (short) (i & IMM16_MASK);
++ if (imm >= 0) {
++ /* found prev func end (poping back stack frame),
++ or end of our own func in other of it's threads (chunks) */
++ if (storedRA != -1)
++ break;
++
++ instr = find_prev_branch(instr + 1, limit, usermode);
++ if (instr == 0) {
++ /* no branch to us was found,
++ it means we are at the begining of the frame */
++ break;
++ }
++ } else {
++ frameSize = -imm;
++ break;
++ }
++ } else if (i == INSTR_MOVE_RA_ZERO) {
++ /* we have come to the end of the world,
++ __start() func sets up RA wrongly */
++ return 0;
++ }
++ }
++
++ if (frameSize > 0) {
++ /* if we hit addiu sp,-X first, we have stack frame */
++
++ if (storedRA != -1) {
++ if (fetch_u32(&ra, (char *) *sp + storedRA, usermode))
++ return 0;
++ if (ra == 0)
++ return 0;
++ }
++ *sp += frameSize;
++ return ra;
++ }
++ return ra;
++}
++
++EXPORT_SYMBOL(find_prev_frame);
+diff -puNrb linux-3.10.49/arch/mips/kernel/cevt-r4k.c linux-3.10.49-minimal/arch/mips/kernel/cevt-r4k.c
+--- linux-3.10.49/arch/mips/kernel/cevt-r4k.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/kernel/cevt-r4k.c 2014-01-11 07:09:06.000000000 +0000
+@@ -112,6 +112,14 @@ static int c0_compare_int_pending(void)
+ * so wait up to worst case number of cycle counter ticks for timer interrupt
+ * changes to propagate to the cause register.
+ */
++#define back_to_back_c0_hazard4() \
++ do { \
++ back_to_back_c0_hazard(); \
++ back_to_back_c0_hazard(); \
++ back_to_back_c0_hazard(); \
++ back_to_back_c0_hazard(); \
++ } while (0)
++
+ #define COMPARE_INT_SEEN_TICKS 50
+
+ int c0_compare_int_usable(void)
+@@ -137,7 +145,7 @@ int c0_compare_int_usable(void)
+ if (c0_compare_int_pending()) {
+ cnt = read_c0_count();
+ write_c0_compare(cnt);
+- back_to_back_c0_hazard();
++ back_to_back_c0_hazard4();
+ while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+ if (!c0_compare_int_pending())
+ break;
+@@ -149,7 +157,7 @@ int c0_compare_int_usable(void)
+ cnt = read_c0_count();
+ cnt += delta;
+ write_c0_compare(cnt);
+- back_to_back_c0_hazard();
++ back_to_back_c0_hazard4();
+ if ((int)(read_c0_count() - cnt) < 0)
+ break;
+ /* increase delta if the timer was already expired */
+@@ -165,7 +173,7 @@ int c0_compare_int_usable(void)
+ return 0;
+ cnt = read_c0_count();
+ write_c0_compare(cnt);
+- back_to_back_c0_hazard();
++ back_to_back_c0_hazard4();
+ while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+ if (!c0_compare_int_pending())
+ break;
+diff -puNrb linux-3.10.49/arch/mips/kernel/head.S linux-3.10.49-minimal/arch/mips/kernel/head.S
+--- linux-3.10.49/arch/mips/kernel/head.S 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/kernel/head.S 2014-01-11 07:09:14.000000000 +0000
+@@ -146,7 +146,7 @@ EXPORT(__image_cmdline)
+ .fill 0x400
+ #endif /* CONFIG_IMAGE_CMDLINE_HACK */
+
+- __REF
++ __HEAD
+
+ NESTED(kernel_entry, 16, sp) # kernel entry point
+
+diff -puNrb linux-3.10.49/arch/mips/kernel/Makefile linux-3.10.49-minimal/arch/mips/kernel/Makefile
+--- linux-3.10.49/arch/mips/kernel/Makefile 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/kernel/Makefile 2014-01-11 07:09:28.000000000 +0000
+@@ -5,7 +5,7 @@
+ extra-y := head.o vmlinux.lds
+
+ obj-y += cpu-probe.o branch.o entry.o genex.o idle.o irq.o process.o \
+- prom.o ptrace.o reset.o setup.o signal.o syscall.o \
++ prom.o ptrace.o reset.o setup.o signal.o syscall.o backtrace.o \
+ time.o topology.o traps.o unaligned.o watch.o vdso.o
+
+ ifdef CONFIG_FUNCTION_TRACER
+diff -puNrb linux-3.10.49/arch/mips/kernel/module.c linux-3.10.49-minimal/arch/mips/kernel/module.c
+--- linux-3.10.49/arch/mips/kernel/module.c 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/kernel/module.c 2014-01-11 07:09:36.000000000 +0000
+@@ -29,6 +29,7 @@
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+ #include <linux/spinlock.h>
++#include <linux/mm.h>
+ #include <linux/jump_label.h>
+
+ #include <asm/pgtable.h> /* MODULE_START */
+@@ -182,7 +183,10 @@ static inline bool is_phys_addr(void *pt
+ #ifdef CONFIG_64BIT
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
+ #else
+- return (KSEGX(ptr) == KSEG0);
++ unsigned addr = (unsigned) ptr;
++ return addr && (addr < VMALLOC_START || addr > VMALLOC_END);
++// return (KSEGX(ptr) == KSEG0);
++
+ #endif
+ }
+
+diff -puNrb linux-3.10.49/arch/mips/kernel/proc.c linux-3.10.49-minimal/arch/mips/kernel/proc.c
+--- linux-3.10.49/arch/mips/kernel/proc.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/kernel/proc.c 2014-01-11 07:09:50.000000000 +0000
+@@ -13,6 +13,7 @@
+ #include <asm/idle.h>
+ #include <asm/mipsregs.h>
+ #include <asm/processor.h>
++#include <asm/time.h>
+ #include <asm/prom.h>
+
+ unsigned int vced_count, vcei_count;
+@@ -20,6 +21,7 @@ unsigned int vced_count, vcei_count;
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ unsigned long n = (unsigned long) v - 1;
++ unsigned cpu_khz = mips_hpt_frequency / 500;
+ unsigned int version = cpu_data[n].processor_id;
+ unsigned int fp_vers = cpu_data[n].fpu_id;
+ char fmt [64];
+@@ -46,6 +48,8 @@ static int show_cpuinfo(struct seq_file
+ seq_printf(m, fmt, __cpu_name[n],
+ (version >> 4) & 0x0f, version & 0x0f,
+ (fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
++ seq_printf(m, "cpu MHz\t\t\t: %u.%03u\n",
++ cpu_khz / 1000, (cpu_khz % 1000));
+ seq_printf(m, "BogoMIPS\t\t: %u.%02u\n",
+ cpu_data[n].udelay_val / (500000/HZ),
+ (cpu_data[n].udelay_val / (5000/HZ)) % 100);
+diff -puNrb linux-3.10.49/arch/mips/kernel/time.c linux-3.10.49-minimal/arch/mips/kernel/time.c
+--- linux-3.10.49/arch/mips/kernel/time.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/kernel/time.c 2014-01-11 07:09:56.000000000 +0000
+@@ -70,6 +70,7 @@ EXPORT_SYMBOL(perf_irq);
+ */
+
+ unsigned int mips_hpt_frequency;
++EXPORT_SYMBOL(mips_hpt_frequency);
+
+ /*
+ * This function exists in order to cause an error due to a duplicate
+diff -puNrb linux-3.10.49/arch/mips/kernel/traps.c linux-3.10.49-minimal/arch/mips/kernel/traps.c
+--- linux-3.10.49/arch/mips/kernel/traps.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/kernel/traps.c 2014-01-11 07:10:14.000000000 +0000
+@@ -91,6 +91,8 @@ void (*board_ebase_setup)(void);
+ void (*board_ebase_setup)(void);
+ void __cpuinitdata(*board_cache_error_setup)(void);
+
++#define CONFIG_RAWBACKTRACE
++#ifdef CONFIG_RAWBACKTRACE
+ static void show_raw_backtrace(unsigned long reg29)
+ {
+ unsigned long *sp = (unsigned long *)(reg29 & ~3);
+@@ -144,6 +146,25 @@ static void show_backtrace(struct task_s
+ printk("\n");
+ }
+
++#else
++
++static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
++{
++ unsigned long sp = regs->regs[29];
++ unsigned long ra = regs->regs[31];
++ unsigned long pc = regs->cp0_epc;
++ int depth = 16;
++
++ printk("Call Trace:\n");
++ while (depth-- && pc) {
++ print_ip_sym(pc);
++ pc = find_prev_frame(pc, ra, &sp, 0);
++ ra = 0;
++ }
++ printk("\n");
++}
++#endif
++
+ /*
+ * This routine abuses get_user()/put_user() to reference pointers
+ * with at least a bit of error checking ...
+@@ -367,6 +388,7 @@ void __noreturn die(const char *str, str
+ if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
+ sig = 0;
+
++ oops_enter();
+ console_verbose();
+ raw_spin_lock_irq(&die_lock);
+ #ifdef CONFIG_MIPS_MT_SMTC
+@@ -1487,7 +1509,7 @@ void __init *set_except_vector(int n, vo
+ #endif
+ u32 *buf = (u32 *)(ebase + 0x200);
+ unsigned int k0 = 26;
+- if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
++ if ((handler & jump_mask) == ((KSEG0ADDR(ebase) + 0x200) & jump_mask)) {
+ uasm_i_j(&buf, handler & ~jump_mask);
+ uasm_i_nop(&buf);
+ } else {
+@@ -1727,6 +1749,7 @@ void __cpuinit per_cpu_trap_init(void)
+ * o read IntCtl.IPTI to determine the timer interrupt
+ * o read IntCtl.IPPCI to determine the performance counter interrupt
+ */
++#ifdef CONFIG_CPU_MIPSR2
+ if (cpu_has_mips_r2) {
+ cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
+ cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
+@@ -1734,11 +1757,17 @@ void __cpuinit per_cpu_trap_init(void)
+ if (cp0_perfcount_irq == cp0_compare_irq)
+ cp0_perfcount_irq = -1;
+ } else {
++#endif
+ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
+ cp0_compare_irq_shift = CP0_LEGACY_PERFCNT_IRQ;
+ cp0_perfcount_irq = -1;
++#ifdef CONFIG_CPU_MIPSR2
+ }
++#endif
+
++#ifdef CONFIG_MIPS_MIKROTIK
++ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
++#endif
+ #ifdef CONFIG_MIPS_MT_SMTC
+ }
+ #endif /* CONFIG_MIPS_MT_SMTC */
+@@ -1833,7 +1862,7 @@ void __init trap_init(void)
+ #define KVM_GUEST_KSEG0 0x40000000
+ ebase = KVM_GUEST_KSEG0;
+ #else
+- ebase = CKSEG0;
++ ebase = CAC_BASE;
+ #endif
+ if (cpu_has_mips_r2)
+ ebase += (read_c0_ebase() & 0x3ffff000);
+diff -puNrb linux-3.10.49/arch/mips/kernel/unaligned.c linux-3.10.49-minimal/arch/mips/kernel/unaligned.c
+--- linux-3.10.49/arch/mips/kernel/unaligned.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/kernel/unaligned.c 2014-01-11 07:10:25.000000000 +0000
+@@ -106,6 +106,24 @@ static u32 unaligned_action;
+ #endif
+ extern void show_registers(struct pt_regs *regs);
+
++#define RATE_BURST (10*5*HZ)
++#define RATE_COST (5*HZ)
++
++static int un_ratelimit(void) {
++ static unsigned toks = RATE_BURST;
++ static unsigned last_msg;
++
++ unsigned now = jiffies;
++ toks += now - last_msg;
++ if (toks > RATE_BURST) toks = RATE_BURST;
++
++ if (toks >= RATE_COST) {
++ toks -= RATE_COST;
++ return 1;
++ }
++ return 0;
++}
++
+ #ifdef __BIG_ENDIAN
+ #define LoadHW(addr, value, res) \
+ __asm__ __volatile__ (".set\tnoat\n" \
+@@ -1549,10 +1579,23 @@ sigill:
+ ("Unhandled kernel unaligned access or invalid instruction", regs);
+ force_sig(SIGILL, current);
+ }
++
++extern asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
++ unsigned long address);
++
+ asmlinkage void do_ade(struct pt_regs *regs)
+ {
+- unsigned int __user *pc;
++ unsigned int __user *pc = NULL;
+ mm_segment_t seg;
++ unsigned long badvaddr = regs->cp0_badvaddr;
++
++ /* We are running in VM protected enviroment and
++ we hit KSEG0, or KSEG3 address */
++ if ((badvaddr & 3) == 0 && KSEGX(badvaddr) == KSEG3) {
++ do_page_fault(regs, (regs->cp0_cause & 0x7c) == 20,
++ badvaddr);
++ return;
++ }
+
+ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
+ 1, regs, regs->cp0_badvaddr);
+@@ -1567,6 +1610,10 @@ asmlinkage void do_ade(struct pt_regs *r
+ if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
+ goto sigbus;
+
++ if (!user_mode(regs) && un_ratelimit())
++ printk(KERN_WARNING "unaligned data access %lx at %p %pS\n",
++ badvaddr, pc, (void *)pc);
++
+ /*
+ * Do branch emulation only if we didn't forward the exception.
+ * This is all so but ugly ...
+diff -puNrb linux-3.10.49/arch/mips/kernel/vmlinux.lds.S linux-3.10.49-minimal/arch/mips/kernel/vmlinux.lds.S
+--- linux-3.10.49/arch/mips/kernel/vmlinux.lds.S 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/kernel/vmlinux.lds.S 2014-01-11 07:10:42.000000000 +0000
+@@ -51,6 +51,7 @@ SECTIONS
+ /* read-only */
+ _text = .; /* Text and read-only data */
+ .text : {
++ HEAD_TEXT
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+diff -puNrb linux-3.10.49/arch/mips/lib/iomap.c linux-3.10.49-minimal/arch/mips/lib/iomap.c
+--- linux-3.10.49/arch/mips/lib/iomap.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/lib/iomap.c 2014-01-11 08:11:06.000000000 +0000
+@@ -25,6 +25,8 @@
+
+ #define PIO_MASK 0x0ffffUL
+
++//#ifndef CONFIG_MIPS_MIKROTIK
++
+ unsigned int ioread8(void __iomem *addr)
+ {
+ return readb(addr);
+@@ -194,6 +196,8 @@ void iowrite32_rep(void __iomem *addr, c
+
+ EXPORT_SYMBOL(iowrite32_rep);
+
++//#endif
++
+ /*
+ * Create a virtual mapping cookie for an IO port range
+ *
+diff -puNrb linux-3.10.49/arch/mips/mm/cache.c linux-3.10.49-minimal/arch/mips/mm/cache.c
+--- linux-3.10.49/arch/mips/mm/cache.c 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/arch/mips/mm/cache.c 2014-01-11 07:11:16.000000000 +0000
+@@ -50,6 +50,7 @@ void (*flush_icache_all)(void);
+ EXPORT_SYMBOL_GPL(local_flush_data_cache_page);
+ EXPORT_SYMBOL(flush_data_cache_page);
+ EXPORT_SYMBOL(flush_icache_all);
++EXPORT_SYMBOL(flush_icache_range);
+
+ #ifdef CONFIG_DMA_NONCOHERENT
+
+diff -puNrb linux-3.10.49/arch/mips/mm/c-r4k.c linux-3.10.49-minimal/arch/mips/mm/c-r4k.c
+--- linux-3.10.49/arch/mips/mm/c-r4k.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/mm/c-r4k.c 2014-01-11 07:11:25.000000000 +0000
+@@ -1013,7 +1013,9 @@ static void __cpuinit probe_pcache(void)
+ c->dcache.linesz;
+ c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
+
++#ifdef CONFIG_CPU_HAS_PREFETCH
+ c->options |= MIPS_CPU_PREFETCH;
++#endif
+ break;
+ }
+
+diff -puNrb linux-3.10.49/arch/mips/mm/dma-default.c linux-3.10.49-minimal/arch/mips/mm/dma-default.c
+--- linux-3.10.49/arch/mips/mm/dma-default.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/mm/dma-default.c 2014-01-11 07:11:38.000000000 +0000
+@@ -14,6 +14,10 @@
+ #include <linux/module.h>
+ #include <linux/scatterlist.h>
+ #include <linux/string.h>
++#ifdef CONFIG_MAPPED_KERNEL
++#include <linux/hardirq.h>
++#include <linux/sched.h>
++#endif
+ #include <linux/gfp.h>
+ #include <linux/highmem.h>
+
+@@ -68,11 +72,9 @@ static gfp_t massage_gfp_flags(const str
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
+
+-#ifdef CONFIG_ISA
+ if (dev == NULL)
+ dma_flag = __GFP_DMA;
+ else
+-#endif
+ #if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
+ if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
+ dma_flag = __GFP_DMA;
+@@ -135,8 +137,15 @@ static void *mips_dma_alloc_coherent(str
+
+ if (!plat_device_is_coherent(dev)) {
+ dma_cache_wback_inv((unsigned long) ret, size);
++#ifndef CONFIG_MAPPED_KERNEL
+ if (!hw_coherentio)
+ ret = UNCAC_ADDR(ret);
++#else
++ if (!in_interrupt())
++ ret = ioremap((unsigned long) *dma_handle, size);
++ else
++ ret = UNCAC_ADDR(ret);
++#endif
+ }
+ }
+
+@@ -162,10 +171,24 @@ static void mips_dma_free_coherent(struc
+ if (dma_release_from_coherent(dev, order, vaddr))
+ return;
+
++#ifndef CONFIG_MAPPED_KERNEL
+ plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL);
+
+ if (!plat_device_is_coherent(dev) && !hw_coherentio)
+ addr = CAC_ADDR(addr);
++#else
++ if (!plat_device_is_coherent(dev)) {
++ pgd_t *pgd = init_mm.pgd + __pgd_offset(addr);
++ pud_t *pud = pud_offset(pgd, addr);
++ pmd_t *pmd = pmd_offset(pud, addr);
++ pte_t *pte = pte_offset(pmd, addr);
++
++ if (pte_present(*pte)) {
++ addr = (unsigned long) pfn_to_kaddr(pte_pfn(*pte));
++ iounmap(vaddr);
++ }
++ }
++#endif
+
+ free_pages(addr, get_order(size));
+ }
+diff -puNrb linux-3.10.49/arch/mips/mm/fault.c linux-3.10.49-minimal/arch/mips/mm/fault.c
+--- linux-3.10.49/arch/mips/mm/fault.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/mm/fault.c 2014-01-11 07:11:48.000000000 +0000
+@@ -85,6 +85,12 @@ asmlinkage void __kprobes do_page_fault(
+ goto VMALLOC_FAULT_TARGET;
+ #endif
+
++#ifdef CONFIG_MAPPED_KERNEL
++ /* in case we touched other VM memory */
++ if (KSEGX(address) == KSEG2)
++ goto VMALLOC_FAULT_TARGET;
++#endif
++
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+diff -puNrb linux-3.10.49/arch/mips/mm/init.c linux-3.10.49-minimal/arch/mips/mm/init.c
+--- linux-3.10.49/arch/mips/mm/init.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/mm/init.c 2014-01-11 07:12:34.000000000 +0000
+@@ -44,6 +44,10 @@
+ #include <asm/tlb.h>
+ #include <asm/fixmap.h>
+
++#ifdef CONFIG_MIPS_MIKROTIK
++#include <asm/rb/boards.h>
++#endif
++
+ /* Atomicity and interruptability */
+ #ifdef CONFIG_MIPS_MT_SMTC
+
+@@ -173,7 +177,7 @@ void *kmap_coherent(struct page *page, u
+
+ #define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+
+-void kunmap_coherent(void)
++void kunmap_coherent()
+ {
+ #ifndef CONFIG_MIPS_MT_SMTC
+ unsigned int wired;
+@@ -333,6 +337,10 @@ void __init paging_init(void)
+
+ #ifdef CONFIG_ZONE_DMA
+ max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
++#if defined(CONFIG_MIPS_MIKROTIK)
++// if (mips_machgroup != MACH_GROUP_MT_RB100)
++ max_zone_pfns[ZONE_DMA] = max_low_pfn;
++#endif
+ #endif
+ #ifdef CONFIG_ZONE_DMA32
+ max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+diff -puNrb linux-3.10.49/arch/mips/mm/ioremap.c linux-3.10.49-minimal/arch/mips/mm/ioremap.c
+--- linux-3.10.49/arch/mips/mm/ioremap.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/mm/ioremap.c 2014-01-11 07:12:48.000000000 +0000
+@@ -127,6 +127,7 @@ void __iomem * __ioremap(phys_t phys_add
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
++#ifndef CONFIG_MAPPED_KERNEL
+ /*
+ * Map uncached objects in the low 512mb of address space using KSEG1,
+ * otherwise map using page tables.
+@@ -149,6 +150,7 @@ void __iomem * __ioremap(phys_t phys_add
+ if(!PageReserved(page))
+ return NULL;
+ }
++#endif
+
+ /*
+ * Mappings have to be page-aligned
+diff -puNrb linux-3.10.49/arch/mips/mm/tlb-r4k.c linux-3.10.49-minimal/arch/mips/mm/tlb-r4k.c
+--- linux-3.10.49/arch/mips/mm/tlb-r4k.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/mm/tlb-r4k.c 2014-01-11 07:13:13.000000000 +0000
+@@ -408,7 +408,9 @@ void __cpuinit tlb_init(void)
+ * be set to fixed-size pages.
+ */
+ write_c0_pagemask(PM_DEFAULT_MASK);
++#ifndef CONFIG_MAPPED_KERNEL
+ write_c0_wired(0);
++#endif
+ if (current_cpu_type() == CPU_R10000 ||
+ current_cpu_type() == CPU_R12000 ||
+ current_cpu_type() == CPU_R14000)
+diff -puNrb linux-3.10.49/arch/mips/oprofile/common.c linux-3.10.49-minimal/arch/mips/oprofile/common.c
+--- linux-3.10.49/arch/mips/oprofile/common.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/oprofile/common.c 2014-01-11 07:14:43.000000000 +0000
+@@ -11,10 +11,14 @@
+ #include <linux/init.h>
+ #include <linux/oprofile.h>
+ #include <linux/smp.h>
++#include <asm/ptrace.h>
+ #include <asm/cpu-info.h>
++#include <asm/rb/boards.h>
+
+ #include "op_impl.h"
+
++extern int __init hrtimer_oprofile_init(struct oprofile_operations *);
++
+ extern struct op_mips_model op_model_mipsxx_ops __weak;
+ extern struct op_mips_model op_model_loongson2_ops __weak;
+
+@@ -70,11 +74,30 @@ static void op_mips_stop(void)
+ on_each_cpu(model->cpu_stop, NULL, 1);
+ }
+
++void mt_op_mips_backtrace(struct pt_regs * const regs, unsigned int depth)
++{
++ unsigned long ra = regs->regs[31];
++ unsigned long pc = regs->cp0_epc;
++ unsigned long sp = regs->regs[29];
++ int usermode = user_mode(regs);
++
++ while (depth-- && pc) {
++ pc = find_prev_frame(pc, ra, &sp, usermode);
++ if (pc) oprofile_add_trace((unsigned long) pc);
++ ra = 0;
++ }
++}
++
+ int __init oprofile_arch_init(struct oprofile_operations *ops)
+ {
+ struct op_mips_model *lmodel = NULL;
+ int res;
+
++ ops->backtrace = mt_op_mips_backtrace;
++
++ if (hrtimer_oprofile_init(ops) == 0)
++ return 0;
++
+ switch (current_cpu_type()) {
+ case CPU_5KC:
+ case CPU_M14KC:
+diff -puNrb linux-3.10.49/arch/mips/oprofile/Makefile linux-3.10.49-minimal/arch/mips/oprofile/Makefile
+--- linux-3.10.49/arch/mips/oprofile/Makefile 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/oprofile/Makefile 2014-01-11 07:15:11.000000000 +0000
+@@ -4,6 +4,7 @@ DRIVER_OBJS = $(addprefix ../../../drive
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o \
++ hrtimer.o \
+ timer_int.o )
+
+ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
+diff -puNrb linux-3.10.49/arch/mips/rb/irq.c linux-3.10.49-minimal/arch/mips/rb/irq.c
+--- linux-3.10.49/arch/mips/rb/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/irq.c 2014-01-11 08:43:14.000000000 +0000
+@@ -0,0 +1,108 @@
++#include <linux/init.h>
++#include <linux/linkage.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/bitops.h>
++#include <linux/module.h>
++#include <asm/signal.h>
++#include <asm/mipsregs.h>
++#include <asm/irq_cpu.h>
++#include <asm/bootinfo.h>
++#include <asm/vm.h>
++#include <asm/rb/boards.h>
++
++asmlinkage void plat_irq_dispatch(void) {
++ unsigned pending = read_c0_status() & read_c0_cause() & 0xfe00;
++
++ if (pending)
++ do_IRQ(fls(pending) - (9 - MIPS_CPU_IRQ_BASE));
++}
++
++volatile unsigned long virqs;
++EXPORT_SYMBOL(virqs);
++
++static void ack_virq(struct irq_data *d)
++{
++ clear_bit(d->irq - VIRQ_BASE, &virqs);
++}
++
++static inline void unmask_virq(struct irq_data *d)
++{
++}
++
++static inline void mask_virq(struct irq_data *d)
++{
++}
++
++static struct irq_chip virq_controller = {
++ .name = "virq",
++ .irq_ack = ack_virq,
++ .irq_unmask = unmask_virq,
++ .irq_mask = mask_virq,
++};
++
++static irqreturn_t virq_cascade_irq(int irq, void *dev_id)
++{
++ unsigned i;
++ unsigned irqs = virqs;
++
++ for (i = 0; irqs; ++i) {
++ if (irqs & (1 << i)) {
++ do_IRQ(i + VIRQ_BASE);
++ irqs ^= (1 << i);
++ }
++ }
++ return IRQ_HANDLED;
++}
++
++static struct irqaction virq_cascade = {
++ .handler = virq_cascade_irq,
++ .name = "virq-cascade",
++};
++
++static void soft_irq_ack(struct irq_data *d)
++{
++ clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
++}
++
++static inline void unmask_soft_irq(struct irq_data *d)
++ {
++ set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
++ irq_enable_hazard();
++ }
++
++static inline void mask_soft_irq(struct irq_data *d)
++{
++ clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
++ irq_disable_hazard();
++}
++
++static struct irq_chip soft_irq_controller = {
++ .name = "MIPS",
++ .irq_ack = soft_irq_ack,
++ .irq_unmask = unmask_soft_irq,
++ .irq_mask = mask_soft_irq,
++};
++
++extern void ont_arch_init_irq(void);
++
++void __init arch_init_irq(void)
++{
++ unsigned i;
++
++ switch (mips_machgroup) {
++ case MACH_GROUP_MT_VM:
++ mips_cpu_irq_init();
++ break;
++ }
++
++ if (mips_machgroup != MACH_GROUP_MT_RB500 &&
++ mips_machgroup != MACH_GROUP_MT_RB100) {
++ irq_set_chip_and_handler(1, &soft_irq_controller, handle_percpu_irq);
++ setup_irq(1, &virq_cascade);
++
++ for (i = VIRQ_BASE; i < VIRQ_BASE + 32; ++i)
++ irq_set_chip_and_handler(i, &virq_controller,
++ handle_edge_irq);
++ }
++}
+diff -puNrb linux-3.10.49/arch/mips/rb/Makefile linux-3.10.49-minimal/arch/mips/rb/Makefile
+--- linux-3.10.49/arch/mips/rb/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/Makefile 2014-01-11 08:15:03.000000000 +0000
+@@ -0,0 +1 @@
++obj-y += prom.o platform.o irq.o
+diff -puNrb linux-3.10.49/arch/mips/rb/Platform linux-3.10.49-minimal/arch/mips/rb/Platform
+--- linux-3.10.49/arch/mips/rb/Platform 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/Platform 2014-01-11 07:18:49.000000000 +0000
+@@ -0,0 +1,13 @@
++#
++# Mikrotik RB100/RB500 boards
++#
++platform-$(CONFIG_MIPS_MIKROTIK) += rb/
++platform-$(CONFIG_MIPS_MIKROTIK) += rb/vm/
++cflags-$(CONFIG_MIPS_MIKROTIK) += -I$(srctree)/arch/mips/include/asm/mach-rb
++ifdef CONFIG_MAPPED_KERNEL
++load-$(CONFIG_MIPS_MIKROTIK) += 0xffffffffc0101000
++OBJCOPYFLAGS += --change-addresses=0xc0000000
++else
++load-$(CONFIG_MIPS_MIKROTIK) += 0xffffffff80101000
++endif
++
+diff -puNrb linux-3.10.49/arch/mips/rb/platform.c linux-3.10.49-minimal/arch/mips/rb/platform.c
+--- linux-3.10.49/arch/mips/rb/platform.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/platform.c 2014-01-11 08:04:11.000000000 +0000
+@@ -0,0 +1,18 @@
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/serial_8250.h>
++#include <linux/spi/spi.h>
++#include <linux/mtd/partitions.h>
++#include <linux/spi/flash.h>
++#include <linux/i2c-gpio.h>
++#include <asm/bootinfo.h>
++#include <asm/rb/boards.h>
++#include <asm/rb/booter.h>
++#include <asm/serial.h>
++
++int rb_platform_init(void)
++{
++ return 0;
++}
++
++arch_initcall(rb_platform_init);
+diff -puNrb linux-3.10.49/arch/mips/rb/prom.c linux-3.10.49-minimal/arch/mips/rb/prom.c
+--- linux-3.10.49/arch/mips/rb/prom.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/prom.c 2014-01-11 08:48:36.000000000 +0000
+@@ -0,0 +1,152 @@
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/console.h>
++#include <asm/bootinfo.h>
++#include <asm/rb/boards.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/ctype.h>
++#include <linux/irq.h>
++#include <linux/initrd.h>
++
++#define FREQ_TAG "HZ="
++#define BOARD_TAG "board="
++
++#define SR_NMI 0x00180000
++
++extern void rbvm_setup(void);
++
++extern char arcs_cmdline[COMMAND_LINE_SIZE];
++
++extern unsigned long totalram_pages;
++extern unsigned long mips_hpt_frequency;
++
++unsigned char mips_mac_address[6];
++
++unsigned long mips_machgroup __read_mostly = 0;
++EXPORT_SYMBOL(mips_machgroup);
++
++const char *get_system_type(void)
++{
++ switch (mips_machgroup) {
++ case MACH_GROUP_MT_VM:
++ return "Mikrotik VM";
++ }
++ return "unknown routerboard";
++}
++
++void __init prom_init(void)
++{
++ int argc = fw_arg0;
++ char **argv = (char **) fw_arg1;
++ unsigned char board_type[16];
++
++ unsigned i, offset = 0;
++
++ set_io_port_base(KSEG1);
++
++ memset(board_type, 0, sizeof(board_type));
++
++ /* HZ must be parsed here because otherwise is too late */
++ for (i = 0; (i < argc && argv[i] != NULL); i++) {
++ if (strncmp(argv[i], FREQ_TAG, sizeof(FREQ_TAG) - 1) == 0) {
++ mips_hpt_frequency =
++ simple_strtoul(argv[i] + sizeof(FREQ_TAG) - 1, 0, 10);
++ continue;
++ }
++ if (strncmp(argv[i], BOARD_TAG, sizeof(BOARD_TAG) - 1) == 0) {
++ strncpy(board_type, argv[i] + sizeof(BOARD_TAG) - 1,
++ sizeof(board_type));
++ }
++ offset += snprintf(arcs_cmdline + offset, sizeof(arcs_cmdline) - offset,
++ "%s ", argv[i]);
++ }
++
++ mips_machgroup = MACH_GROUP_MT_VM;
++ mips_machtype = 0;
++}
++
++void __init prom_free_prom_memory(void)
++{
++ unsigned long addr, end;
++ extern char _text;
++
++ /*
++ * Free everything below the kernel itself but leave
++ * the first page reserved for the exception handlers.
++ */
++
++ end = __pa(&_text);
++ addr = PAGE_SIZE;
++
++ while (addr < end) {
++ ClearPageReserved(virt_to_page(__va(addr)));
++ init_page_count(virt_to_page(__va(addr)));
++ free_page((unsigned long)__va(addr));
++ addr += PAGE_SIZE;
++ ++totalram_pages;
++ }
++}
++
++void __init plat_mem_setup(void)
++{
++#ifdef CONFIG_BLK_DEV_INITRD
++ extern int _end;
++ u32 *initrd_header;
++
++ initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
++ if (initrd_header[0] == 0x494E5244) {
++ initrd_start = (unsigned long) (initrd_header + 2);
++ initrd_end = initrd_start + initrd_header[1];
++ }
++#endif
++
++ switch (mips_machgroup) {
++ case MACH_GROUP_MT_VM:
++ rbvm_setup();
++ break;
++ }
++}
++
++void __init plat_time_init(void)
++{
++}
++
++static int __init setup_kmac(char *s)
++{
++ int i, j;
++ unsigned char result, value;
++
++ for (i = 0; i < 6; i++) {
++ if (s[0] == '\0' || s[1] == '\0') return 0;
++ if (i != 5 && s[2] != ':') return 0;
++
++ result = 0;
++ for (j = 0; j < 2; j++) {
++ if (!isxdigit(*s)) return 0;
++
++ value = isdigit(*s) ? *s - '0' :
++ toupper(*s) - 'A' + 10;
++ if (value >= 16) return 0;
++
++ result = result * 16 + value;
++ s++;
++ }
++
++ s++;
++ mips_mac_address[i] = result;
++ }
++
++ return *s == '\0';
++}
++
++__setup("kmac=", setup_kmac);
++
++EXPORT_SYMBOL(mips_mac_address);
++
++unsigned long long sched_clock(void)
++{
++ return read_c0_count() * 1000000000 / mips_hpt_frequency;
++}
+diff -puNrb linux-3.10.49/arch/mips/rb/vm/Makefile linux-3.10.49-minimal/arch/mips/rb/vm/Makefile
+--- linux-3.10.49/arch/mips/rb/vm/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/vm/Makefile 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1 @@
++obj-y := setup.o
+diff -puNrb linux-3.10.49/arch/mips/rb/vm/setup.c linux-3.10.49-minimal/arch/mips/rb/vm/setup.c
+--- linux-3.10.49/arch/mips/rb/vm/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/arch/mips/rb/vm/setup.c 2014-01-11 05:37:12.000000000 +0000
+@@ -0,0 +1,142 @@
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <asm/reboot.h>
++#include <asm/vm.h>
++#include <asm/rb/boards.h>
++
++#define BUF_SIZE 256
++#define BUF_COUNT 4
++
++hypercall(vm_create_queue, 4, unsigned id, unsigned irq,
++ unsigned tx, unsigned rx);
++hypercall(vm_release_queue, 5, unsigned id);
++hypercall(vm_running, 6, void);
++hypercall(vm_setup_irqs, 14, unsigned *irqs, unsigned count);
++
++static volatile struct vdma_descr tx_chain[BUF_COUNT];
++static volatile struct vdma_descr rx_chain[BUF_COUNT];
++static unsigned char tx_buffers[BUF_COUNT][BUF_SIZE];
++static unsigned char rx_buffers[BUF_COUNT][BUF_SIZE];
++
++static unsigned cur_tx;
++static unsigned cur_rx;
++
++static int send_message(const unsigned char *buf, int len)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ /* drop some data if full buffer */
++ while (tx_chain[cur_tx].size & DONE)
++ asm volatile ("wait");
++
++ len = min_t(int, len, BUF_SIZE);
++ memcpy(tx_buffers[cur_tx], buf, len);
++ tx_chain[cur_tx].size = len | DONE;
++
++ cur_tx = (cur_tx + 1) % BUF_COUNT;
++
++ local_irq_restore(flags);
++
++ return len;
++}
++
++static int recv_message(char *buf, int len)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ if (!(rx_chain[cur_rx].size & DONE)) {
++ local_irq_restore(flags);
++ return 0;
++ }
++
++ len = min_t(int, len, rx_chain[cur_rx].size & ~DONE);
++ memcpy(buf, rx_buffers[cur_rx], len);
++
++ rx_chain[cur_rx].size = BUF_SIZE;
++ cur_rx = (cur_rx + 1) % BUF_COUNT;
++
++ local_irq_restore(flags);
++
++ return len;
++}
++
++static irqreturn_t ctrl_interrupt(int irq, void *dev_id)
++{
++ struct task_struct *init;
++ char buf[256];
++ int len;
++
++ len = recv_message(buf, sizeof(buf));
++ if (len <= 0)
++ return IRQ_HANDLED;
++
++ if (strncmp(buf, "restart", len) == 0) {
++ printk("RESTART\n");
++ init = find_task_by_pid_ns(1, &init_pid_ns);
++ if (init)
++ send_sig(SIGINT, init, 1);
++ } else if (strncmp(buf, "halt", len) == 0) {
++ printk("HALT\n");
++ init = find_task_by_pid_ns(1, &init_pid_ns);
++ if (init)
++ send_sig(SIGWINCH, init, 1);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static void rbvm_machine_restart(char *command)
++{
++ char msg[] = "restart";
++
++ send_message(msg, sizeof(msg));
++}
++
++static void rbvm_machine_halt(void)
++{
++ char msg[] = "halt";
++
++ send_message(msg, sizeof(msg));
++}
++
++void __init rbvm_setup(void)
++{
++ extern unsigned long virqs;
++ int i;
++
++ vm_setup_irqs((unsigned *) &virqs, 32);
++
++ for (i = 0; i < BUF_COUNT; ++i) {
++ rx_chain[i].addr = (unsigned) rx_buffers[i];
++ rx_chain[i].size = BUF_SIZE;
++ rx_chain[i].next = (unsigned) &rx_chain[i + 1];
++
++ tx_chain[i].addr = (unsigned) tx_buffers[i];
++ tx_chain[i].size = 0;
++ tx_chain[i].next = (unsigned) &tx_chain[i + 1];
++ }
++ rx_chain[BUF_COUNT - 1].next = (unsigned) &rx_chain[0];
++ tx_chain[BUF_COUNT - 1].next = (unsigned) &tx_chain[0];
++
++ vm_create_queue(0, 0, (unsigned) &tx_chain[0],
++ (unsigned) &rx_chain[0]);
++
++ _machine_restart = rbvm_machine_restart;
++ _machine_halt = rbvm_machine_halt;
++}
++
++int __init init_ctrl_interrupt(void)
++{
++ if (mips_machgroup != MACH_GROUP_MT_VM)
++ return 0;
++
++ if (request_irq(VIRQ_BASE + 0, ctrl_interrupt, 0, "ctrl", (void *) 1))
++ return -EBUSY;
++ return 0;
++
++}
++arch_initcall(init_ctrl_interrupt);
+diff -puNrb linux-3.10.49/drivers/block/loop.c linux-3.10.49-minimal/drivers/block/loop.c
+--- linux-3.10.49/drivers/block/loop.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/drivers/block/loop.c 2014-01-11 07:26:26.000000000 +0000
+@@ -372,6 +372,9 @@ do_lo_receive(struct loop_device *lo,
+ struct file *file;
+ ssize_t retval;
+
++ pgoff_t index;
++ pgoff_t last_index;
++
+ cookie.lo = lo;
+ cookie.page = bvec->bv_page;
+ cookie.offset = bvec->bv_offset;
+@@ -386,6 +389,11 @@ do_lo_receive(struct loop_device *lo,
+ file = lo->lo_backing_file;
+ retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
+
++ /* HACK: try to free up page cache from tripple buffers */
++ index = pos >> PAGE_CACHE_SHIFT;
++ last_index = (pos + bsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++ invalidate_mapping_pages(file->f_mapping, index, last_index);
++
+ return retval;
+ }
+
+diff -puNrb linux-3.10.49/drivers/char/Kconfig linux-3.10.49-minimal/drivers/char/Kconfig
+--- linux-3.10.49/drivers/char/Kconfig 2014-01-11 05:33:54.000000000 +0000
++++ linux-3.10.49-minimal/drivers/char/Kconfig 2014-01-11 07:26:40.000000000 +0000
+@@ -156,6 +156,13 @@ config PPDEV
+ If unsure, say N.
+
+ source "drivers/tty/hvc/Kconfig"
++config HVC_META
++ bool "MetaROUTER Hypervisor Console support"
++ depends on METAROUTER || MIPS_MIKROTIK
++ select HVC_DRIVER
++ select HVC_IRQ
++ default y
++
+
+ config VIRTIO_CONSOLE
+ tristate "Virtio console"
+@@ -606,4 +613,3 @@ config TILE_SROM
+ how to partition a single ROM for multiple purposes.
+
+ endmenu
+-
+diff -puNrb linux-3.10.49/drivers/net/ethernet/Kconfig linux-3.10.49-minimal/drivers/net/ethernet/Kconfig
+--- linux-3.10.49/drivers/net/ethernet/Kconfig 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/drivers/net/ethernet/Kconfig 2014-01-11 07:30:08.000000000 +0000
+@@ -85,6 +85,11 @@ config LANTIQ_ETOP
+ ---help---
+ Support for the MII0 inside the Lantiq SoC
+
++config MT_VETH
++ bool "MetaROUTER Virtual Ethernet support"
++ depends on METAROUTER || MIPS_MIKROTIK
++ default y
++
+ source "drivers/net/ethernet/marvell/Kconfig"
+ source "drivers/net/ethernet/mellanox/Kconfig"
+ source "drivers/net/ethernet/micrel/Kconfig"
+diff -puNrb linux-3.10.49/drivers/net/ethernet/Makefile linux-3.10.49-minimal/drivers/net/ethernet/Makefile
+--- linux-3.10.49/drivers/net/ethernet/Makefile 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/drivers/net/ethernet/Makefile 2014-01-11 07:30:34.000000000 +0000
+@@ -35,6 +35,7 @@ obj-$(CONFIG_NET_VENDOR_XSCALE) += xscal
+ obj-$(CONFIG_IP1000) += icplus/
+ obj-$(CONFIG_JME) += jme.o
+ obj-$(CONFIG_KORINA) += korina.o
++obj-$(CONFIG_MT_VETH) += mtveth.o
+ obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
+ obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
+ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
+diff -puNrb linux-3.10.49/drivers/net/ethernet/mtveth.c linux-3.10.49-minimal/drivers/net/ethernet/mtveth.c
+--- linux-3.10.49/drivers/net/ethernet/mtveth.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/drivers/net/ethernet/mtveth.c 2014-01-11 07:30:48.000000000 +0000
+@@ -0,0 +1,284 @@
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/interrupt.h>
++#include <asm/vm.h>
++
++#define MAX_IFACES 8
++
++#define TXBUF_COUNT 1024
++#define RXBUF_COUNT 128
++
++#define RXBUF_SIZE 10300
++
++extern int vm_create_queue(unsigned id, unsigned irq,
++ unsigned tx, unsigned rx);
++extern int vm_release_queue(unsigned id);
++
++#define CMD_NEWIFACE 0
++#define CMD_DELIFACE 1
++
++struct ctrl_msg {
++ unsigned cmd;
++ unsigned short id;
++ unsigned char hwaddr[6];
++} __attribute__((packed));
++
++static volatile struct vdma_descr rx_descr[RXBUF_COUNT];
++static volatile struct vdma_descr tx_descr[TXBUF_COUNT];
++static struct sk_buff *rx_skbs[RXBUF_COUNT];
++static struct sk_buff *tx_skbs[TXBUF_COUNT];
++
++static unsigned last_tx;
++static atomic_t cur_tx;
++static unsigned cur_rx;
++static unsigned max_tx;
++
++static struct net_device *devs[MAX_IFACES];
++
++struct veth_private {
++ unsigned id;
++ atomic_t pending_tx;
++};
++
++static void ctrl_receiver(struct work_struct *work);
++
++static struct sk_buff_head ctrl_queue;
++static DECLARE_WORK(ctrl_work, ctrl_receiver);
++
++static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct veth_private *veth = netdev_priv(dev);
++ unsigned cur = atomic_read(&cur_tx) % TXBUF_COUNT;
++
++ if (skb_padto(skb, ETH_ZLEN))
++ return NETDEV_TX_OK;
++
++ if (tx_descr[cur].size & DONE) {
++ dev->stats.tx_dropped++;
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++
++ if (skb_headroom(skb) < 2) {
++ struct sk_buff *s = skb;
++ skb = skb_realloc_headroom(s, 2);
++ dev_kfree_skb_any(s);
++ } else {
++ skb = skb_unshare(skb, GFP_ATOMIC);
++ }
++ if (!skb) {
++ dev->stats.tx_dropped++;
++ return NETDEV_TX_OK;
++ }
++ *(u16 *) skb_push(skb, 2) = veth->id;
++
++ dev->stats.tx_packets++;
++ dev->stats.tx_bytes += skb->len;
++
++ tx_descr[cur].addr = (unsigned) skb->data;
++ tx_descr[cur].size = skb->len | DONE;
++
++ if (tx_skbs[cur]) {
++ /* should not happen */
++ dev->stats.tx_dropped++;
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_BUSY;
++ }
++
++ tx_skbs[cur] = skb;
++ atomic_add(1, &cur_tx);
++
++ if (atomic_add_return(1, &veth->pending_tx) >= max_tx) {
++ netif_stop_queue(dev);
++
++ /* in case we got rewaken right before stop */
++ if (atomic_read(&veth->pending_tx) < max_tx)
++ netif_wake_queue(dev);
++ }
++
++ return 0;
++}
++
++static irqreturn_t veth_interrupt(int irq, void *dev_id)
++{
++ unsigned cur;
++
++ while (last_tx != atomic_read(&cur_tx)) {
++ unsigned last = last_tx % TXBUF_COUNT;
++ struct net_device *dev;
++ struct veth_private *veth;
++
++ if (tx_descr[last].size & DONE)
++ break;
++
++ dev = tx_skbs[last]->dev;
++ veth = netdev_priv(dev);
++ dev_kfree_skb_irq(tx_skbs[last]);
++ tx_skbs[last] = NULL;
++
++ ++last_tx;
++
++ if (atomic_sub_return(1, &veth->pending_tx) < max_tx)
++ netif_wake_queue(dev);
++ }
++
++ cur = cur_rx % RXBUF_COUNT;
++ while ((rx_descr[cur].size & DONE)) {
++ struct sk_buff *skb = rx_skbs[cur];
++ struct net_device *dev;
++ unsigned id;
++
++ skb_put(skb, rx_descr[cur].size & ~DONE);
++ if (skb->len < 2) {
++ dev_kfree_skb_irq(skb);
++ goto next;
++ }
++
++ id = *(u16 *) skb->data;
++ skb_pull(skb, 2);
++
++ if (id == 0) {
++ __skb_queue_tail(&ctrl_queue, skb);
++ schedule_work(&ctrl_work);
++ goto next;
++ }
++ if (id >= MAX_IFACES || !devs[id]) {
++ dev_kfree_skb_irq(skb);
++ goto next;
++ }
++ dev = devs[id];
++
++ skb->dev = dev;
++ skb->protocol = eth_type_trans(skb, dev);
++
++ dev->last_rx = jiffies;
++ ++dev->stats.rx_packets;
++ dev->stats.rx_bytes += skb->len;
++
++ netif_rx(skb);
++
++ next:
++ skb = dev_alloc_skb(RXBUF_SIZE);
++ rx_skbs[cur] = skb;
++ if (skb) {
++ rx_descr[cur].addr = (unsigned) skb->data;
++ rx_descr[cur].size = RXBUF_SIZE;
++ } else {
++ rx_descr[cur].size = 0;
++ }
++
++ ++cur_rx;
++ cur = cur_rx % RXBUF_COUNT;
++ }
++
++ return IRQ_HANDLED;
++}
++
++static const struct net_device_ops veth_netdev_ops = {
++ .ndo_start_xmit = veth_xmit,
++};
++
++static int veth_alloc_dev(unsigned id, const unsigned char *hwaddr)
++{
++ struct veth_private *veth;
++ struct net_device *dev;
++ int err;
++
++ //SET_NETDEV_DEV(dev, &pdev->dev);
++ //platform_set_drvdata(pdev, dev);
++
++ dev = alloc_etherdev(sizeof(struct veth_private));
++ if (!dev)
++ return -ENOMEM;
++
++ veth = netdev_priv(dev);
++ veth->id = id;
++ atomic_set(&veth->pending_tx, 1);
++ memcpy(dev->dev_addr, hwaddr, 6);
++ dev->netdev_ops = &veth_netdev_ops;
++
++ err = register_netdev(dev);
++ if (err < 0) {
++ printk("cannot register net device %u\n", err);
++ goto netdev_err;
++ }
++
++ devs[id] = dev;
++ return 0;
++
++ netdev_err:
++ free_netdev(dev);
++ return err;
++}
++
++static int recv_ctrl_msg(struct sk_buff *skb)
++{
++ struct ctrl_msg *msg = (struct ctrl_msg *) skb->data;
++
++ if (skb->len < sizeof(struct ctrl_msg))
++ return -EINVAL;
++
++ if (msg->cmd == CMD_NEWIFACE) {
++ if (msg->id >= MAX_IFACES || devs[msg->id])
++ return -EBUSY;
++
++ veth_alloc_dev(msg->id, msg->hwaddr);
++ return 0;
++ } else if (msg->cmd == CMD_DELIFACE) {
++ struct net_device *dev;
++
++ if (msg->id >= MAX_IFACES || !devs[msg->id])
++ return -EINVAL;
++
++ dev = devs[msg->id];
++ devs[msg->id] = NULL;
++
++ unregister_netdev(dev);
++ }
++ return -EINVAL;
++}
++
++static void ctrl_receiver(struct work_struct *work)
++{
++ struct sk_buff *skb;
++
++ while ((skb = skb_dequeue(&ctrl_queue)))
++ recv_ctrl_msg(skb);
++}
++
++int veth_init(void)
++{
++ unsigned i;
++
++ if (vm_running() != 0)
++ return 0;
++
++ skb_queue_head_init(&ctrl_queue);
++
++ if (request_irq(get_virq_nr(3), veth_interrupt, IRQF_SHARED,
++ "veth", (void *) 1))
++ return -EBUSY;
++
++ for (i = 0; i < TXBUF_COUNT; ++i) {
++ tx_descr[i].addr = 0;
++ tx_descr[i].size = 0;
++ tx_descr[i].next = (unsigned) &tx_descr[i + 1];
++ }
++ for (i = 0; i < RXBUF_COUNT; ++i) {
++ rx_skbs[i] = dev_alloc_skb(RXBUF_SIZE);
++ rx_descr[i].addr = (unsigned) rx_skbs[i]->data;
++ rx_descr[i].size = RXBUF_SIZE;
++ rx_descr[i].next = (unsigned) &rx_descr[i + 1];
++ }
++ tx_descr[TXBUF_COUNT - 1].next = (unsigned) &tx_descr[0];
++ rx_descr[RXBUF_COUNT - 1].next = (unsigned) &rx_descr[0];
++
++ vm_create_queue(3, 3,
++ (unsigned) &tx_descr[0], (unsigned) &rx_descr[0]);
++
++ max_tx = TXBUF_COUNT / MAX_IFACES;
++
++ return 0;
++}
++module_init(veth_init);
+diff -puNrb linux-3.10.49/drivers/tty/hvc/hvc_console.c linux-3.10.49-minimal/drivers/tty/hvc/hvc_console.c
+--- linux-3.10.49/drivers/tty/hvc/hvc_console.c 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/drivers/tty/hvc/hvc_console.c 2014-01-11 07:33:14.000000000 +0000
+@@ -588,7 +588,7 @@ static int hvc_chars_in_buffer(struct tt
+ * there has been no input for some time.
+ */
+ #define MIN_TIMEOUT (10)
+-#define MAX_TIMEOUT (2000)
++#define MAX_TIMEOUT (200)
+ static u32 timeout = MIN_TIMEOUT;
+
+ #define HVC_POLL_READ 0x00000001
+diff -puNrb linux-3.10.49/drivers/tty/hvc/hvc_meta.c linux-3.10.49-minimal/drivers/tty/hvc/hvc_meta.c
+--- linux-3.10.49/drivers/tty/hvc/hvc_meta.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/drivers/tty/hvc/hvc_meta.c 2014-01-11 07:33:36.000000000 +0000
+@@ -0,0 +1,135 @@
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++#include <linux/slab.h>
++#include <asm/vm.h>
++#include <asm/irq.h>
++#include "hvc_console.h"
++
++extern int vm_create_queue(unsigned id, unsigned irq,
++ unsigned tx, unsigned rx);
++extern int vm_release_queue(unsigned id);
++
++#define BUF_SIZE 4096
++
++static volatile struct vdma_descr tx_descr;
++static volatile struct vdma_descr rx_descr;
++
++static unsigned rx_offset;
++static DEFINE_SPINLOCK(lock);
++
++static int put_chars(u32 vtermno, const char *buf, int count)
++{
++ unsigned long flags;
++ int i;
++
++ spin_lock_irqsave(&lock, flags);
++
++#ifdef __powerpc__
++ for (i = 0; i < 2000000; ++i) {
++#else
++ for (i = 0; i < 2; ++i) {
++#endif
++ unsigned size = xchg(&tx_descr.size, 0);
++
++ if (!(size & DONE)) {
++ count = min(count, BUF_SIZE);
++ memcpy((char *) tx_descr.addr, buf, count);
++ tx_descr.size = count | DONE;
++
++ spin_unlock_irqrestore(&lock, flags);
++ return count;
++ }
++
++ if (size == (BUF_SIZE | DONE)) {
++ if (i == 0) {
++ tx_descr.size = size;
++ hc_yield();
++ continue;
++ } else {
++ unsigned drop = BUF_SIZE / 4;
++ size = BUF_SIZE - drop;
++ memcpy((char *) tx_descr.addr,
++ (char *) tx_descr.addr + drop,
++ size);
++ }
++ }
++
++ size &= ~DONE;
++ count = min(BUF_SIZE - (int) size, count);
++ memcpy((char *) tx_descr.addr + size, buf, count);
++ tx_descr.size = (size + count) | DONE;
++
++ spin_unlock_irqrestore(&lock, flags);
++ return count;
++ }
++
++ spin_unlock_irqrestore(&lock, flags);
++ return 0;
++}
++
++static int get_chars(u32 vtermno, char *buf, int count)
++{
++ unsigned long flags;
++ unsigned size;
++
++ spin_lock_irqsave(&lock, flags);
++
++ if (!(rx_descr.size & DONE)) {
++ spin_unlock_irqrestore(&lock, flags);
++ return -EAGAIN;
++ }
++
++ size = (rx_descr.size & ~DONE) - rx_offset;
++ count = min(count, (int) size);
++
++ memcpy(buf, (char *) rx_descr.addr + rx_offset, count);
++
++ if (count == size) {
++ rx_descr.size = BUF_SIZE;
++ rx_offset = 0;
++ } else {
++ rx_offset += count;
++ }
++
++ spin_unlock_irqrestore(&lock, flags);
++ return count;
++}
++
++static struct hv_ops cons = {
++ .put_chars = put_chars,
++ .get_chars = get_chars,
++ .notifier_add = notifier_add_irq,
++ .notifier_del = notifier_del_irq,
++};
++
++static int __init cons_init(void)
++{
++ if (vm_running() != 0)
++ return 0;
++
++ rx_descr.addr = (unsigned) kmalloc(BUF_SIZE, GFP_KERNEL);
++ rx_descr.size = BUF_SIZE;
++ rx_descr.next = (unsigned) &rx_descr;
++
++ tx_descr.addr = (unsigned) kmalloc(BUF_SIZE, GFP_KERNEL);
++ tx_descr.size = 0;
++ tx_descr.next = (unsigned) &tx_descr;
++
++ vm_create_queue(1, 1,
++ (unsigned) &tx_descr, (unsigned) &rx_descr);
++
++ return hvc_instantiate(0, 0, &cons);
++}
++console_initcall(cons_init);
++
++int vm_init(void)
++{
++ if (vm_running() == 0)
++ hvc_alloc(0, get_virq_nr(1), &cons, 256);
++ return 0;
++}
++module_init(vm_init);
+diff -puNrb linux-3.10.49/drivers/tty/hvc/Makefile linux-3.10.49-minimal/drivers/tty/hvc/Makefile
+--- linux-3.10.49/drivers/tty/hvc/Makefile 2012-06-01 08:16:13.000000000 +0100
++++ linux-3.10.49-minimal/drivers/tty/hvc/Makefile 2014-01-11 07:33:59.000000000 +0000
+@@ -8,6 +8,7 @@ obj-$(CONFIG_HVC_BEAT) += hvc_beat.o
+ obj-$(CONFIG_HVC_DRIVER) += hvc_console.o
+ obj-$(CONFIG_HVC_IRQ) += hvc_irq.o
+ obj-$(CONFIG_HVC_XEN) += hvc_xen.o
++obj-$(CONFIG_HVC_META) += hvc_meta.o
+ obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o
+ obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o
+ obj-$(CONFIG_HVC_BFIN_JTAG) += hvc_bfin_jtag.o
+diff -puNrb linux-3.10.49/fs/Kconfig linux-3.10.49-minimal/fs/Kconfig
+--- linux-3.10.49/fs/Kconfig 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/fs/Kconfig 2014-01-11 07:36:36.000000000 +0000
+@@ -217,6 +217,7 @@ source "fs/pstore/Kconfig"
+ source "fs/exofs/Kconfig"
+ source "fs/f2fs/Kconfig"
+ source "fs/efivarfs/Kconfig"
++source "fs/metafs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+
+diff -puNrb linux-3.10.49/fs/Makefile linux-3.10.49-minimal/fs/Makefile
+--- linux-3.10.49/fs/Makefile 2014-01-11 05:33:53.000000000 +0000
++++ linux-3.10.49-minimal/fs/Makefile 2014-01-11 07:37:06.000000000 +0000
+@@ -62,6 +62,7 @@ obj-$(CONFIG_PROFILING) += dcookies.o
+ obj-$(CONFIG_DLM) += dlm/
+
+ # Do not add any filesystems before this line
++obj-$(CONFIG_META_FS) += metafs/
+ obj-$(CONFIG_FSCACHE) += fscache/
+ obj-$(CONFIG_REISERFS_FS) += reiserfs/
+ obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3
+diff -puNrb linux-3.10.49/fs/metafs/inode.c linux-3.10.49-minimal/fs/metafs/inode.c
+--- linux-3.10.49/fs/metafs/inode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/fs/metafs/inode.c 2014-01-11 05:37:13.000000000 +0000
+@@ -0,0 +1,909 @@
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/statfs.h>
++#include <linux/pagemap.h>
++#include <linux/namei.h>
++#include <linux/slab.h>
++#include <linux/mount.h>
++#include <asm/vm.h>
++
++#define CMD_GETINODE 0
++#define CMD_RELEASE_INODE 1
++#define CMD_LOOKUP 2
++#define CMD_READPAGE 3
++#define CMD_READLINK 4
++#define CMD_READDIR 5
++#define CMD_WRITEPAGE 6
++#define CMD_CREATE 7
++#define CMD_UNLINK 8
++#define CMD_SYMLINK 9
++#define CMD_RENAME 10
++#define CMD_SETINODE 11
++#define CMD_STATFS 12
++#define CMD_HLINK 13
++#define CMD_FSYNC 14
++
++struct hptime {
++ unsigned sec;
++ unsigned nsec;
++};
++
++struct getinode_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++} __attribute__((packed));
++
++struct inode_rep {
++ int status;
++ unsigned long long ino;
++ unsigned long long size;
++ unsigned mode;
++ unsigned nlink;
++ unsigned uid;
++ unsigned gid;
++ unsigned rdev;
++ struct hptime atime;
++ struct hptime mtime;
++ struct hptime ctime;
++ unsigned long blksize;
++ unsigned long long blocks;
++} __attribute__((packed));
++
++struct setinode_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++ unsigned long long size;
++ unsigned mode;
++ unsigned uid;
++ unsigned gid;
++ unsigned rdev;
++} __attribute__((packed));
++
++struct lookup_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long parent_ino;
++ char name[0];
++} __attribute__((packed));
++
++struct create_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long parent_ino;
++ unsigned mode;
++ unsigned dev;
++ char name[0];
++} __attribute__((packed));
++
++struct unlink_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long parent_ino;
++ char name[0];
++} __attribute__((packed));
++
++struct symlink_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long parent_ino;
++ unsigned namelen;
++ char names[0];
++} __attribute__((packed));
++
++struct hlink_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long parent_ino;
++ unsigned long long ino;
++ char name[0];
++} __attribute__((packed));
++
++struct rename_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long old_parent_ino;
++ unsigned long long new_parent_ino;
++ unsigned old_namelen;
++ char names[0];
++} __attribute__((packed));
++
++struct readpage_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++ unsigned long long offset;
++ unsigned size;
++} __attribute__((packed));
++
++struct writepage_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++ unsigned long long offset;
++ unsigned size;
++} __attribute__((packed));
++
++struct fsync_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++} __attribute__((packed));
++
++struct readlink_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++} __attribute__((packed));
++
++struct readlink_rep {
++ int status;
++ char target[0];
++} __attribute__((packed));
++
++struct readdir_req {
++ unsigned short id;
++ unsigned short cmd;
++ unsigned long long ino;
++ unsigned long long offset;
++ unsigned size;
++} __attribute__((packed));
++
++struct dirnode {
++ unsigned long long ino;
++ unsigned long long offset;
++ unsigned char type;
++ unsigned short len;
++ char name[0];
++} __attribute__((packed));
++
++struct readdir_rep {
++ int status;
++ unsigned long long offset;
++ struct dirnode entries[0];
++} __attribute__((packed));
++
++struct statfs_req {
++ unsigned short id;
++ unsigned short cmd;
++} __attribute__((packed));
++
++struct statfs_rep {
++ int status;
++ unsigned blocks;
++ unsigned bfree;
++} __attribute__((packed));
++
++#define BUF_COUNT 16
++
++extern int vm_create_queue(unsigned id, unsigned irq,
++ unsigned tx, unsigned rx);
++extern int vm_release_queue(unsigned id);
++
++static volatile struct vdma_descr rx_descr[BUF_COUNT];
++static volatile struct vdma_descr tx_descr[BUF_COUNT];
++
++#define MFS_ID(sb) ((unsigned) sb->s_fs_info)
++
++
++static void mfs_update_inode(struct inode *i, struct inode_rep *rep);
++static struct inode *mfs_new_inode(struct super_block *sb,
++ struct inode_rep *rep);
++
++static void start_new_request(unsigned *tx_idx, unsigned tx_slots,
++ unsigned *rx_idx, unsigned rx_slots)
++{
++ static DEFINE_MUTEX(mfs_lock);
++ static unsigned cur_tx;
++ static unsigned cur_rx;
++
++ mutex_lock(&mfs_lock);
++
++ *tx_idx = cur_tx;
++ cur_tx += tx_slots;
++
++ *rx_idx = cur_rx;
++ cur_rx += rx_slots;
++
++ mutex_unlock(&mfs_lock);
++}
++
++static void prepare_receive(unsigned idx, void *resp, unsigned rp_size)
++{
++ idx = idx & (BUF_COUNT - 1);
++
++ rx_descr[idx].addr = (unsigned) resp;
++ rx_descr[idx].size = rp_size;
++}
++
++static void post_request(unsigned idx, const void *req, unsigned rq_size)
++{
++ idx = idx & (BUF_COUNT - 1);
++
++ while (tx_descr[idx].size & DONE) {
++ hc_yield();
++ }
++
++ tx_descr[idx].addr = (unsigned) req;
++ tx_descr[idx].size = rq_size | DONE;
++}
++
++static unsigned wait_for_reply(unsigned idx)
++{
++ idx = idx & (BUF_COUNT - 1);
++
++ while (!(rx_descr[idx].size & DONE)) {
++ hc_yield();
++ }
++ return rx_descr[idx].size & ~(PAGE_MASK<<1);
++}
++
++static unsigned send_request(const void *req, unsigned rq_size,
++ void *resp, unsigned rp_size)
++{
++ unsigned tx;
++ unsigned rx;
++
++ start_new_request(&tx, 1, &rx, 1);
++ prepare_receive(rx, resp, rp_size);
++ post_request(tx, req, rq_size);
++ return wait_for_reply(rx);
++}
++
++static struct kmem_cache *mfs_inode_cachep;
++
++static struct inode *mfs_alloc_inode(struct super_block *sb)
++{
++ return kmem_cache_alloc(mfs_inode_cachep, GFP_KERNEL);
++}
++
++static void mfs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(mfs_inode_cachep, inode);
++}
++
++static struct dentry *mfs_lookup(struct inode *dir,
++ struct dentry *dentry, unsigned int dummy)
++{
++ unsigned size = sizeof(struct lookup_req) + dentry->d_name.len;
++ unsigned char buf[size];
++ struct lookup_req *req = (struct lookup_req *) buf;
++ struct inode_rep rep;
++ struct inode *inode = NULL;
++ struct dentry *res = NULL;
++ unsigned ret;
++
++ req->id = MFS_ID(dir->i_sb);
++ req->cmd = CMD_LOOKUP;
++ req->parent_ino = dir->i_ino;
++ memcpy(req->name, dentry->d_name.name, dentry->d_name.len);
++
++ rep.status = -EINVAL;
++ ret = send_request(req, size, &rep, sizeof(rep));
++ if (ret == sizeof(rep) && rep.status == 0)
++ inode = mfs_new_inode(dir->i_sb, &rep);
++ d_add(dentry, inode);
++ return res;
++}
++
++static int mfs_create_file(struct inode *dir, struct dentry *dentry,
++ int mode, dev_t dev)
++{
++ unsigned size = sizeof(struct create_req) + dentry->d_name.len;
++ unsigned char buf[size];
++ struct create_req *req = (struct create_req *) buf;
++ struct inode_rep rep;
++ struct inode *inode = NULL;
++ unsigned ret;
++
++ req->id = MFS_ID(dir->i_sb);
++ req->cmd = CMD_CREATE;
++ req->parent_ino = dir->i_ino;
++ req->mode = mode;
++ req->dev = (unsigned) dev;
++ memcpy(req->name, dentry->d_name.name, dentry->d_name.len);
++
++ rep.status = -EINVAL;
++ ret = send_request(req, size, &rep, sizeof(rep));
++ if (ret < sizeof(rep))
++ return rep.status;
++
++ inode = mfs_new_inode(dir->i_sb, &rep);
++ d_instantiate(dentry, inode);
++ return 0;
++}
++
++static int mfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++ bool dummy)
++{
++ return mfs_create_file(dir, dentry, mode, MKDEV(0, 0));
++}
++
++static int mfs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ unsigned size = sizeof(struct unlink_req) + dentry->d_name.len;
++ unsigned char buf[size];
++ struct unlink_req *req = (struct unlink_req *) buf;
++ int err = -EINVAL;
++
++ req->id = MFS_ID(dir->i_sb);
++ req->cmd = CMD_UNLINK;
++ req->parent_ino = dir->i_ino;
++ memcpy(req->name, dentry->d_name.name, dentry->d_name.len);
++
++ send_request(req, size, &err, sizeof(err));
++ return err;
++}
++
++static int mfs_symlink(struct inode *dir, struct dentry *dentry,
++ const char *target)
++{
++ unsigned tlen = strlen(target);
++ unsigned size = sizeof(struct symlink_req) + dentry->d_name.len + tlen;
++ unsigned char buf[size];
++ struct symlink_req *req = (struct symlink_req *) buf;
++ struct inode_rep rep;
++ struct inode *inode = NULL;
++ unsigned ret;
++
++ req->id = MFS_ID(dir->i_sb);
++ req->cmd = CMD_SYMLINK;
++ req->parent_ino = dir->i_ino;
++ req->namelen = dentry->d_name.len;
++ memcpy(req->names, dentry->d_name.name, dentry->d_name.len);
++ memcpy(req->names + req->namelen, target, tlen);
++
++ rep.status = -EINVAL;
++ ret = send_request(req, size, &rep, sizeof(rep));
++ if (ret < sizeof(rep))
++ return rep.status;
++
++ inode = mfs_new_inode(dir->i_sb, &rep);
++ d_instantiate(dentry, inode);
++ return 0;
++}
++
++static int mfs_link(struct dentry *old_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ unsigned size = sizeof(struct hlink_req) + dentry->d_name.len;
++ unsigned char buf[size];
++ struct hlink_req *req = (struct hlink_req *) buf;
++ struct inode_rep rep;
++ unsigned ret;
++
++ req->id = MFS_ID(dir->i_sb);
++ req->cmd = CMD_HLINK;
++ req->parent_ino = dir->i_ino;
++ req->ino = old_dentry->d_inode->i_ino;
++ memcpy(req->name, dentry->d_name.name, dentry->d_name.len);
++
++ rep.status = -EINVAL;
++ ret = send_request(req, size, &rep, sizeof(rep));
++ if (ret < sizeof(rep))
++ return rep.status;
++
++ mfs_update_inode(old_dentry->d_inode, &rep);
++
++ atomic_inc(&old_dentry->d_inode->i_count);
++ d_instantiate(dentry, old_dentry->d_inode);
++ return 0;
++}
++
++static int mfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++{
++ return mfs_create_file(dir, dentry, mode | S_IFDIR, MKDEV(0, 0));
++}
++
++static int mfs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ return mfs_unlink(dir, dentry);
++}
++
++static int mfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
++ dev_t rdev) {
++ return mfs_create_file(dir, dentry, mode, rdev);
++}
++
++static int mfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ unsigned size = sizeof(struct rename_req) +
++ old_dentry->d_name.len + new_dentry->d_name.len;
++ unsigned char buf[size];
++ struct rename_req *req = (struct rename_req *) buf;
++ int err = -EINVAL;
++
++ req->id = MFS_ID(old_dir->i_sb);
++ req->cmd = CMD_RENAME;
++ req->old_parent_ino = old_dir->i_ino;
++ req->new_parent_ino = new_dir->i_ino;
++ req->old_namelen = old_dentry->d_name.len;
++ memcpy(req->names, old_dentry->d_name.name, old_dentry->d_name.len);
++ memcpy(req->names + req->old_namelen,
++ new_dentry->d_name.name, new_dentry->d_name.len);
++
++ send_request(req, size, &err, sizeof(err));
++ return err;
++}
++
++static int mfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ struct readdir_req req;
++ struct readdir_rep *rep;
++ struct dirnode *dn;
++ unsigned len;
++ int res = -EINVAL;
++
++ rep = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (!rep)
++ return -ENOMEM;
++
++ req.id = MFS_ID(file->f_dentry->d_inode->i_sb);
++ req.cmd = CMD_READDIR;
++ req.ino = file->f_dentry->d_inode->i_ino;
++ req.offset = file->f_pos;
++ req.size = PAGE_SIZE;
++
++ len = send_request(&req, sizeof(req), rep, PAGE_SIZE);
++ if (len <= sizeof(*rep)) {
++ if (len >= sizeof(int))
++ res = rep->status;
++ goto eod;
++ }
++
++ dn = rep->entries;
++ res = 0;
++ while ((char *) dn + sizeof(struct dirnode) < (char *) rep + len) {
++ if ((char *) dn + dn->len > (char *) rep + len)
++ break;
++ if (filldir(dirent, dn->name, dn->len - sizeof(struct dirnode),
++ dn->offset, dn->ino, dn->type) < 0)
++ break;
++ ++res;
++ dn = (struct dirnode *) ((unsigned char *) dn + dn->len);
++ }
++ file->f_pos = rep->offset;
++
++ eod:
++ kfree(rep);
++ return res;
++}
++
++static int mfs_readpage(struct file *file, struct page *page)
++{
++ struct readpage_req req;
++ void *buf;
++ int res = -EIO;
++ unsigned len;
++ unsigned tx;
++ unsigned rx;
++
++ buf = kmap(page);
++ if (!buf)
++ goto err_out;
++
++ req.id = MFS_ID(file->f_dentry->d_inode->i_sb);
++ req.cmd = CMD_READPAGE;
++ req.ino = file->f_dentry->d_inode->i_ino;
++ req.offset = page_offset(page);
++ req.size = PAGE_SIZE;
++
++ start_new_request(&tx, 1, &rx, 2);
++ prepare_receive(rx, &res, sizeof(res));
++ prepare_receive(rx + 1, buf, PAGE_SIZE);
++ post_request(tx, &req, sizeof(req));
++
++ if (wait_for_reply(rx) < sizeof(res)) {
++ res = -EINVAL;
++ goto err_out;
++ }
++ if (res) {
++ memset(buf, 0, PAGE_SIZE);
++ SetPageError(page);
++ goto err_buf;
++ }
++ len = wait_for_reply(rx + 1);
++
++ memset(buf + len, 0, PAGE_SIZE - len);
++ SetPageUptodate(page);
++
++ err_buf:
++ kunmap(page);
++ flush_dcache_page(page);
++ err_out:
++ unlock_page(page);
++ return res;
++}
++
++static int mfs_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{
++ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
++
++ *pagep = grab_cache_page_write_begin(mapping, index, flags);
++ if (!*pagep)
++ return -ENOMEM;
++
++ // FIXME: do prereading
++
++ return 0;
++}
++
++static int mfs_write_end(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned blen, unsigned copied,
++ struct page *page, void *fsdata)
++{
++ struct inode *i = file->f_dentry->d_inode;
++ struct writepage_req req;
++ void *buf;
++ int len = -EFAULT;
++ unsigned tx;
++ unsigned rx;
++ unsigned size;
++
++ flush_dcache_page(page);
++
++ buf = kmap(page);
++ if (!buf)
++ return -EINVAL;
++
++ req.id = MFS_ID(i->i_sb);
++ req.cmd = CMD_WRITEPAGE;
++ req.ino = file->f_dentry->d_inode->i_ino;
++ req.offset = pos;
++ req.size = blen;
++
++ start_new_request(&tx, 2, &rx, 1);
++ prepare_receive(rx, &len, sizeof(len));
++ post_request(tx, &req, sizeof(req));
++ post_request(tx + 1, buf + (pos & (PAGE_CACHE_SIZE - 1)), blen);
++ wait_for_reply(rx);
++
++ if (len >= 0) {
++ if (len != blen) {
++ SetPageError(page);
++ ClearPageUptodate(page);
++ } else {
++ SetPageUptodate(page);
++ }
++
++ size = req.offset + len;
++ if (size > i_size_read(i)) i_size_write(i, size);
++ }
++
++ kunmap(page);
++ unlock_page(page);
++ page_cache_release(page);
++ return len;
++}
++
++static int mfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
++{
++ struct inode *inode = file->f_mapping->host;
++ struct fsync_req req;
++ int err;
++
++ err = filemap_write_and_wait_range(inode->i_mapping, start, end);
++ if (err)
++ return err;
++
++ req.id = MFS_ID(file->f_mapping->host->i_sb);
++ req.cmd = CMD_FSYNC;
++ req.ino = file->f_mapping->host->i_ino;
++
++ err = -EINVAL;
++ send_request(&req, sizeof(req), &err, sizeof(err));
++ return err;
++}
++
++static void *mfs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ struct readlink_req req;
++ struct readlink_rep *rep;
++ int len;
++
++ rep = kmalloc(256, GFP_KERNEL);
++ if (!rep)
++ return ERR_PTR(-ENOMEM);
++
++ req.id = MFS_ID(dentry->d_inode->i_sb);
++ req.cmd = CMD_READLINK;
++ req.ino = dentry->d_inode->i_ino;
++
++ rep->status = -EINVAL;
++ len = send_request(&req, sizeof(req), rep, 255);
++ if (len < sizeof(*rep) + 1) {
++ kfree(rep);
++ return ERR_PTR(rep->status);
++ }
++
++ *((char *) rep + len) = 0;
++ nd_set_link(nd, rep->target);
++ return NULL;
++}
++
++static void mfs_put_link(struct dentry *direntry,
++ struct nameidata *nd, void *cookie)
++{
++ char *p = nd_get_link(nd);
++
++ if (!IS_ERR(p))
++ kfree(p - sizeof(struct readlink_rep));
++}
++
++static int mfs_setattr(struct dentry *dentry, struct iattr *attr)
++{
++ struct setinode_req req;
++ struct inode_rep rep;
++ struct inode *i = dentry->d_inode;
++ unsigned ia = attr->ia_valid;
++ unsigned len;
++
++ req.id = MFS_ID(i->i_sb);
++ req.cmd = CMD_SETINODE;
++ req.ino = i->i_ino;
++ req.mode = ia & ATTR_MODE ? attr->ia_mode : i->i_mode;
++ req.uid = ia & ATTR_UID ? attr->ia_uid.val : i->i_uid.val;
++ req.gid = ia & ATTR_GID ? attr->ia_gid.val : i->i_gid.val;
++ req.size = ia & ATTR_SIZE ? attr->ia_size : i->i_size;
++
++ len = send_request(&req, sizeof(req), &rep, sizeof(rep));
++ if (len < sizeof(rep))
++ return -EINVAL;
++
++ if (rep.status)
++ return rep.status;
++
++ mfs_update_inode(i, &rep);
++ return 0;
++}
++
++static const struct file_operations mfs_dir_fops = {
++ .read = generic_read_dir,
++ .readdir = mfs_readdir,
++};
++
++static const struct inode_operations mfs_dir_ops = {
++ .lookup = mfs_lookup,
++ .create = mfs_create,
++ .link = mfs_link,
++ .unlink = mfs_unlink,
++ .symlink = mfs_symlink,
++ .mkdir = mfs_mkdir,
++ .rmdir = mfs_rmdir,
++ .mknod = mfs_mknod,
++ .rename = mfs_rename,
++ .setattr = mfs_setattr,
++};
++
++static const struct inode_operations mfs_file_ops = {
++ .setattr = mfs_setattr,
++};
++
++static const struct file_operations mfs_fops = {
++ .llseek = generic_file_llseek,
++ .read = do_sync_read,
++ .write = do_sync_write,
++ .aio_read = generic_file_aio_read,
++ .aio_write = generic_file_aio_write,
++ .mmap = generic_file_readonly_mmap,
++ .splice_read = generic_file_splice_read,
++ .fsync = mfs_fsync,
++};
++
++static const struct address_space_operations mfs_aops = {
++ .readpage = mfs_readpage,
++ .write_begin = mfs_write_begin,
++ .write_end = mfs_write_end,
++};
++
++static const struct inode_operations mfs_link_ops = {
++ .readlink = generic_readlink,
++ .follow_link = mfs_follow_link,
++ .put_link = mfs_put_link,
++ .setattr = mfs_setattr,
++};
++
++static void mfs_update_inode(struct inode *i, struct inode_rep *rep)
++{
++ i->i_ino = rep->ino;
++ i->i_mode = rep->mode;
++ set_nlink(i, rep->nlink);
++ i->i_uid.val = rep->uid;
++ i->i_gid.val = rep->gid;
++ i->i_size = rep->size;
++ i->i_atime.tv_sec = rep->atime.sec;
++ i->i_atime.tv_nsec = rep->atime.nsec;
++ i->i_mtime.tv_sec = rep->mtime.sec;
++ i->i_mtime.tv_nsec = rep->mtime.nsec;
++ i->i_ctime.tv_sec = rep->ctime.sec;
++ i->i_ctime.tv_nsec = rep->ctime.nsec;
++ i->i_blkbits = ffs(rep->blksize);
++ i->i_blocks = rep->blocks;
++
++ if (i->i_sb->s_flags & MS_RDONLY)
++ i->i_mode &= ~0222;
++}
++
++static struct inode *mfs_new_inode(struct super_block *sb,
++ struct inode_rep *rep)
++{
++ struct inode *i = new_inode(sb);
++ if (!i) return NULL;
++
++ mfs_update_inode(i, rep);
++
++ if (S_ISREG(rep->mode)) {
++ i->i_op = &mfs_file_ops;
++ i->i_fop = &mfs_fops;
++ i->i_data.a_ops = &mfs_aops;
++ } else if (S_ISDIR(rep->mode)) {
++ i->i_op = &mfs_dir_ops;
++ i->i_fop = &mfs_dir_fops;
++ } else if (S_ISLNK(rep->mode)) {
++ i->i_op = &mfs_link_ops;
++ } else {
++ init_special_inode(i, rep->mode, (dev_t) rep->rdev);
++ }
++
++ insert_inode_hash(i);
++ return i;
++}
++
++static struct inode *mfs_getinode(struct super_block *sb,
++ unsigned long long ino)
++{
++ struct getinode_req req;
++ struct inode_rep rep;
++ unsigned len;
++
++ req.id = MFS_ID(sb);
++ req.cmd = CMD_GETINODE;
++ req.ino = ino;
++ len = send_request(&req, sizeof(req), &rep, sizeof(rep));
++
++ if (len < sizeof(rep) || rep.status)
++ return NULL;
++
++ return mfs_new_inode(sb, &rep);
++}
++
++static void mfs_put_super(struct super_block *sb)
++{
++}
++
++static int mfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct statfs_req req;
++ struct statfs_rep rep;
++ struct super_block *sb = dentry->d_sb;
++ unsigned len;
++
++ req.id = MFS_ID(sb);
++ req.cmd = CMD_STATFS;
++ rep.status = -EINVAL;
++ len = send_request(&req, sizeof(req), &rep, sizeof(rep));
++
++ if (len < sizeof(rep) || rep.status)
++ return rep.status;
++
++ buf->f_type = sb->s_magic;
++ buf->f_bsize = 512;
++ buf->f_blocks = rep.blocks;
++ buf->f_bfree = rep.bfree;
++ buf->f_bavail = rep.bfree;
++ buf->f_namelen = 255;
++
++ return 0;
++}
++
++static const struct super_operations mfs_ops = {
++ .alloc_inode = mfs_alloc_inode,
++ .destroy_inode = mfs_destroy_inode,
++ .put_super = mfs_put_super,
++ .statfs = mfs_statfs,
++};
++
++static int mfs_fill_super(struct super_block *sb, void *data, int silent)
++{
++ struct inode *root;
++ unsigned id;
++
++ if (*(char *) data == '/') ++data;
++ id = simple_strtoul((char *) data, NULL, 10);
++
++ sb->s_magic = 0xdeadbeef;
++ sb->s_op = &mfs_ops;
++ if (id == 0)
++ sb->s_flags |= MS_RDONLY;
++ sb->s_fs_info = (void *) id;
++
++ root = mfs_getinode(sb, 0);
++ if (!root)
++ goto out;
++
++ sb->s_root = d_make_root(root);
++ if (!sb->s_root)
++ goto outiput;
++
++ return 0;
++
++ outiput:
++ iput(root);
++ out:
++ return -EINVAL;
++}
++
++static struct dentry *mfs_mount(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *data)
++{
++ return mount_nodev(fs_type, flags, (void *) dev_name, mfs_fill_super);
++}
++
++static struct file_system_type mfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "metafs",
++ .mount = mfs_mount,
++ .kill_sb = kill_block_super,
++ .fs_flags = FS_REQUIRES_DEV,
++};
++
++static void init_once(void *foo)
++{
++ struct inode * inode = (struct inode *) foo;
++
++ inode_init_once(inode);
++}
++
++static int __init init_mfs_fs(void)
++{
++ unsigned i;
++ int err;
++
++ if (vm_running() != 0)
++ return 0;
++
++ printk("MFS init\n");
++ mfs_inode_cachep = kmem_cache_create("metafs_inode_cache",
++ sizeof(struct inode),
++ 0, (SLAB_RECLAIM_ACCOUNT|
++ SLAB_MEM_SPREAD),
++ init_once);
++ if (!mfs_inode_cachep)
++ return -ENOMEM;
++
++ for (i = 0; i < BUF_COUNT; ++i) {
++ tx_descr[i].addr = 0;
++ tx_descr[i].size = 0;
++ tx_descr[i].next = (unsigned) &tx_descr[i + 1];
++
++ rx_descr[i].addr = 0;
++ rx_descr[i].size = DONE;
++ rx_descr[i].next = (unsigned) &rx_descr[i + 1];
++ }
++ tx_descr[BUF_COUNT - 1].next = (unsigned) &tx_descr[0];
++ rx_descr[BUF_COUNT - 1].next = (unsigned) &rx_descr[0];
++
++ vm_create_queue(2, -1u,
++ (unsigned) &tx_descr[0], (unsigned) &rx_descr[0]);
++
++ err = register_filesystem(&mfs_fs_type);
++ if (err != 0) {
++ kmem_cache_destroy(mfs_inode_cachep);
++ return err;
++ }
++
++ return 0;
++}
++
++static void __exit exit_mfs_fs(void)
++{
++ unregister_filesystem(&mfs_fs_type);
++ kmem_cache_destroy(mfs_inode_cachep);
++}
++
++module_init(init_mfs_fs);
++module_exit(exit_mfs_fs);
+diff -puNrb linux-3.10.49/fs/metafs/Kconfig linux-3.10.49-minimal/fs/metafs/Kconfig
+--- linux-3.10.49/fs/metafs/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/fs/metafs/Kconfig 2014-01-11 05:37:13.000000000 +0000
+@@ -0,0 +1,3 @@
++config META_FS
++ depends on METAROUTER || MIPS_MIKROTIK
++ tristate "MetaFS on Mikrotik MetaRouters"
+diff -puNrb linux-3.10.49/fs/metafs/Makefile linux-3.10.49-minimal/fs/metafs/Makefile
+--- linux-3.10.49/fs/metafs/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.10.49-minimal/fs/metafs/Makefile 2014-01-11 05:37:13.000000000 +0000
+@@ -0,0 +1,3 @@
++obj-y += metafs.o
++
++metafs-objs := inode.o
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment