aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/defconfig2785
-rw-r--r--recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/kernel_af_bus.patch6313
-rw-r--r--recipes-kernel/linux/linux-omap4_3.4.0.bb21
-rw-r--r--recipes-kernel/linux/linux.inc277
4 files changed, 9396 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/defconfig b/recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/defconfig
new file mode 100644
index 0000000..7d9baa0
--- /dev/null
+++ b/recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/defconfig
@@ -0,0 +1,2785 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.4.11 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_LOCKBREAK=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO 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=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_FHANDLE is not set
+CONFIG_TASKSTATS=y
+# CONFIG_TASK_DELAY_ACCT is not set
+# CONFIG_TASK_XACCT is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_BOOST is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+# 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=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_DEBUG_PERF_USE_VMALLOC=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=y
+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_CONTIGUOUS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_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=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+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=y
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_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_UNINLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# 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 is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# 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 is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_PRIMA2 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PICOXCELL is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_ARCH_ZYNQ is not set
+CONFIG_GPIO_PCA953X=y
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+
+#
+# TI OMAP Common Features
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2PLUS=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_CLASS3 is not set
+CONFIG_OMAP_SMARTREFLEX_CLASS1P5=y
+CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY=86400000
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP5_SEVM_PALMAS=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+CONFIG_OMAP_SCM_DEV=y
+CONFIG_OMAP_MBOX_FWK=y
+CONFIG_OMAP_MBOX_KFIFO_SIZE=256
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_PM_NOOP=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# TI OMAP2/3/4 Specific Features
+#
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_ARCH_OMAP3 is not set
+CONFIG_ARCH_OMAP4=y
+CONFIG_ARCH_OMAP5=y
+CONFIG_OMAP_PACKAGE_CBL=y
+CONFIG_OMAP_PACKAGE_CBS=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP_4430SDP=y
+CONFIG_MACH_OMAP4_PANDA=y
+CONFIG_MACH_OMAP5_SEVM=y
+CONFIG_SECURE_REGS=y
+CONFIG_OMAP4_ERRATA_I688=y
+CONFIG_OMAP_TPS6236X=y
+# CONFIG_OMAP_PM_STANDALONE is not set
+# CONFIG_OMAP4_ARM_ERRATA_742230 is not set
+# CONFIG_OMAP4_ARM_ERRATA_751472 is not set
+# CONFIG_OMAP4_ARM_ERRATA_743622 is not set
+
+#
+# System MMU
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_SWP_EMULATE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_CACHE_L2X0=y
+CONFIG_CACHE_PL310=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARCH_HAS_BARRIERS=y
+CONFIG_ARM_NR_BANKS=8
+CONFIG_CPU_HAS_PMU=y
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_742230 is not set
+# CONFIG_ARM_ERRATA_742231 is not set
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_727915=y
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+CONFIG_PL310_ERRATA_753970=y
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_ARM_ERRATA_761171=y
+CONFIG_ARM_ERRATA_4668=y
+CONFIG_ARM_GIC=y
+# CONFIG_FIQ_DEBUGGER is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_HAVE_SMP=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_ARM_CPU_TOPOLOGY=y
+# CONFIG_SCHED_MC is not set
+# CONFIG_SCHED_SMT is not set
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_ARM_SMP_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
+CONFIG_LOCAL_TIMERS=y
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_HZ=128
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_COMPACTION is not set
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_CLEANCACHE is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_ARM_APPENDED_DTB is not set
+CONFIG_CMDLINE="console=ttyO2,115200n8 root=/dev/mmcblk0p2 rootwait earlyprintk earlycon=ttyO2.115200n8"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CLK_REG_CPUFREQ_DRIVER is not set
+
+#
+# ARM CPU frequency scaling drivers
+#
+# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HAS_WAKELOCK is not set
+# CONFIG_WAKELOCK is not set
+# CONFIG_USER_WAKELOCK is not set
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_CAN_PM_TRACE=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_HAS_OPP=y
+CONFIG_PM_OPP=y
+CONFIG_PM_CLK=y
+CONFIG_CPU_PM=y
+# CONFIG_SUSPEND_TIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+CONFIG_TCP_CONG_CUBIC=y
+# 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_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+# CONFIG_NET_ACTIVITY_STATS is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# 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 is not set
+# CONFIG_DCB is not set
+# CONFIG_DNS_RESOLVER is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+CONFIG_BQL=y
+CONFIG_HAVE_BPF_JIT=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+# CONFIG_BT_BNEP_MC_FILTER is not set
+# CONFIG_BT_BNEP_PROTO_FILTER is not set
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_WILINK=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+CONFIG_NL80211_TESTMODE=y
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_CFG80211_ALLOW_RECONNECT is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+# CONFIG_MAC80211_RC_PID is not set
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+CONFIG_RFKILL_PM=y
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+# CONFIG_RFKILL_REGULATOR is not set
+CONFIG_RFKILL_GPIO=y
+# 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=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+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_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_SYNC is not set
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+
+#
+# Default contiguous memory area size:
+#
+CONFIG_CMA_SIZE_MBYTES=16
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_ALIGNMENT=8
+CONFIG_CMA_AREAS=7
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+CONFIG_OF_NET=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_VIRTIO_BLK 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_ATMEL_PWM is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_SENSORS_AK8975 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_UID_STAT is not set
+CONFIG_DDR=y
+CONFIG_EMIF=y
+CONFIG_BMP085=m
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_WL127X_RFKILL is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IWMC3200TOP is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+CONFIG_TI_ST=y
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_VIRTIO is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+# CONFIG_SATA_PMP is not set
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+# CONFIG_SATA_MV is not set
+
+#
+# PATA SFF controllers with BMDMA
+#
+
+#
+# PIO-only SFF controllers
+#
+# CONFIG_PATA_PLATFORM is not set
+
+#
+# Generic fallback / legacy drivers
+#
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE 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=y
+# 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
+
+#
+# CAIF transport drivers
+#
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+CONFIG_USB_NET_SMSC95XX=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_WIFI_CONTROL_FUNC is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BCMDHD is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IWM is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CU is not set
+CONFIG_WL_TI=y
+# CONFIG_WL1251 is not set
+CONFIG_WL12XX=m
+CONFIG_WLCORE=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_WL12XX_PLATFORM_DATA=y
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN 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=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_KEYRESET is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+CONFIG_KEYBOARD_OMAP4=y
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_SMSC is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TI_TSCADC is not set
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+CONFIG_TOUCHSCREEN_QUANTUM_OBP=m
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+CONFIG_INPUT_TSL2771=m
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYCHORD is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_TWL4030_PWRBUTTON is not set
+CONFIG_INPUT_PALMAS_PWRBUTTON=y
+# CONFIG_INPUT_TWL4030_VIBRA is not set
+# CONFIG_INPUT_TWL6040_VIBRA is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_GPIO is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+CONFIG_INPUT_MPU6050=y
+CONFIG_INPUT_MPU6050_I2C=y
+CONFIG_INPUT_MPU6050_ACCEL=y
+CONFIG_INPUT_MPU6050_GYRO=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_SERIAL_8250_DW is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_VIRTIO_CONSOLE is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_VIRTIO is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_DCC_TTY is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_SPI is not set
+# CONFIG_HSI 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
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X_IRQ is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+CONFIG_GPIO_TWL4030=y
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_GPIO_PALMAS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+CONFIG_SENSORS_OMAP_TEMP_SENSOR=y
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_SCH5636 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_THMC50 is not set
+CONFIG_SENSORS_TMP102=y
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+CONFIG_OMAP4460PLUS_SCM=y
+CONFIG_OMAP4460PLUS_TEMP_SENSOR=y
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_MADC is not set
+CONFIG_TWL4030_POWER=y
+# CONFIG_MFD_TWL4030_AUDIO is not set
+# CONFIG_TWL6030_PWM is not set
+CONFIG_TWL6040_CORE=y
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_S5M_CORE is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_OMAP_CONTROL is not set
+CONFIG_MFD_OMAP_USB_HOST=y
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_RC5T583 is not set
+CONFIG_MFD_PALMAS=y
+CONFIG_MFD_PALMAS_GPADC=y
+CONFIG_MFD_PALMAS_RESOURCE=y
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_TPS62360 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_RC_CORE is not set
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_XC4000=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders, decoders, sensors and other helper chips
+#
+
+#
+# Audio decoders, processors and mixers
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# RDS decoders
+#
+# CONFIG_VIDEO_SAA6588 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_ADV7180 is not set
+# CONFIG_VIDEO_ADV7183 is not set
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_TVP7002 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+# CONFIG_VIDEO_AK881X is not set
+
+#
+# Camera sensor devices
+#
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_VS6624 is not set
+# CONFIG_VIDEO_MT9M032 is not set
+# CONFIG_VIDEO_MT9P031 is not set
+# CONFIG_VIDEO_MT9T001 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_MT9V032 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_NOON010PC30 is not set
+# CONFIG_VIDEO_M5MOLS is not set
+# CONFIG_VIDEO_S5K6AA is not set
+
+#
+# Flash devices
+#
+# CONFIG_VIDEO_ADP1653 is not set
+# CONFIG_VIDEO_AS3645A is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# Miscelaneous helper chips
+#
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VIDEO_CLASS is not set
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_OMAP2_VOUT=m
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_IMX074 is not set
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9T112 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_SOC_CAMERA_PLATFORM=m
+# CONFIG_SOC_CAMERA_OV2640 is not set
+CONFIG_SOC_CAMERA_OV5642=m
+CONFIG_SOC_CAMERA_OV6650=m
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+# CONFIG_SOC_CAMERA_OV9740 is not set
+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+
+#
+# Graphics support
+#
+CONFIG_DRM=y
+CONFIG_DRM_KMS_HELPER=y
+# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+# CONFIG_DRM_I2C_SIL164 is not set
+# CONFIG_DRM_UDL is not set
+# CONFIG_ION is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=16
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS=y
+CONFIG_OMAP2_DSS_DPI=y
+CONFIG_OMAP2_DSS_RFBI=y
+CONFIG_OMAP2_DSS_VENC=y
+CONFIG_OMAP4_DSS_HDMI=y
+CONFIG_OMAP4_DSS_HDMI_AUDIO=y
+CONFIG_OMAP5_DSS_HDMI=y
+CONFIG_OMAP5_DSS_HDMI_AUDIO=y
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC_DPI=y
+CONFIG_PANEL_TFP410=y
+# CONFIG_PANEL_PICODLP is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_VERBOSE=y
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_DMIC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_MCPDM=y
+CONFIG_SND_OMAP_SOC_HDMI=y
+CONFIG_SND_OMAP_SOC_ABE=y
+CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=y
+CONFIG_SND_OMAP_SOC_SDP4430=y
+CONFIG_SND_OMAP_SOC_OMAP_HDMI=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_DMIC=y
+CONFIG_SND_SOC_OMAP_HDMI_CODEC=y
+CONFIG_SND_SOC_TWL6040=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB_ARCH_HAS_XHCI=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_DWC3=m
+# CONFIG_USB_DWC3_DEBUG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=m
+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_HCD_OMAP=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=m
+# CONFIG_USB_MUSB_TUSB6010 is not set
+CONFIG_USB_MUSB_OMAP2PLUS=m
+# CONFIG_USB_MUSB_AM35X is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_MUSB_PIO_ONLY is not set
+# CONFIG_USB_RENESAS_USBHS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+# CONFIG_USB_FUSB300 is not set
+CONFIG_USB_OMAP=m
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_MV_UDC is not set
+CONFIG_USB_GADGET_MUSB_HDRC=m
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_GADGET_SUPERSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+CONFIG_USB_MASS_STORAGE=m
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_ACM_MS is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_TWL4030_USB=y
+CONFIG_TWL6030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_PALMAS_USB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+# CONFIG_MMC_EMBEDDED_SDIO is not set
+# CONFIG_MMC_PARANOID_SD_INIT is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+# CONFIG_MMC_OMAP is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA9633 is not set
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_RENESAS_TPU is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_OT200 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_SWITCH is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# 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_BALLOON is not set
+CONFIG_VIRTIO_MMIO=y
+
+#
+# Microsoft Hyper-V guest support
+#
+CONFIG_STAGING=y
+# CONFIG_USBIP_CORE is not set
+# CONFIG_W35UND is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_R8712U is not set
+# CONFIG_RTS5139 is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_VT6656 is not set
+# CONFIG_IIO is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+# CONFIG_STAGING_MEDIA is not set
+CONFIG_DRM_OMAP=y
+CONFIG_DRM_OMAP_NUM_CRTCS=2
+CONFIG_RPC_OMAP=m
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_PHONE is not set
+# CONFIG_USB_WPAN_HCD is not set
+CONFIG_THERMAL_FRAMEWORK=y
+CONFIG_OMAP_THERMAL=y
+CONFIG_OMAP_DIE_GOVERNOR=y
+CONFIG_OMAP_GPU_GOVERNOR=y
+CONFIG_DRM_OMAP_DCE=m
+# CONFIG_OMAP_RPMSG_RDAEMON is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HWSPINLOCK=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_HWSPINLOCK_OMAP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_IOMMU_API=y
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_OMAP_IOMMU=y
+CONFIG_OMAP_IOVMM=y
+# CONFIG_OMAP_IOMMU_DEBUG is not set
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+CONFIG_REMOTEPROC=m
+CONFIG_OMAP_REMOTEPROC=m
+CONFIG_OMAP_REMOTEPROC_IPU=y
+CONFIG_OMAP_REMOTEPROC_DSP=y
+CONFIG_OMAP_REMOTEPROC_WATCHDOG=y
+CONFIG_OMAP4_IPU_CMA_SIZE=0x7000000
+CONFIG_OMAP5_IPU_CMA_SIZE=0xA400000
+CONFIG_OMAP_DSP_CMA_SIZE=0x700000
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+CONFIG_RPMSG=m
+CONFIG_RPMSG_RESMGR_FWK=m
+CONFIG_RPMSG_RESMGR=m
+CONFIG_OMAP_RPMSG_RESMGR=m
+CONFIG_RPMSG_OMX=m
+CONFIG_VIRT_DRIVERS=y
+# CONFIG_PM_DEVFREQ is not set
+CONFIG_GATOR=m
+CONFIG_STM_FW=y
+# CONFIG_STM_OMAP_TI1_0 is not set
+CONFIG_STM_ARM=y
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# 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=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# 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_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# 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_ECRYPT_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 is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_PNFS_FILE_LAYOUT=y
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_USE_LEGACY_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_BACKCHANNEL=y
+# CONFIG_SUNRPC_DEBUG 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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# 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=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT 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=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED 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_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_RCU_CPU_STALL_VERBOSE=y
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE 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_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_LKDTM is not set
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+# CONFIG_EVENT_POWER_TRACING_DEPRECATED is not set
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_FUNCTION_GRAPH_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_DYNAMIC_FTRACE=y
+# CONFIG_FUNCTION_PROFILER is not set
+CONFIG_FTRACE_MCOUNT_RECORD=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK 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_STRICT_DEVMEM is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_OLD_MCOUNT=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_UART_NONE=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_SEMIHOSTING is not set
+CONFIG_EARLY_PRINTK=y
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# 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=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=y
+# 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=y
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_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=y
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+
+#config required by systemd
+CONFIG_CGROUPS=y
diff --git a/recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/kernel_af_bus.patch b/recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/kernel_af_bus.patch
new file mode 100644
index 0000000..9ef0452
--- /dev/null
+++ b/recipes-kernel/linux/linux-omap4-3.4.0/pandaboard/kernel_af_bus.patch
@@ -0,0 +1,6313 @@
+From 8c071e4a4be17b7bb01ab2a911c1697902dc2c35 Mon Sep 17 00:00:00 2001
+From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Date: Wed, 20 Jun 2012 12:07:49 +0200
+Subject: [PATCH 1/1] net: bus: add the AF_BUS socket address family
+
+AF_BUS is a new socket address family that allows both unicast and
+multicast I on a local machine with total ordering for messages
+(every process on the same bus sees each message in the same order).
+
+A process can create buses to which other processes can connect and
+communicate with each other by sending messages. Processes' addresses are
+automatically assigned by the bus on connect and are unique. Messages can
+be sent either to process' unique address or to a bus multicast address.
+
+Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+
+Index: git/Documentation/networking/af_bus.patch
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/Documentation/networking/af_bus.patch 2012-10-05 12:54:51.000000000 +0300
+@@ -0,0 +1,558 @@
++ The AF_BUS socket address family
++ ================================
++
++Introduction
++------------
++
++AF_BUS is a message oriented inter process communication system.
++
++The principle features are:
++
++ - Reliable datagram based communication (all sockets are of type
++ SOCK_SEQPACKET)
++
++ - Multicast message delivery (one to many, unicast as a subset)
++
++ - Strict ordering (messages are delivered to every client in the same order)
++
++ - Ability to pass file descriptors
++
++ - Ability to pass credentials
++
++The basic concept is to provide a virtual bus on which multiple
++processes can communicate and policy is imposed by a "bus master".
++
++A process can create buses to which other processes can connect and
++communicate with each other by sending messages. Processes' addresses
++are automatically assigned by the bus on connect and are
++unique. Messages can be sent either to a process' unique address or to
++a bus multicast addresses.
++
++Netfilter rules or Berkeley Packet Filter can be used to restrict the
++messages that each peer is allowed to receive. This is especially
++important when sending to multicast addresses.
++
++Besides messages, process can send and receive ancillary data (i.e.,
++SCM_RIGHTS for passing file descriptors or SCM_CREDENTIALS for passing
++Unix credentials). In the case of a multicast message all recipients
++of a message may obtain a copy a file descriptor or credentials.
++
++A bus is created by processes connecting on an AF_BUS socket. The
++"bus master" binds itself instead of connecting to the NULL address.
++
++The socket address is made up of a path component and a numeric
++component. The path component is either a pathname or an abstract
++socket similar to a unix socket. The numeric component is used to
++uniquely identify each connection to the bus. Thus the path identifies
++a specific bus and the numeric component the attachment to that bus.
++
++The process that calls bind(2) on the socket is the owner of the bus
++and is called the bus master. The master is a special client of the
++bus and has some responsibility for the bus' operation. The master is
++assigned a fixed address with all the bits zero (0x0000000000000000).
++
++Each process connected to an AF_BUS socket has one or more addresses
++within that bus. These addresses are 64-bit unsigned integers,
++interpreted by splitting the address into two parts: the most
++significant 16 bits are a prefix identifying the type of address, and
++the remaining 48 bits are the actual client address within that
++prefix, as shown in this figure:
++
++Bit: 0 15 16 63
++ +----------------+------------------------------------------------+
++ | Type prefix | Client address |
++ +----------------+------------------------------------------------+
++
++The prefix with all bits zero is reserved for use by the kernel, which
++automatically assigns one address from this prefix to each client on
++connection. The address in this prefix with all bits zero is always
++assigned to the bus master. Addresses on the prefix 0x0000 are unique
++and will never repeat for the lifetime of the bus master.
++
++A client may have multiple addresses. When data is sent to other
++clients, those clients will always see the sender address that is in
++the prefix 0x0000 address space when calling recvmsg(2) or
++recvfrom(2). Similarly, the prefix 0x0000 address is returned by calls
++to getsockname(2) and getpeername(2).
++
++For each prefix, the address where the least significant 48 bits are
++all 1 (i.e., 0xffffffffffff) is also reserved, and can be used to send
++multicast messages to all the peers on a prefix.
++
++The non-reserved addresses in each of the remaining prefixes are
++managed by the bus master, which may assign additional addresses to
++any other connected socket.
++
++Having different name-spaces has two advantages:
++
++ - Clients can have addresses on different mutually-exclusive
++ scopes. This permits sending multicast packets to only clients
++ that have addresses on a given prefix.
++
++ - The addressing scheme can be more flexible. The kernel will only
++ assign unique addresses on the all-bits-zero prefix (0x0000) and
++ allows the bus master process to assign additional addresses to
++ clients on other prefixes. By having different prefixes, the
++ kernel and bus master assignments will not collide.
++
++AF_BUS transport can support two network topologies. When a process
++first connects to the bus master, it can only communicate with the bus
++master. The process can't send and receive packets from other peers on
++the bus. So, from the client process point of view the network
++topology is point-to-point.
++
++The bus master can allow the connected peer to be part of the bus and
++start to communicate with other peers by setting a socket option with
++the setsockopt(2) system call using the accepted socket descriptor. At
++this point, the topology becomes a bus to the client process.
++
++Packets whose destination address is not assigned to any client are
++routed by default to the bus master (the client accepted socket
++descriptor).
++
++
++Semantics
++---------
++
++Bus features:
++
++ - Unicast and multicast addressing scheme.
++ - Ability to assign addresses from user-space with different prefixes.
++ - Automatic address assignment.
++ - Ordered packets delivery (FIFO, total ordering).
++ - File descriptor and credentials passing.
++ - Support for both point-to-point and bus network topologies.
++ - Bus control access managed from user-space.
++ - Netfilter hooks for packet sending, routing and receiving.
++
++A process (the "bus master") can create an AF_BUS bus with socket(2)
++and use bind(2) to assign an address to the bus. Then it can listen(2)
++on the created socket to start accepting incoming connections with
++accept(2).
++
++Processes can connect to the bus by creating a socket with socket(2)
++and using connect(2). The kernel will assign a unique address to each
++connection and messages can be sent and received by using BSD socket
++primitives.
++
++This uses the connect(2) semantic in a non-traditional way, with
++AF_BUS sockets, it's not possible to connect "my" socket to a specific
++peer socket whereas the traditional BSD sockets API usage, connect(2)
++either connects to stream sockets, or assigns a peer address to a
++datagram socket (so that send(2) can be used instead of sendto()).
++
++An AF_BUS socket address is represented as a combination of a bus
++address and a bus path name. Address are unique within a path. The
++unique bus address is further subdivided into a prefix and a client
++address. Thus the path identifies a specific bus and the numeric
++component the attachment to that bus.
++
++#define BUS_PATH_MAX 108
++
++/* Bus address */
++struct bus_addr {
++ uint64_t s_addr; /* 16-bit prefix + 48-bit client address */
++};
++
++/* Structure describing an AF_BUS socket address. */
++struct sockaddr_bus {
++ sa_family_t sbus_family; /* AF_BUS */
++ struct bus_addr sbus_addr; /* bus address */
++ char sbus_path[BUS_PATH_MAX]; /* pathname */
++};
++
++A process becomes a bus master for a given struct sockaddr_bus by
++calling bind(2) on an AF_BUS addresses. The argument must be { AF_BUS,
++0, path }.
++
++AF_BUS supports both abstract and non-abstract path names. Abstract
++names are distinguished by the fact that sbus_path[0] == '\0' and they
++don't represent file system paths while non-abstract paths are bound
++to a file system path name. (See the unix(7) man page for a discussion
++of abstract socket addresses in the AF_UNIX address family.)
++
++Then the process calls listen(2) to accept incoming connections. If
++that process calls getsockname(2), the returned address will be {
++AF_BUS, 0, path }.
++
++The conventional string form of the full address is path + ":" +
++prefix + "/" + client address. Prefix and client address are
++represented in hex.
++
++For example the address:
++
++struct sockaddr_bus addr;
++addr.sbus_family = AF_BUS;
++strcpy(addr.sbus_path, "/tmp/test");
++addr.sbus_addr.s_addr = 0x0002f00ddeadbeef;
++
++would be represented using the string /tmp/test:0002/f00ddeadbeef.
++
++If the bus_addr is 0, then both the prefix and client address may be
++omitted from the string form. To connect to a bus as a client it is
++sufficient to specify the path, since the listening address always has
++bus_addr == 0. it is not meanigful to specify 'bus_addr' as other than
++0 on connect()
++
++The AF_BUS implementation will automatically assign a unique address
++to each client but the bus master can assign additional addresses on a
++different prefix by means of the setsockopt(2) system call. For
++example:
++
++struct bus_addr addr;
++addr.s_addr = 0x0001deadfee1dead;
++ret = setsockopt(afd, SOL_BUS, BUS_ADD_ADDR, &addr, sizeof(addr));
++
++where afd is the accepted socket descriptor in the daemon. To show graphically:
++
++ L The AF_BUS listening socket }
++ / | \ }-- listener process
++ A1 A2 A3 The AF_BUS accepted sockets }
++ | | |
++ C1 C2 C3 The AF_BUS connected sockets }-- client processes
++
++So if setsockopt(A1, SOL_BUS, BUS_ADD_ADDR, &addr, sizeof(addr)) is
++called, C1 will get the new address.
++
++The inverse operation is BUS_DEL_ADDR, which the bus master can use to
++remove a client socket AF_BUS address:
++
++ret = setsockopt(afd, SOL_BUS, BUS_DEL_ADDR, &addr, sizeof(addr));
++
++Besides assigning additional addresses, the bus master has to allow a
++client process to communicate with other peers on the bus using a
++setsockopt(2):
++
++ret = setsockopt(afd, SOL_BUS, BUS_JOIN_BUS, NULL, 0);
++
++Clients are not meant to send messages to each other until the master
++tells them (in a protocol-specific way) that the BUS_JOIN_BUS
++setsockopt(2) call was made.
++
++If a client sends a message to a destination other than the bus
++master's all-zero address before joining the bus, a EHOSTUNREACH (No
++route to host) error is returned since the only host that exists in
++the point-to-point network before the client joins the bus are the
++client and the bus master.
++
++A EHOSTUNREACH is returned if a client that joined a bus tries to send
++a packet to a client from another bus. Cross-bus communication is not
++permited.
++
++When a process wants to send a unicast message to a peer, it fills a
++sockaddr structure and performs a socket operation (i.e., sendto(2))
++
++struct sockaddr_bus addr;
++char *msg = "Hello world";
++
++addr.sbus_family = AF_BUS;
++strcpy(addr.sbus_path, "/tmp/test");
++addr.sbus_addr.s_addr = 0x0001f00ddeadbeef;
++
++ret = sendto(sockfd, "Hello world", strlen("Hello world"), 0,
++ (struct sockaddr*)&addr, sizeof(addr));
++
++The current implementation requires that the addr.sbus_path component
++match the one used to conenct() to the bus but in future this
++requirement will be removed.
++
++The kernel will first check that the socket is connected and that the
++bus path of the socket correspond with the destination, then it will
++extract the prefix and client address from the bus address using a
++fixed 16 -bit bitmask.
++
++prefix = bus address >> 48 & 0xffff
++client address = bus address & 0xffff
++
++If the client address is not all bits one, then the message is unicast
++and is delivered to the socket with that assigned address
++(0x0001f00ddeadbeef). Otherwise the message is multicast and is
++delivered to all the peers with this address prefix (0x0001 in this
++case).
++
++So, when a process wants to send a multicast message, it just has to
++fill the address structure with the address prefix + 0xffffffffffff:
++
++struct sockaddr_bus addr;
++char *msg = "Hello world";
++
++addr.bus_family = AF_BUS;
++strcpy(addr.sbus_path, "/tmp/test");
++addr.bus_addr = 0x0001ffffffffffff;
++
++ret = sendto(sockfd, "Hello world", strlen("Hello world"), 0,
++ (struct sockaddr*)&addr, sizeof(addr));
++
++The kernel, will apply the binary and operation, learn that the
++address is 0xffffffffffff and send the message to all the peers on
++this prefix (0x0001).
++
++Socket transmit queued bytes are limited by a maximum send buffer size
++(sysctl_wmem_max) defined in the kernel and can be modified at runtime
++using the sysctl interface on /proc/sys/net/core/wmem_default. This
++parameter is global for all the sockets families in a Linux system.
++
++AF_BUS permits the definition of a per-bus maximum send buffer size
++using the BUS_SET_SENDBUF socket option. The bus master can call the
++setsockopt(2) system call using as a parameter the listening socket.
++The command sets a maximum write buffer that will be imposed on each
++new socket that connects to the bus:
++
++ret = setsockopt(serverfd, SOL_BUS, BUS_SET_SENDBUF, &sndbuf,
++sizeof(int));
++
++In the transmission path both Berkeley Packet Filters and Netfilter
++hooks are available, so they can be used to filter sending packets.
++
++
++Using this addressing scheme with D-Bus
++---------------------------------------
++
++As an example of a use case for AF_BUS, let's analyze how the D-Bus
++IPC system can be implemented on top of it.
++
++We define a new D-Bus address type "afbus".
++
++A D-Bus client may connect to an address of the form "afbus:path=X"
++where X is a string. This means that it connect()s to { AF_BUS, 0, X }.
++
++For example: afbus:path=/tmp/test connects to { AF_BUS, 0, /tmp/test }.
++
++A D-Bus daemon may listen on the address "afbus:", which means that it
++binds to { AF_BUS, 0, /tmp/test }. It will advertise an address of the
++form "afbus:path=/tmp/test" to clients, for instance via the
++--print-address option, or via dbus-launch setting the
++DBUS_SESSION_BUS_ADDRESS environment variable. For instance, "afbus:"
++is an appropriate default listening address for the session bus,
++resulting in dbus-launch setting the DBUS_SESSION_BUS_ADDRESS
++environment variable to something like
++"afbus:path=/tmp/test,guid=...".
++
++A D-Bus daemon may listen on the address "afbus:file=/some/file",
++which means that it will do as above, then write its path into the
++given well-known file. For instance,
++"afbus:file=/run/dbus/system_bus.afbus" is an appropriate listening
++address for the system bus. Only processes with suitable privileges to
++write to that file can impersonate the system bus.
++
++D-Bus clients wishing to connect to the well-known system bus should
++attempt to connect to afbus:file=/run/dbus/system_bus.afbus, falling
++back to unix:path=/var/run/dbus/system_bus_socket if that fails. On
++Linux systems, the well-known system bus daemon should attempt to
++listen on both of those addresses.
++
++The D-Bus daemon will serve as bus master as well since it will be the
++process that creates and listens on the AF_BUS socket.
++
++D-Bus clients will use the fixed bus master address (all zero bits) to
++send messages to the D-Bus daemon and the client's unique address to
++send messages to other D-Bus clients using the bus.
++
++When initially connected, D-Bus clients will only be able to
++communicate with the D-Bus daemon and will send authentication
++information (AUTH message and SCM_CREDENTIALS ancillary
++messages). Since the D-Bus daemon is also the bus master, it can allow
++D-Bus clients to join the bus and be able to send and receive D-Bus
++messages from other peers.
++
++On connection, the kernel will assign to each client an address in the
++prefix 0x0000. If a client attempts to send messages to clients other
++than the bus master, this is considered to be an error, and is
++prevented by the kernel.
++
++When the D-Bus daemon has authenticated a client and determined that
++it is authorized to be on this bus, it uses a setsockopt(2) call to
++tell the kernel that this client has permission to send messages. The
++D-Bus daemon then tells the client by sending the Hello() reply that
++it has made the setsockopt(2) call and that now is able to send
++messages to other peers on the bus.
++
++Well-known names are represented by addresses in the 0x0001, ... prefixes.
++
++Addresses in prefix 0x0000 must be mapped to D-Bus unique names in a
++way that can't collide with unique names allocated by the dbus-daemon
++for legacy clients.
++
++In order to be consistent with current D-Bus unique naming, the AF_BUS
++addresses can be mapped directly to D-Bus unique names, for example
++(0000/0000deadbeef to ":0.deadbeef"). Leading zeroes can be suppressed
++since the common case should be relatively small numbers (the kernel
++allocates client addresses sequentially, and machines could be
++rebooted occasionally).
++
++By having both AF_BUS and legacy D-Bus clients use the same address
++space, the D-Bus daemon can act as a proxy between clients and can be
++sure that D-Bus unique names will be unique for both AF_BUS and legacy
++clients.
++
++To act as a proxy between AF_BUS and legacy clients, each time the
++D-Bus daemon accepts a legacy connection (i.e., AF_UNIX), it will
++create an AF_BUS socket and establish a connection with itself. It
++will then associate this newly created connection with the legacy one.
++
++To explain it graphically:
++
++ L The AF_BUS listening socket }
++ / | \ }-- listener process
++ A1 A2 A3 The AF_BUS accepted sockets }
++ | | |
++ C1 C2 C3 The AF_BUS connected sockets, where:
++ | * C1 belongs to the listener process
++ | * C2 and C3 belongs to the client processes
++ |
++ L2--A4 The AF_UNIX listening and accepted sockets \
++ | in the listener process
++ C4 The AF_UNIX connected socket in the legacy client process
++
++
++where C2 and C3 are normal AF_BUS clients and C4 is a legacy
++client. The D-Bus daemon after accepting the connection using the
++legacy transport (A4), will create an AF_BUS socket pair (C1, A1)
++associated with the legacy client.
++
++Legacy clients will send messages to the D-Bus daemon using their
++legacy socket and the D-Bus daemon will extract the destination
++address, resolve to the corresponding AF_BUS address and use this to
++send the message to the right peer.
++
++Conversely, when an AF_BUS client sends a D-Bus message to a legacy
++client, it will use the AF_BUS address of the connection associated
++with that client. The D-Bus daemon will receive the message, modify
++the message's content to set SENDER headers based on the AF_BUS source
++address and use the legacy transport to send the D-Bus message to the
++legacy client.
++
++As a special case, the bus daemon's all-zeroes address maps to
++"org.freedesktop.DBus" and vice versa.
++
++When a D-Bus client receives an AF_BUS message from the bus master
++(0/0), it must use the SENDER header field in the D-Bus message, as
++for any other D-Bus transport, to determine whether the message is
++actually from the D-Bus daemon (the SENDER is "org.freedesktop.DBus"
++or missing), or from another client (the SENDER starts with ":"). It
++is valid for messages from another AF_BUS client to be received via
++the D-Bus daemon; if they are, the SENDER header field will always be
++set.
++
++Besides its unique name, D-Bus services can have well-known names such
++as org.gnome.Keyring or org.freedesktop.Telepathy. These well-known
++names can also be used as a D-Bus message destination
++address. Well-known names are not numeric and AF_BUS is not able to
++parse D-Bus messages.
++
++To solve this, the D-Bus daemon will assign an additional AF_BUS
++address to each D-Bus client that owns a well-known name. The mapping
++between well-known names and AF_BUS address is maintained by the D-Bus
++daemon on a persistent data structure.
++
++D-Bus client libraries will maintain a cache of these mappings so they
++can send messages to services with well-known names using their mapped
++AF_BUS address.
++
++If a client intending to send a D-Bus message to a given well-known
++name does not have that well-known name in its cache, it must send the
++AF_BUS message to the listener (0000/000000000000) instead.
++
++The listener must forward the D-Bus message to the owner of that
++well-known name, setting the SENDER header field if necessary. It may
++also send this AF_BUS-specific D-Bus signal to the sender, so that the
++sender can update its cache:
++
++ org.freedesktop.DBus.AF_BUS.Forwarded (STRING well_known_name,
++ UINT64 af_bus_client)
++
++ Emitted by the D-Bus daemon with sender "org.freedesktop.DBus"
++ and object path "/org/freedesktop/DBus" to indicate that
++ the well-known name well_known_name is represented by the
++ AF_BUS address { AF_BUS, af_bus_client, path } where
++ path is the path name used by this bus.
++
++ For instance, if the well-known name "org.gnome.Keyring"
++ is represented by AF_BUS address 0001/0000deadbeef,
++ the signal would have arguments ("org.gnome.Keyring",
++ 0x00010000deadbeef), corresponding to the AF_BUS
++ address { AF_BUS, 0x00010000deadbeef, /tmp/test }.
++
++If the D-Bus service for that well-known name is not active, then the
++D-Bus daemon will first do the service activation, assign an
++additional address to the recently activated service, store the
++well-known service to numeric address mapping on its persistent cache,
++and then send the AF_BUS.Forwarded signal back to the client.
++
++Once the mapping has been made, the AF_BUS address associated with a
++well-known name cannot be reused for the lifetime of the D-Bus daemon
++(which is the same as the lifetime of the socket).
++
++Nevertheless the AF_BUS address associated with a well-known name can
++change, for example if a service goes away and a new instance gets
++activated. This new instance can have a different AF_BUS address. The
++D-Bus daemon will maintain a list of the mappings that are currently
++valid so it can send the AF_BUS.
++
++Forwarded signal with the mapping information to the clients. Client
++libraries will maintain a fixed-size Last Recently Used (LRU) cache
++with previous mappings sent by the D-Bus daemon.
++
++If the clients overwrite a mapping due to the LRU replace policy and
++later want to send a D-Bus message to the overwritten well-known name,
++they will send the D-Bus message back to the D-Bus daemon and this
++will send the signal with the mapping information.
++
++If a service goes away or if the service AF_BUS address changed and
++the client still has the old AF_BUS address in its cache, it will send
++the D-Bus message to the old destination.
++
++Since packets whose destination AF_BUS addresses are not assigned to
++any process are routed by default to the bus master, the D-Bus daemon
++will receive these D-bus messages and send an AF_BUS.
++
++Forwarded signal back to the client with the new AF_BUS address so it
++can update its cache with the new mapping.
++
++For well-known names, the D-Bus daemon will use a different address
++prefix (0x0001) so it doesn't conflict with the D-Bus unique names
++address prefix (0x0000).
++
++Besides D-Bus method call messages which are unicast, D-Bus allows
++clients to send multicast messages (D-Bus signals). Clients can send
++signals messages using the bus unique name prefix multicast address
++(0x0001ffffffffffff).
++
++A netfilter hook is used to filter these multicast messages and only
++deliver to the correct peers based on match rules.
++
++
++D-Bus aware netfilter module
++----------------------------
++
++AF_BUS is designed to be a generic bus transport supporting both
++unicast and multicast communications.
++
++In order for D-Bus to operate efficiently, the transport method has to
++know the D-Bus message wire-protocol and D-Bus message structure. But
++adding this D-Bus specific knowledge to AF_BUS will break one of the
++fundamental design principles of any network protocol stack, namely
++layer-independence: layer n must not make any assumptions about the
++payload in layer n + 1.
++
++So, in order to have a clean protocol design but be able to allow the
++transport to analyze the D-Bus messages, netfilter hooks are used to
++do the filtering based on match rules.
++
++The kernel module has to maintain the match rules and the D-Bus daemon
++is responsible for managing this information. Every time an add match
++rule message is processed by the D-Bus daemon, this will update the
++netfilter module match rules set so the netfilter hook function can
++use that information to do the match rules based filtering.
++
++The D-Bus daemon and the netfilter module will use the generic netlink
++subsystem to do the kernel-to-user-space communication. Netlink is
++already used by most of the networking subsystem in Linux
++(iptables/netfilter, ip/routing, etc).
++
++We enforce a security scheme so only the bus master's user ID can
++update the netfilter module match rules set.
++
++The advantage of using the netfilter subsystem is that we decouple the
++mechanism from the policy. AF_BUS will only add a set of hook points
++and external modules will be used to enforce a given policy.
+Index: git/drivers/connector/connector.c
+===================================================================
+--- git.orig/drivers/connector/connector.c 2012-10-05 12:09:43.000000000 +0300
++++ git/drivers/connector/connector.c 2012-10-05 12:56:28.000000000 +0300
+@@ -118,6 +118,38 @@
+ EXPORT_SYMBOL_GPL(cn_netlink_send);
+
+ /*
+++ * Send an unicast reply from a connector callback
+++ *
+++ */
++int cn_netlink_reply(struct cn_msg *msg, u32 pid, gfp_t gfp_mask)
++{
++unsigned int size;
++struct sk_buff *skb;
++struct nlmsghdr *nlh;
++struct cn_msg *data;
++struct cn_dev *dev = &cdev;
++
++size = NLMSG_SPACE(sizeof(*msg) + msg->len);
++
++skb = alloc_skb(size, gfp_mask);
++if (!skb)
++return -ENOMEM;
++
++nlh = nlmsg_put(skb, 0, msg->seq, NLMSG_DONE, size - sizeof(*nlh), 0);
++if (nlh == NULL) {
++kfree_skb(skb);
++return -EMSGSIZE;
++}
++
++data = nlmsg_data(nlh);
++
++memcpy(data, msg, sizeof(*data) + msg->len);
++
++return netlink_unicast(dev->nls, skb, pid, 1);
++}
++EXPORT_SYMBOL_GPL(cn_netlink_reply);
++
++/*
+ * Callback helper - queues work and setup destructor for given data.
+ */
+ static int cn_call_callback(struct sk_buff *skb)
+Index: git/include/linux/bus.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/include/linux/bus.h 2012-10-05 12:57:46.000000000 +0300
+@@ -0,0 +1,34 @@
++#ifndef _LINUX_BUS_H
++#define _LINUX_BUS_H
++
++#include <linux/socket.h>
++
++/* 'protocol' to use in socket(AF_BUS, SOCK_SEQPACKET, protocol) */
++#define BUS_PROTO_NONE 0
++#define BUS_PROTO_DBUS 1
++#define BUS_PROTO_MAX 1
++
++#define BUS_PATH_MAX 108
++
++/**
++ * struct bus_addr - af_bus address
++ * @s_addr: an af_bus address (16-bit prefix + 48-bit client address)
++ */
++struct bus_addr {
++ u64 s_addr;
++};
++
++
++/**
++ * struct sockaddr_bus - af_bus socket address
++ * @sbus_family: the socket address family
++ * @sbus_addr: an af_bus address
++ * @sbus_path: a path name
++ */
++struct sockaddr_bus {
++ __kernel_sa_family_t sbus_family;
++ struct bus_addr sbus_addr;
++ char sbus_path[BUS_PATH_MAX];
++};
++
++#endif /* _LINUX_BUS_H */
+Index: git/include/linux/connector.h
+===================================================================
+--- git.orig/include/linux/connector.h 2012-10-05 12:12:18.000000000 +0300
++++ git/include/linux/connector.h 2012-10-05 13:01:07.000000000 +0300
+@@ -44,8 +44,10 @@
+ #define CN_VAL_DRBD 0x1
+ #define CN_KVP_IDX 0x9 /* HyperV KVP */
+ #define CN_KVP_VAL 0x1 /* queries from the kernel */
++#define CN_IDX_NFDBUS 0xA /* netfilter D-Bus */
++#define CN_VAL_NFDBUS 0x1
+
+-#define CN_NETLINK_USERS 10 /* Highest index + 1 */
++#define CN_NETLINK_USERS 11 /* Highest index + 1 */
+
+ /*
+ * Maximum connector's message size.
+@@ -125,6 +127,7 @@
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
+ void cn_del_callback(struct cb_id *);
+ int cn_netlink_send(struct cn_msg *, u32, gfp_t);
++int cn_netlink_reply(struct cn_msg *, u32, gfp_t);
+
+ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
+ struct cb_id *id,
+Index: git/include/linux/netfilter.h
+===================================================================
+--- git.orig/include/linux/netfilter.h 2012-10-05 12:12:19.000000000 +0300
++++ git/include/linux/netfilter.h 2012-10-05 13:01:54.000000000 +0300
+@@ -67,6 +67,7 @@
+ NFPROTO_BRIDGE = 7,
+ NFPROTO_IPV6 = 10,
+ NFPROTO_DECNET = 12,
++ NFPROTO_BUS,
+ NFPROTO_NUMPROTO,
+ };
+
+Index: git/include/linux/security.h
+===================================================================
+--- git.orig/include/linux/security.h 2012-10-05 12:12:21.000000000 +0300
++++ git/include/linux/security.h 2012-10-05 13:07:01.000000000 +0300
+@@ -1578,6 +1578,8 @@
+
+ #ifdef CONFIG_SECURITY_NETWORK
+ int (*unix_stream_connect) (struct sock *sock, struct sock *other, struct sock *newsk);
++ int (*bus_connect) (struct sock *sock, struct sock *other,
++ struct sock *newsk);
+ int (*unix_may_send) (struct socket *sock, struct socket *other);
+
+ int (*socket_create) (int family, int type, int protocol, int kern);
+@@ -2517,6 +2519,8 @@
+ #ifdef CONFIG_SECURITY_NETWORK
+
+ int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk);
++int security_bus_connect(struct sock *sock, struct sock *other,
++ struct sock *newsk);
+ int security_unix_may_send(struct socket *sock, struct socket *other);
+ int security_socket_create(int family, int type, int protocol, int kern);
+ int security_socket_post_create(struct socket *sock, int family,
+@@ -2564,6 +2568,13 @@
+ return 0;
+ }
+
++static inline int security_bus_connect(struct socket *sock,
++ struct sock *other,
++ struct sock *newsk)
++{
++return 0;
++}
++
+ static inline int security_unix_may_send(struct socket *sock,
+ struct socket *other)
+ {
+Index: git/include/linux/socket.h
+===================================================================
+--- git.orig/include/linux/socket.h 2012-10-05 12:12:21.000000000 +0300
++++ git/include/linux/socket.h 2012-10-05 13:11:59.000000000 +0300
+@@ -196,7 +196,8 @@
+ #define AF_ALG 38 /* Algorithm sockets */
+ #define AF_NFC 39 /* NFC sockets */
+ #define AF_RPMSG 40 /* Remote-processor messaging */
+-#define AF_MAX 41 /* For now.. */
++#define AF_BUS 41/* BUS sockets*/
++#define AF_MAX 42/* For now.. */
+
+ /* Protocol families, same as address families. */
+ #define PF_UNSPEC AF_UNSPEC
+@@ -239,6 +240,7 @@
+ #define PF_CAIF AF_CAIF
+ #define PF_ALG AF_ALG
+ #define PF_NFC AF_NFC
++#define PF_BUS AF_BUS
+ #define PF_RPMSG AF_RPMSG
+ #define PF_MAX AF_MAX
+
+@@ -315,6 +317,7 @@
+ #define SOL_CAIF 278
+ #define SOL_ALG 279
+ #define SOL_RPMSG 280
++#define SOL_BUS 281
+
+ /* IPX options */
+ #define IPX_TYPE 1
+Index: git/include/net/af_bus.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/include/net/af_bus.h 2012-10-05 13:18:00.000000000 +0300
+@@ -0,0 +1,273 @@
++/*
++ * Copyright (c) 2012, GENIVI Alliance
++ *
++ * Authors: Javier Martinez Canillas, <javier.martinez@collabora.co.uk>
++ * Alban Crequy, <alban.crequy@collabora.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * Based on BSD Unix domain sockets (net/unix).
++ */
++
++#ifndef __LINUX_NET_AFBUS_H
++#define __LINUX_NET_AFBUS_H
++
++#include <linux/socket.h>
++#include <linux/bus.h>
++#include <linux/mutex.h>
++#include <net/sock.h>
++#include <net/tcp_states.h>
++
++extern void bus_inflight(struct file *fp);
++extern void bus_notinflight(struct file *fp);
++extern void bus_gc(void);
++extern void wait_for_bus_gc(void);
++extern struct sock *bus_get_socket(struct file *filp);
++extern struct sock *bus_peer_get(struct sock *);
++
++#define BUS_HASH_SIZE 256
++
++extern spinlock_t bus_address_lock;
++extern struct hlist_head bus_address_table[BUS_HASH_SIZE];
++
++#define BUS_MAX_QLEN 10
++#define BUS_MASTER_ADDR 0x0
++#define BUS_PREFIX_BITS 16
++#define BUS_CLIENT_BITS 48
++#define BUS_PREFIX_MASK 0xffff000000000000
++#define BUS_CLIENT_MASK 0x0000ffffffffffff
++
++/* AF_BUS socket options */
++#define BUS_ADD_ADDR 1
++#define BUS_JOIN_BUS 2
++#define BUS_DEL_ADDR 3
++#define BUS_SET_EAVESDROP 4
++#define BUS_UNSET_EAVESDROP 5
++#define BUS_SET_SENDBUF 6
++#define BUS_SET_MAXQLEN 7
++#define BUS_GET_QLENFULL 8
++
++/* Connection and socket states */
++enum {
++ BUS_ESTABLISHED = TCP_ESTABLISHED,
++ BUS_CLOSE = TCP_CLOSE,
++ BUS_LISTEN = TCP_LISTEN,
++ BUS_MAX_STATES
++};
++
++#define NF_BUS_SENDING 1
++
++extern unsigned int bus_tot_inflight;
++extern spinlock_t bus_table_lock;
++extern struct hlist_head bus_socket_table[BUS_HASH_SIZE + 1];
++
++/**
++ * struct bus_address - an af_bus address associated with an af_bus sock
++ * @refcnt: address reference counter
++ * @len: address length
++ * @hash: address hash value
++ * @addr_node: member of struct bus_sock.addr_list
++ * @table_node: member of struct hlist_head bus_address_table[hash]
++ * @sock: the af_bus sock that owns this address
++ * @name: the socket address for this address
++ */
++struct bus_address {
++ atomic_t refcnt;
++ int len;
++ unsigned hash;
++ struct hlist_node addr_node;
++ struct hlist_node table_node;
++ struct sock *sock;
++ struct sockaddr_bus name[0];
++};
++
++/**
++ * struct bus_send_context - sending context for an socket buffer
++ * @sender_socket: the sender socket associated with this sk_buff
++ * @siocb: used to send ancillary data
++ * @timeo: sending timeout
++ * @max_level: file descriptor passing maximum recursion level
++ * @namelen: length of socket address name
++ * @hash: socket name hash value
++ * @other: destination sock
++ * @sender: sender socket address name
++ * @recipient: recipient socket address name
++ * @authenticated: flag whether the sock already joined the bus
++ * @bus_master_side: flag whether the sock is an accepted socket
++ * @to_master: flag whether the destination is the bus master
++ * @multicast: flag whether the destination is a multicast address
++ * @deliver: flag whether the skb has to be delivered
++ * @eavesdropper: flag whether the sock is allowed to eavesdrop
++ * @main_recipient: flag whether the sock is the main recipient
++ */
++struct bus_send_context {
++ struct socket *sender_socket;
++ struct sock_iocb *siocb;
++ long timeo;
++ int max_level;
++ int namelen;
++ unsigned hash;
++ struct sock *other;
++ struct sockaddr_bus *sender;
++ struct sockaddr_bus *recipient;
++ unsigned int authenticated:1;
++ unsigned int bus_master_side:1;
++ unsigned int to_master:1;
++ unsigned int multicast:1;
++ unsigned int deliver:1;
++ unsigned int eavesdropper:1;
++ unsigned int main_recipient:1;
++};
++
++/**
++ * struct bus_skb_parms - socket buffer parameters
++ * @pid: process id
++ * @cred: skb credentials
++ * @fp: passed file descriptors
++ * @secid: security id
++ * @sendctx: skb sending context
++ */
++struct bus_skb_parms {
++ struct pid *pid;
++ const struct cred *cred;
++ struct scm_fp_list *fp;
++#ifdef CONFIG_SECURITY_NETWORK
++ u32 secid;
++#endif
++ struct bus_send_context *sendctx;
++};
++
++#define BUSCB(skb) (*(struct bus_skb_parms *)&((skb)->cb))
++#define BUSSID(skb) (&BUSCB((skb)).secid)
++
++#define bus_state_lock(s) spin_lock(&bus_sk(s)->lock)
++#define bus_state_unlock(s) spin_unlock(&bus_sk(s)->lock)
++#define bus_state_lock_nested(s) \
++ spin_lock_nested(&bus_sk(s)->lock, \
++ SINGLE_DEPTH_NESTING)
++
++/**
++ * struct bus - a communication bus
++ * @master: the bus master sock
++ * @peers: list of struct bus_sock.bus_node allowed to join the bus
++ * @lock: protect peers concurrent access
++ * @send_lock: enforce atomic multicast delivery
++ * @kref: bus reference counter
++ * @addr_cnt: address number counter to assign prefix 0x0000 addresses
++ * @eavesdropper_cnt: eavesdroppers counter
++ */
++struct bus {
++ struct sock *master;
++ struct hlist_head peers;
++ spinlock_t lock;
++ spinlock_t send_lock;
++ struct kref kref;
++ atomic64_t addr_cnt;
++ atomic64_t eavesdropper_cnt;
++};
++
++/**
++ * struct bus_sock - an af_bus socket
++ * @sk: associated sock
++ * @addr: sock principal address
++ * @addr_list: list of struct bus_address.addr_node
++ * @path: sock path name
++ * @readlock: protect from concurrent reading
++ * @peer: peer sock
++ * @other: the listening sock
++ * @link: list of candidates for garbage collection
++ * @inflight: number of times the file descriptor is in flight
++ * @lock: protect the sock from concurrent access
++ * @gc_candidate: flag whether the is a candidate for gc
++ * @gc_maybe_cycle: flag whether could be a cyclic reference
++ * @recursion_level: file passing current recursion level
++ * @peer_wq: peer sock wait queue
++ * @bus: bus that this sock belongs to
++ * @bus_master: flag whether the sock is the bus master
++ * @bus_master_side: flag whether is an accepted socket
++ * @authenticated: flag whether the sock joined the bus
++ * @eavesdropper: flag whether the sock is allowed to eavesdrop
++ * @bus_node: member of struct bus.peers list of joined socks
++ */
++struct bus_sock {
++ /* WARNING: sk has to be the first member */
++ struct sock sk;
++ struct bus_address *addr;
++ struct hlist_head addr_list;
++ struct path path;
++ struct mutex readlock;
++ struct sock *peer;
++ struct sock *other;
++ struct list_head link;
++ atomic_long_t inflight;
++ spinlock_t lock;
++ unsigned int gc_candidate:1;
++ unsigned int gc_maybe_cycle:1;
++ unsigned char recursion_level;
++ struct socket_wq peer_wq;
++ struct bus *bus;
++ bool bus_master;
++ bool bus_master_side;
++ bool authenticated;
++ bool eavesdropper;
++ struct hlist_node bus_node;
++};
++#define bus_sk(__sk) ((struct bus_sock *)__sk)
++
++#define peer_wait peer_wq.wait
++
++/**
++ * bus_same_bus - Test if two socket address belongs to the same bus
++ * @sbusaddr1: socket address name
++ * @sbusaddr2: socket address name
++ */
++static inline bool bus_same_bus(struct sockaddr_bus *sbusaddr1,
++ struct sockaddr_bus *sbusaddr2)
++{
++ int offset;
++
++ if (sbusaddr1->sbus_path[0] != sbusaddr2->sbus_path[0])
++ return false;
++
++ /*
++ * abstract path names start with a null byte character,
++ * so they have to be compared starting at the second char.
++ */
++ offset = (sbusaddr1->sbus_path[0] == '\0');
++
++ return !strncmp(sbusaddr1->sbus_path + offset,
++ sbusaddr2->sbus_path + offset,
++ BUS_PATH_MAX);
++}
++
++static inline unsigned int bus_hash_fold(__wsum n)
++{
++ unsigned int hash = (__force unsigned int)n;
++ hash ^= hash>>16;
++ hash ^= hash>>8;
++ return hash&(BUS_HASH_SIZE-1);
++}
++
++static inline unsigned int bus_compute_hash(struct bus_addr addr)
++{
++ return bus_hash_fold(csum_partial((void *)&addr, sizeof(addr), 0));
++}
++
++long bus_inq_len(struct sock *sk);
++long bus_outq_len(struct sock *sk);
++
++#ifdef CONFIG_SYSCTL
++extern int bus_sysctl_register(struct net *net);
++extern void bus_sysctl_unregister(struct net *net);
++#else
++static inline int bus_sysctl_register(struct net *net) { return 0; }
++static inline void bus_sysctl_unregister(struct net *net) {}
++#endif
++
++bool bus_can_write(struct net *net, struct sockaddr_bus *addr, int len,
++ int protocol);
++
++#endif /* __LINUX_NET_AFBUS_H */
+Index: git/net/Kconfig
+===================================================================
+--- git.orig/net/Kconfig 2012-10-05 12:12:33.000000000 +0300
++++ git/net/Kconfig 2012-10-05 13:18:58.000000000 +0300
+@@ -47,6 +47,7 @@
+
+ source "net/packet/Kconfig"
+ source "net/unix/Kconfig"
++source "net/bus/Kconfig"
+ source "net/xfrm/Kconfig"
+ source "net/iucv/Kconfig"
+
+Index: git/net/Makefile
+===================================================================
+--- git.orig/net/Makefile 2012-10-05 12:12:33.000000000 +0300
++++ git/net/Makefile 2012-10-05 13:19:47.000000000 +0300
+@@ -19,6 +19,7 @@
+ obj-$(CONFIG_INET) += ipv4/
+ obj-$(CONFIG_XFRM) += xfrm/
+ obj-$(CONFIG_UNIX) += unix/
++obj-$(CONFIG_AF_BUS) += bus/
+ obj-$(CONFIG_NET) += ipv6/
+ obj-$(CONFIG_PACKET) += packet/
+ obj-$(CONFIG_NET_KEY) += key/
+Index: git/net/bus/Kconfig
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/bus/Kconfig 2012-10-05 13:22:11.000000000 +0300
+@@ -0,0 +1,15 @@
++#
++# Bus Domain Sockets
++#
++
++config AF_BUS
++ tristate "Bus domain sockets (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ ---help---
++ If you say Y here, you will include support for Bus domain sockets.
++ These sockets are used to create communication buses for IPC.
++
++ To compile this driver as a module, choose M here: the module will be
++ called bus.
++
++ Say N unless you know what you are doing.
+Index: git/net/bus/Makefile
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/bus/Makefile 2012-10-05 13:22:50.000000000 +0300
+@@ -0,0 +1,7 @@
++#
++# Makefile for the Linux bus domain socket layer.
++#
++
++obj-$(CONFIG_AF_BUS) += af-bus.o
++
++af-bus-y := af_bus.o garbage.o
+Index: git/net/bus/af_bus.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/bus/af_bus.c 2012-10-05 13:35:20.000000000 +0300
+@@ -0,0 +1,2688 @@
++/*
++ * Implementation of Bus domain sockets.
++ *
++ * Copyright (c) 2012, GENIVI Alliance
++ *
++ * Authors: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
++ * Alban Crequy <alban.crequy@collabora.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * Based on BSD Unix domain sockets (net/unix).
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/stat.h>
++#include <linux/dcache.h>
++#include <linux/namei.h>
++#include <linux/socket.h>
++#include <linux/bus.h>
++#include <linux/fcntl.h>
++#include <linux/termios.h>
++#include <linux/sockios.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/fs.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <net/net_namespace.h>
++#include <net/sock.h>
++#include <net/af_bus.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <net/scm.h>
++#include <linux/init.h>
++#include <linux/poll.h>
++#include <linux/rtnetlink.h>
++#include <linux/mount.h>
++#include <net/checksum.h>
++#include <linux/security.h>
++
++struct hlist_head bus_socket_table[BUS_HASH_SIZE + 1];
++EXPORT_SYMBOL_GPL(bus_socket_table);
++struct hlist_head bus_address_table[BUS_HASH_SIZE];
++EXPORT_SYMBOL_GPL(bus_address_table);
++DEFINE_SPINLOCK(bus_table_lock);
++DEFINE_SPINLOCK(bus_address_lock);
++EXPORT_SYMBOL_GPL(bus_address_lock);
++static atomic_long_t bus_nr_socks;
++
++#define bus_sockets_unbound (&bus_socket_table[BUS_HASH_SIZE])
++
++#define BUS_ABSTRACT(sk) (bus_sk(sk)->addr->hash != BUS_HASH_SIZE)
++
++#ifdef CONFIG_SECURITY_NETWORK
++static void bus_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
++{
++ memcpy(BUSSID(skb), &scm->secid, sizeof(u32));
++}
++
++static inline void bus_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
++{
++ scm->secid = *BUSSID(skb);
++}
++#else
++static inline void bus_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
++{ }
++
++static inline void bus_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
++{ }
++#endif /* CONFIG_SECURITY_NETWORK */
++
++/*
++ * SMP locking strategy:
++ * bus_socket_table hash table is protected with spinlock bus_table_lock
++ * bus_address_table hash table is protected with spinlock bus_address_lock
++ * each bus is protected by a separate spin lock.
++ * multicast atomic sending is protected by a separate spin lock.
++ * each socket state is protected by a separate spin lock.
++ * each socket address is protected by a separate spin lock.
++ *
++ * When holding more than one lock, use the following hierarchy:
++ * - bus_table_lock.
++ * - bus_address_lock.
++ * - socket lock.
++ * - bus lock.
++ * - bus send_lock.
++ * - sock address lock.
++ */
++
++#define bus_peer(sk) (bus_sk(sk)->peer)
++
++static inline int bus_our_peer(struct sock *sk, struct sock *osk)
++{
++ return bus_peer(osk) == sk;
++}
++
++static inline int bus_recvq_full(struct sock const *sk)
++{
++ return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
++}
++
++static inline u16 bus_addr_prefix(struct sockaddr_bus *busaddr)
++{
++ return (busaddr->sbus_addr.s_addr & BUS_PREFIX_MASK) >> BUS_CLIENT_BITS;
++}
++
++static inline u64 bus_addr_client(struct sockaddr_bus *sbusaddr)
++{
++ return sbusaddr->sbus_addr.s_addr & BUS_CLIENT_MASK;
++}
++
++static inline bool bus_mc_addr(struct sockaddr_bus *sbusaddr)
++{
++ return bus_addr_client(sbusaddr) == BUS_CLIENT_MASK;
++}
++
++struct sock *bus_peer_get(struct sock *s)
++{
++ struct sock *peer;
++
++ bus_state_lock(s);
++ peer = bus_peer(s);
++ if (peer)
++ sock_hold(peer);
++ bus_state_unlock(s);
++ return peer;
++}
++EXPORT_SYMBOL_GPL(bus_peer_get);
++
++static inline void bus_release_addr(struct bus_address *addr)
++{
++ if (atomic_dec_and_test(&addr->refcnt))
++ kfree(addr);
++}
++
++/*
++ * Check bus socket name:
++ * - should be not zero length.
++ * - if started by not zero, should be NULL terminated (FS object)
++ * - if started by zero, it is abstract name.
++ */
++
++static int bus_mkname(struct sockaddr_bus *sbusaddr, int len,
++ unsigned int *hashp)
++{
++ int offset = (sbusaddr->sbus_path[0] == '\0');
++
++ if (len <= sizeof(short) || len > sizeof(*sbusaddr))
++ return -EINVAL;
++ if (!sbusaddr || sbusaddr->sbus_family != AF_BUS)
++ return -EINVAL;
++
++ len = strnlen(sbusaddr->sbus_path + offset, BUS_PATH_MAX) + 1 +
++ sizeof(__kernel_sa_family_t) +
++ sizeof(struct bus_addr);
++
++ *hashp = bus_compute_hash(sbusaddr->sbus_addr);
++ return len;
++}
++
++static void __bus_remove_address(struct bus_address *addr)
++{
++ hlist_del(&addr->table_node);
++}
++
++static void __bus_insert_address(struct hlist_head *list,
++ struct bus_address *addr)
++{
++ hlist_add_head(&addr->table_node, list);
++}
++
++static inline void bus_remove_address(struct bus_address *addr)
++{
++ spin_lock(&bus_address_lock);
++ __bus_remove_address(addr);
++ spin_unlock(&bus_address_lock);
++}
++
++static inline void bus_insert_address(struct hlist_head *list,
++ struct bus_address *addr)
++{
++ spin_lock(&bus_address_lock);
++ __bus_insert_address(list, addr);
++ spin_unlock(&bus_address_lock);
++}
++
++static void __bus_remove_socket(struct sock *sk)
++{
++ sk_del_node_init(sk);
++}
++
++static void __bus_insert_socket(struct hlist_head *list, struct sock *sk)
++{
++ WARN_ON(!sk_unhashed(sk));
++ sk_add_node(sk, list);
++}
++
++static inline void bus_remove_socket(struct sock *sk)
++{
++ spin_lock(&bus_table_lock);
++ __bus_remove_socket(sk);
++ spin_unlock(&bus_table_lock);
++}
++
++static inline void bus_insert_socket(struct hlist_head *list, struct sock *sk)
++{
++ spin_lock(&bus_table_lock);
++ __bus_insert_socket(list, sk);
++ spin_unlock(&bus_table_lock);
++}
++
++static inline bool __bus_has_prefix(struct sock *sk, u16 prefix)
++{
++ struct bus_sock *u = bus_sk(sk);
++ struct bus_address *addr;
++ struct hlist_node *node;
++ bool ret = false;
++
++ hlist_for_each_entry(addr, node, &u->addr_list, addr_node) {
++ if (bus_addr_prefix(addr->name) == prefix)
++ ret = true;
++ }
++
++ return ret;
++}
++
++static inline bool bus_has_prefix(struct sock *sk, u16 prefix)
++{
++ bool ret;
++
++ bus_state_lock(sk);
++ ret = __bus_has_prefix(sk, prefix);
++ bus_state_unlock(sk);
++
++ return ret;
++}
++
++static inline bool __bus_eavesdropper(struct sock *sk, u16 condition)
++{
++ struct bus_sock *u = bus_sk(sk);
++
++ return u->eavesdropper;
++}
++
++static inline bool bus_eavesdropper(struct sock *sk, u16 condition)
++{
++ bool ret;
++
++ bus_state_lock(sk);
++ ret = __bus_eavesdropper(sk, condition);
++ bus_state_unlock(sk);
++
++ return ret;
++}
++
++static inline bool bus_has_prefix_eavesdropper(struct sock *sk, u16 prefix)
++{
++ bool ret;
++
++ bus_state_lock(sk);
++ ret = __bus_has_prefix(sk, prefix) || __bus_eavesdropper(sk, 0);
++ bus_state_unlock(sk);
++
++ return ret;
++}
++
++static inline struct bus_address *__bus_get_address(struct sock *sk,
++ struct bus_addr *sbus_addr)
++{
++ struct bus_sock *u = bus_sk(sk);
++ struct bus_address *addr = NULL;
++ struct hlist_node *node;
++
++ hlist_for_each_entry(addr, node, &u->addr_list, addr_node) {
++ if (addr->name->sbus_addr.s_addr == sbus_addr->s_addr)
++ return addr;
++ }
++
++ return NULL;
++}
++
++static inline struct bus_address *bus_get_address(struct sock *sk,
++ struct bus_addr *sbus_addr)
++{
++ struct bus_address *addr;
++
++ bus_state_lock(sk);
++ addr = __bus_get_address(sk, sbus_addr);
++ bus_state_unlock(sk);
++
++ return addr;
++}
++
++static struct sock *__bus_find_socket_byname(struct net *net,
++ struct sockaddr_bus *sbusname,
++ int len, unsigned int hash)
++{
++ struct sock *s;
++ struct hlist_node *node;
++
++ sk_for_each(s, node, &bus_socket_table[hash]) {
++ struct bus_sock *u = bus_sk(s);
++
++ if (!net_eq(sock_net(s), net))
++ continue;
++
++ if (u->addr->len == len &&
++ !memcmp(u->addr->name, sbusname, len))
++ return s;
++ }
++
++ return NULL;
++}
++
++static inline struct sock *bus_find_socket_byname(struct net *net,
++ struct sockaddr_bus *sbusname,
++ int len, unsigned int hash)
++{
++ struct sock *s;
++
++ spin_lock(&bus_table_lock);
++ s = __bus_find_socket_byname(net, sbusname, len, hash);
++ if (s)
++ sock_hold(s);
++ spin_unlock(&bus_table_lock);
++ return s;
++}
++
++static struct sock *__bus_find_socket_byaddress(struct net *net,
++ struct sockaddr_bus *sbusname,
++ int len, int protocol,
++ unsigned int hash)
++{
++ struct sock *s;
++ struct bus_address *addr;
++ struct hlist_node *node;
++ struct bus_sock *u;
++ int offset = (sbusname->sbus_path[0] == '\0');
++ int path_len = strnlen(sbusname->sbus_path + offset, BUS_PATH_MAX);
++
++ len = path_len + 1 + sizeof(__kernel_sa_family_t) +
++ sizeof(struct bus_addr);
++
++ hlist_for_each_entry(addr, node, &bus_address_table[hash],
++ table_node) {
++ s = addr->sock;
++ u = bus_sk(s);
++
++ if (s->sk_protocol != protocol)
++ continue;
++
++ if (!net_eq(sock_net(s), net))
++ continue;
++
++ if (addr->len == len &&
++ addr->name->sbus_family == sbusname->sbus_family &&
++ addr->name->sbus_addr.s_addr == sbusname->sbus_addr.s_addr
++ && bus_same_bus(addr->name, sbusname))
++ goto found;
++ }
++ s = NULL;
++found:
++ return s;
++}
++
++static inline struct sock *bus_find_socket_byaddress(struct net *net,
++ struct sockaddr_bus *name,
++ int len, int protocol,
++ unsigned int hash)
++{
++ struct sock *s;
++
++ spin_lock(&bus_address_lock);
++ s = __bus_find_socket_byaddress(net, name, len, protocol, hash);
++ if (s)
++ sock_hold(s);
++ spin_unlock(&bus_address_lock);
++ return s;
++}
++
++static inline int bus_writable(struct sock *sk)
++{
++ return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
++}
++
++static void bus_write_space(struct sock *sk)
++{
++ struct bus_sock *u = bus_sk(sk);
++ struct bus_sock *p;
++ struct hlist_node *node;
++ struct socket_wq *wq;
++
++ if (bus_writable(sk)) {
++ rcu_read_lock();
++ wq = rcu_dereference(sk->sk_wq);
++ if (wq_has_sleeper(wq))
++ wake_up_interruptible_sync_poll(&wq->wait,
++ POLLOUT | POLLWRNORM | POLLWRBAND);
++ sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
++ rcu_read_unlock();
++
++ if (u && u->bus) {
++ spin_lock(&u->bus->lock);
++ hlist_for_each_entry(p, node, &u->bus->peers,
++ bus_node) {
++ wake_up_interruptible_sync_poll(sk_sleep(&p->sk),
++ POLLOUT |
++ POLLWRNORM |
++ POLLWRBAND);
++ sk_wake_async(&p->sk, SOCK_WAKE_SPACE,
++ POLL_OUT);
++ }
++ spin_unlock(&u->bus->lock);
++ }
++ }
++}
++
++static void bus_bus_release(struct kref *kref)
++{
++ struct bus *bus;
++
++ bus = container_of(kref, struct bus, kref);
++
++ kfree(bus);
++}
++
++static void bus_sock_destructor(struct sock *sk)
++{
++ struct bus_sock *u = bus_sk(sk);
++
++ skb_queue_purge(&sk->sk_receive_queue);
++
++ WARN_ON(atomic_read(&sk->sk_wmem_alloc));
++ WARN_ON(!sk_unhashed(sk));
++ WARN_ON(sk->sk_socket);
++ if (!sock_flag(sk, SOCK_DEAD)) {
++ pr_info("Attempt to release alive bus socket: %p\n", sk);
++ return;
++ }
++
++ if (u->bus) {
++ kref_put(&u->bus->kref, bus_bus_release);
++ u->bus = NULL;
++ }
++
++ atomic_long_dec(&bus_nr_socks);
++ local_bh_disable();
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
++ local_bh_enable();
++#ifdef BUS_REFCNT_DEBUG
++ pr_debug("BUS %p is destroyed, %ld are still alive.\n", sk,
++ atomic_long_read(&bus_nr_socks));
++#endif
++}
++
++static int bus_release_sock(struct sock *sk, int embrion)
++{
++ struct bus_sock *u = bus_sk(sk);
++ struct path path;
++ struct sock *skpair;
++ struct sk_buff *skb;
++ int state;
++ struct bus_address *addr;
++ struct hlist_node *node, *tmp;
++
++ bus_remove_socket(sk);
++
++ if (u->bus && u->authenticated &&
++ !u->bus_master && !u->bus_master_side) {
++ spin_lock(&u->bus->lock);
++ hlist_del(&u->bus_node);
++ if (u->eavesdropper)
++ atomic64_dec(&u->bus->eavesdropper_cnt);
++ spin_unlock(&u->bus->lock);
++ }
++
++ /* Clear state */
++ bus_state_lock(sk);
++ sock_orphan(sk);
++ sk->sk_shutdown = SHUTDOWN_MASK;
++ path = u->path;
++ u->path.dentry = NULL;
++ u->path.mnt = NULL;
++ state = sk->sk_state;
++ sk->sk_state = BUS_CLOSE;
++
++ if (u->bus_master)
++ u->bus->master = NULL;
++
++ if (u->bus_master_side) {
++ bus_release_addr(u->addr);
++ u->addr = NULL;
++ } else {
++ u->addr = NULL;
++
++ spin_lock(&bus_address_lock);
++ hlist_for_each_entry_safe(addr, node, tmp, &u->addr_list,
++ addr_node) {
++ hlist_del(&addr->addr_node);
++ __bus_remove_address(addr);
++ bus_release_addr(addr);
++ }
++ spin_unlock(&bus_address_lock);
++ }
++
++ bus_state_unlock(sk);
++
++ wake_up_interruptible_all(&u->peer_wait);
++
++ skpair = bus_peer(sk);
++
++ if (skpair != NULL) {
++ bus_state_lock(skpair);
++ /* No more writes */
++ skpair->sk_shutdown = SHUTDOWN_MASK;
++ if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
++ skpair->sk_err = ECONNRESET;
++ bus_state_unlock(skpair);
++ skpair->sk_state_change(skpair);
++ sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
++ sock_put(skpair); /* It may now die */
++ bus_peer(sk) = NULL;
++ }
++
++ /* Try to flush out this socket. Throw out buffers at least */
++
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (state == BUS_LISTEN)
++ bus_release_sock(skb->sk, 1);
++ /* passed fds are erased in the kfree_skb hook */
++ kfree_skb(skb);
++ }
++
++ if (path.dentry)
++ path_put(&path);
++
++ sock_put(sk);
++
++ /* ---- Socket is dead now and most probably destroyed ---- */
++
++ if (bus_tot_inflight)
++ bus_gc(); /* Garbage collect fds */
++
++ return 0;
++}
++
++static void init_peercred(struct sock *sk)
++{
++ put_pid(sk->sk_peer_pid);
++ if (sk->sk_peer_cred)
++ put_cred(sk->sk_peer_cred);
++ sk->sk_peer_pid = get_pid(task_tgid(current));
++ sk->sk_peer_cred = get_current_cred();
++}
++
++static void copy_peercred(struct sock *sk, struct sock *peersk)
++{
++ put_pid(sk->sk_peer_pid);
++ if (sk->sk_peer_cred)
++ put_cred(sk->sk_peer_cred);
++ sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
++ sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
++}
++
++static int bus_listen(struct socket *sock, int backlog)
++{
++ int err;
++ struct sock *sk = sock->sk;
++ struct bus_sock *u = bus_sk(sk);
++ struct pid *old_pid = NULL;
++ const struct cred *old_cred = NULL;
++
++ err = -EINVAL;
++ if (!u->addr || !u->bus_master)
++ goto out; /* Only listens on an bound an master socket */
++ bus_state_lock(sk);
++ if (sk->sk_state != BUS_CLOSE && sk->sk_state != BUS_LISTEN)
++ goto out_unlock;
++ if (backlog > sk->sk_max_ack_backlog)
++ wake_up_interruptible_all(&u->peer_wait);
++ sk->sk_max_ack_backlog = backlog;
++ sk->sk_state = BUS_LISTEN;
++ /* set credentials so connect can copy them */
++ init_peercred(sk);
++ err = 0;
++
++out_unlock:
++ bus_state_unlock(sk);
++ put_pid(old_pid);
++ if (old_cred)
++ put_cred(old_cred);
++out:
++ return err;
++}
++
++static int bus_release(struct socket *);
++static int bus_bind(struct socket *, struct sockaddr *, int);
++static int bus_connect(struct socket *, struct sockaddr *,
++ int addr_len, int flags);
++static int bus_accept(struct socket *, struct socket *, int);
++static int bus_getname(struct socket *, struct sockaddr *, int *, int);
++static unsigned int bus_poll(struct file *, struct socket *,
++ poll_table *);
++static int bus_ioctl(struct socket *, unsigned int, unsigned long);
++static int bus_shutdown(struct socket *, int);
++static int bus_setsockopt(struct socket *, int, int, char __user *,
++ unsigned int);
++static int bus_sendmsg(struct kiocb *, struct socket *,
++ struct msghdr *, size_t);
++static int bus_recvmsg(struct kiocb *, struct socket *,
++ struct msghdr *, size_t, int);
++
++static void bus_set_peek_off(struct sock *sk, int val)
++{
++ struct bus_sock *u = bus_sk(sk);
++
++ mutex_lock(&u->readlock);
++ sk->sk_peek_off = val;
++ mutex_unlock(&u->readlock);
++}
++
++static const struct proto_ops bus_seqpacket_ops = {
++ .family = PF_BUS,
++ .owner = THIS_MODULE,
++ .release = bus_release,
++ .bind = bus_bind,
++ .connect = bus_connect,
++ .socketpair = sock_no_socketpair,
++ .accept = bus_accept,
++ .getname = bus_getname,
++ .poll = bus_poll,
++ .ioctl = bus_ioctl,
++ .listen = bus_listen,
++ .shutdown = bus_shutdown,
++ .setsockopt = bus_setsockopt,
++ .getsockopt = sock_no_getsockopt,
++ .sendmsg = bus_sendmsg,
++ .recvmsg = bus_recvmsg,
++ .mmap = sock_no_mmap,
++ .sendpage = sock_no_sendpage,
++ .set_peek_off = bus_set_peek_off,
++};
++
++static struct proto bus_proto = {
++ .name = "BUS",
++ .owner = THIS_MODULE,
++ .obj_size = sizeof(struct bus_sock),
++};
++
++/*
++ * AF_BUS sockets do not interact with hardware, hence they
++ * dont trigger interrupts - so it's safe for them to have
++ * bh-unsafe locking for their sk_receive_queue.lock. Split off
++ * this special lock-class by reinitializing the spinlock key:
++ */
++static struct lock_class_key af_bus_sk_receive_queue_lock_key;
++
++static struct sock *bus_create1(struct net *net, struct socket *sock)
++{
++ struct sock *sk = NULL;
++ struct bus_sock *u;
++
++ atomic_long_inc(&bus_nr_socks);
++ if (atomic_long_read(&bus_nr_socks) > 2 * get_max_files())
++ goto out;
++
++ sk = sk_alloc(net, PF_BUS, GFP_KERNEL, &bus_proto);
++ if (!sk)
++ goto out;
++
++ sock_init_data(sock, sk);
++ lockdep_set_class(&sk->sk_receive_queue.lock,
++ &af_bus_sk_receive_queue_lock_key);
++
++ sk->sk_write_space = bus_write_space;
++ sk->sk_max_ack_backlog = BUS_MAX_QLEN;
++ sk->sk_destruct = bus_sock_destructor;
++ u = bus_sk(sk);
++ u->path.dentry = NULL;
++ u->path.mnt = NULL;
++ u->bus = NULL;
++ u->bus_master = false;
++ u->authenticated = false;
++ u->eavesdropper = false;
++ spin_lock_init(&u->lock);
++ atomic_long_set(&u->inflight, 0);
++ INIT_LIST_HEAD(&u->link);
++ INIT_HLIST_HEAD(&u->addr_list);
++ INIT_HLIST_NODE(&u->bus_node);
++ mutex_init(&u->readlock); /* single task reading lock */
++ init_waitqueue_head(&u->peer_wait);
++ bus_insert_socket(bus_sockets_unbound, sk);
++out:
++ if (sk == NULL)
++ atomic_long_dec(&bus_nr_socks);
++ else {
++ local_bh_disable();
++ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
++ local_bh_enable();
++ }
++ return sk;
++}
++
++static int bus_create(struct net *net, struct socket *sock, int protocol,
++ int kern)
++{
++ struct sock *sk;
++
++ if (protocol < BUS_PROTO_NONE || protocol > BUS_PROTO_DBUS)
++ return -EPROTONOSUPPORT;
++
++ if (protocol != BUS_PROTO_NONE)
++ request_module("net-pf-%d-proto-%d", PF_BUS, protocol);
++
++ sock->state = SS_UNCONNECTED;
++
++ if (sock->type == SOCK_SEQPACKET)
++ sock->ops = &bus_seqpacket_ops;
++ else
++ return -ESOCKTNOSUPPORT;
++
++ sk = bus_create1(net, sock);
++ if (!sk)
++ return -ENOMEM;
++
++ sk->sk_protocol = protocol;
++
++ return 0;
++}
++
++static int bus_release(struct socket *sock)
++{
++ struct sock *sk = sock->sk;
++
++ if (!sk)
++ return 0;
++
++ sock->sk = NULL;
++
++ return bus_release_sock(sk, 0);
++}
++
++static struct sock *bus_find_other(struct net *net,
++ struct sockaddr_bus *sbusname, int len,
++ int protocol, unsigned int hash, int *error)
++{
++ struct sock *u;
++ struct path path;
++ int err = 0;
++
++ if (sbusname->sbus_path[0]) {
++ struct inode *inode;
++ err = kern_path(sbusname->sbus_path, LOOKUP_FOLLOW, &path);
++ if (err)
++ goto fail;
++ inode = path.dentry->d_inode;
++ err = inode_permission(inode, MAY_WRITE);
++ if (err)
++ goto put_fail;
++
++ err = -ECONNREFUSED;
++ if (!S_ISSOCK(inode->i_mode))
++ goto put_fail;
++ u = bus_find_socket_byaddress(net, sbusname, len, protocol,
++ hash);
++ if (!u)
++ goto put_fail;
++
++ touch_atime(&path);
++ path_put(&path);
++
++ } else {
++ err = -ECONNREFUSED;
++ u = bus_find_socket_byaddress(net, sbusname, len, protocol, hash);
++ if (u) {
++ struct dentry *dentry;
++ dentry = bus_sk(u)->path.dentry;
++ if (dentry)
++ touch_atime(&bus_sk(u)->path);
++ } else
++ goto fail;
++ }
++
++ return u;
++
++put_fail:
++ path_put(&path);
++fail:
++ *error = err;
++ return NULL;
++}
++
++
++static int bus_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
++{
++ struct sock *sk = sock->sk;
++ struct net *net = sock_net(sk);
++ struct bus_sock *u = bus_sk(sk);
++ struct sockaddr_bus *sbusaddr = (struct sockaddr_bus *)uaddr;
++ char *sbus_path = sbusaddr->sbus_path;
++ struct dentry *dentry = NULL;
++ struct path path;
++ int err;
++ unsigned int hash;
++ struct bus_address *addr;
++ struct hlist_head *list;
++ struct bus *bus;
++
++ err = -EINVAL;
++ if (sbusaddr->sbus_family != AF_BUS)
++ goto out;
++
++ /* If the address is available, the socket is the bus master */
++ sbusaddr->sbus_addr.s_addr = BUS_MASTER_ADDR;
++
++ err = bus_mkname(sbusaddr, addr_len, &hash);
++ if (err < 0)
++ goto out;
++ addr_len = err;
++
++ mutex_lock(&u->readlock);
++
++ err = -EINVAL;
++ if (u->addr)
++ goto out_up;
++
++ err = -ENOMEM;
++ addr = kzalloc(sizeof(*addr) + sizeof(struct sockaddr_bus), GFP_KERNEL);
++ if (!addr)
++ goto out_up;
++
++ memcpy(addr->name, sbusaddr, sizeof(struct sockaddr_bus));
++ addr->len = addr_len;
++ addr->hash = hash;
++ atomic_set(&addr->refcnt, 1);
++ addr->sock = sk;
++ INIT_HLIST_NODE(&addr->addr_node);
++ INIT_HLIST_NODE(&addr->table_node);
++
++ if (sbus_path[0]) {
++ umode_t mode;
++ err = 0;
++ /*
++ * Get the parent directory, calculate the hash for last
++ * component.
++ */
++ dentry = kern_path_create(AT_FDCWD, sbus_path, &path, 0);
++ err = PTR_ERR(dentry);
++ if (IS_ERR(dentry))
++ goto out_mknod_parent;
++
++ /*
++ * All right, let's create it.
++ */
++ mode = S_IFSOCK |
++ (SOCK_INODE(sock)->i_mode & ~current_umask());
++ err = mnt_want_write(path.mnt);
++ if (err)
++ goto out_mknod_dput;
++ err = security_path_mknod(&path, dentry, mode, 0);
++ if (err)
++ goto out_mknod_drop_write;
++ err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
++out_mknod_drop_write:
++ mnt_drop_write(path.mnt);
++ if (err)
++ goto out_mknod_dput;
++ mutex_unlock(&path.dentry->d_inode->i_mutex);
++ dput(path.dentry);
++ path.dentry = dentry;
++ }
++
++ err = -ENOMEM;
++ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
++ if (!bus)
++ goto out_unlock;
++
++ spin_lock(&bus_table_lock);
++
++ if (!sbus_path[0]) {
++ err = -EADDRINUSE;
++ if (__bus_find_socket_byname(net, sbusaddr, addr_len, hash)) {
++ bus_release_addr(addr);
++ kfree(bus);
++ goto out_unlock;
++ }
++
++ list = &bus_socket_table[addr->hash];
++ } else {
++ list = &bus_socket_table[dentry->d_inode->i_ino &
++ (BUS_HASH_SIZE-1)];
++ u->path = path;
++ }
++
++ kref_init(&bus->kref);
++ bus->master = sk;
++ INIT_HLIST_HEAD(&bus->peers);
++ spin_lock_init(&bus->lock);
++ spin_lock_init(&bus->send_lock);
++ atomic64_set(&bus->addr_cnt, 0);
++ atomic64_set(&bus->eavesdropper_cnt, 0);
++
++ hlist_add_head(&addr->addr_node, &u->addr_list);
++
++ err = 0;
++ __bus_remove_socket(sk);
++ u->addr = addr;
++ u->bus_master = true;
++ u->bus = bus;
++ __bus_insert_socket(list, sk);
++ bus_insert_address(&bus_address_table[addr->hash], addr);
++
++out_unlock:
++ spin_unlock(&bus_table_lock);
++out_up:
++ mutex_unlock(&u->readlock);
++out:
++ return err;
++
++out_mknod_dput:
++ dput(dentry);
++ mutex_unlock(&path.dentry->d_inode->i_mutex);
++ path_put(&path);
++out_mknod_parent:
++ if (err == -EEXIST)
++ err = -EADDRINUSE;
++ bus_release_addr(addr);
++ goto out_up;
++}
++
++static long bus_wait_for_peer(struct sock *other, long timeo)
++{
++ struct bus_sock *u = bus_sk(other);
++ int sched;
++ DEFINE_WAIT(wait);
++
++ prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
++
++ sched = !sock_flag(other, SOCK_DEAD) &&
++ !(other->sk_shutdown & RCV_SHUTDOWN) &&
++ bus_recvq_full(other);
++
++ bus_state_unlock(other);
++
++ if (sched)
++ timeo = schedule_timeout(timeo);
++
++ finish_wait(&u->peer_wait, &wait);
++ return timeo;
++}
++
++static int bus_connect(struct socket *sock, struct sockaddr *uaddr,
++ int addr_len, int flags)
++{
++ struct sockaddr_bus *sbusaddr = (struct sockaddr_bus *)uaddr;
++ struct sock *sk = sock->sk;
++ struct net *net = sock_net(sk);
++ struct bus_sock *u = bus_sk(sk), *newu, *otheru;
++ struct sock *newsk = NULL;
++ struct sock *other = NULL;
++ struct sk_buff *skb = NULL;
++ struct bus_address *addr = NULL;
++ unsigned int hash;
++ int st;
++ int err;
++ long timeo;
++
++ /* Only connections to the bus master is allowed */
++ sbusaddr->sbus_addr.s_addr = BUS_MASTER_ADDR;
++
++ err = bus_mkname(sbusaddr, addr_len, &hash);
++ if (err < 0)
++ goto out;
++ addr_len = err;
++
++ err = -ENOMEM;
++ addr = kzalloc(sizeof(*addr) + sizeof(struct sockaddr_bus), GFP_KERNEL);
++ if (!addr)
++ goto out;
++
++ atomic_set(&addr->refcnt, 1);
++ INIT_HLIST_NODE(&addr->addr_node);
++ INIT_HLIST_NODE(&addr->table_node);
++
++ timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
++
++ /* First of all allocate resources.
++ If we will make it after state is locked,
++ we will have to recheck all again in any case.
++ */
++
++ err = -ENOMEM;
++
++ /* create new sock for complete connection */
++ newsk = bus_create1(sock_net(sk), NULL);
++ if (newsk == NULL)
++ goto out;
++
++ /* Allocate skb for sending to listening sock */
++ skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
++ if (skb == NULL)
++ goto out;
++
++restart:
++ /* Find listening sock. */
++ other = bus_find_other(net, sbusaddr, addr_len, sk->sk_protocol, hash,
++ &err);
++ if (!other)
++ goto out;
++
++ /* Latch state of peer */
++ bus_state_lock(other);
++
++ /* Apparently VFS overslept socket death. Retry. */
++ if (sock_flag(other, SOCK_DEAD)) {
++ bus_state_unlock(other);
++ sock_put(other);
++ goto restart;
++ }
++
++ err = -ECONNREFUSED;
++ if (other->sk_state != BUS_LISTEN)
++ goto out_unlock;
++ if (other->sk_shutdown & RCV_SHUTDOWN)
++ goto out_unlock;
++
++ if (bus_recvq_full(other)) {
++ err = -EAGAIN;
++ if (!timeo)
++ goto out_unlock;
++
++ timeo = bus_wait_for_peer(other, timeo);
++
++ err = sock_intr_errno(timeo);
++ if (signal_pending(current))
++ goto out;
++ sock_put(other);
++ goto restart;
++ }
++
++ /* Latch our state.
++
++ It is tricky place. We need to grab our state lock and cannot
++ drop lock on peer. It is dangerous because deadlock is
++ possible. Connect to self case and simultaneous
++ attempt to connect are eliminated by checking socket
++ state. other is BUS_LISTEN, if sk is BUS_LISTEN we
++ check this before attempt to grab lock.
++
++ Well, and we have to recheck the state after socket locked.
++ */
++ st = sk->sk_state;
++
++ switch (st) {
++ case BUS_CLOSE:
++ /* This is ok... continue with connect */
++ break;
++ case BUS_ESTABLISHED:
++ /* Socket is already connected */
++ err = -EISCONN;
++ goto out_unlock;
++ default:
++ err = -EINVAL;
++ goto out_unlock;
++ }
++
++ bus_state_lock_nested(sk);
++
++ if (sk->sk_state != st) {
++ bus_state_unlock(sk);
++ bus_state_unlock(other);
++ sock_put(other);
++ goto restart;
++ }
++
++ err = security_bus_connect(sk, other, newsk);
++ if (err) {
++ bus_state_unlock(sk);
++ goto out_unlock;
++ }
++
++ /* The way is open! Fastly set all the necessary fields... */
++
++ sock_hold(sk);
++ bus_peer(newsk) = sk;
++ newsk->sk_state = BUS_ESTABLISHED;
++ newsk->sk_type = sk->sk_type;
++ newsk->sk_protocol = sk->sk_protocol;
++ init_peercred(newsk);
++ newu = bus_sk(newsk);
++ RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
++ otheru = bus_sk(other);
++
++ /* copy address information from listening to new sock*/
++ if (otheru->addr && otheru->bus_master) {
++ atomic_inc(&otheru->addr->refcnt);
++ newu->addr = otheru->addr;
++ memcpy(addr->name, otheru->addr->name,
++ sizeof(struct sockaddr_bus));
++ addr->len = otheru->addr->len;
++ addr->name->sbus_addr.s_addr =
++ (atomic64_inc_return(&otheru->bus->addr_cnt) &
++ BUS_CLIENT_MASK);
++ addr->hash = bus_compute_hash(addr->name->sbus_addr);
++ addr->sock = sk;
++ u->addr = addr;
++ kref_get(&otheru->bus->kref);
++ u->bus = otheru->bus;
++ u->bus_master_side = false;
++ kref_get(&otheru->bus->kref);
++ newu->bus = otheru->bus;
++ newu->bus_master_side = true;
++ hlist_add_head(&addr->addr_node, &u->addr_list);
++
++ bus_insert_address(&bus_address_table[addr->hash], addr);
++ }
++ if (otheru->path.dentry) {
++ path_get(&otheru->path);
++ newu->path = otheru->path;
++ }
++
++ /* Set credentials */
++ copy_peercred(sk, other);
++ sk->sk_sndbuf = other->sk_sndbuf;
++ sk->sk_max_ack_backlog = other->sk_max_ack_backlog;
++ newsk->sk_sndbuf = other->sk_sndbuf;
++
++ sock->state = SS_CONNECTED;
++ sk->sk_state = BUS_ESTABLISHED;
++ sock_hold(newsk);
++
++ smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
++ bus_peer(sk) = newsk;
++
++ bus_state_unlock(sk);
++
++ /* take ten and and send info to listening sock */
++ spin_lock(&other->sk_receive_queue.lock);
++ __skb_queue_tail(&other->sk_receive_queue, skb);
++ spin_unlock(&other->sk_receive_queue.lock);
++ bus_state_unlock(other);
++ other->sk_data_ready(other, 0);
++ sock_put(other);
++ return 0;
++
++out_unlock:
++ if (other)
++ bus_state_unlock(other);
++
++out:
++ kfree_skb(skb);
++ if (addr)
++ bus_release_addr(addr);
++ if (newsk)
++ bus_release_sock(newsk, 0);
++ if (other)
++ sock_put(other);
++ return err;
++}
++
++static int bus_accept(struct socket *sock, struct socket *newsock, int flags)
++{
++ struct sock *sk = sock->sk;
++ struct sock *tsk;
++ struct sk_buff *skb;
++ int err;
++
++ err = -EINVAL;
++ if (sk->sk_state != BUS_LISTEN)
++ goto out;
++
++ /* If socket state is BUS_LISTEN it cannot change (for now...),
++ * so that no locks are necessary.
++ */
++
++ skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
++ if (!skb) {
++ /* This means receive shutdown. */
++ if (err == 0)
++ err = -EINVAL;
++ goto out;
++ }
++
++ tsk = skb->sk;
++ skb_free_datagram(sk, skb);
++ wake_up_interruptible(&bus_sk(sk)->peer_wait);
++
++ /* attach accepted sock to socket */
++ bus_state_lock(tsk);
++ newsock->state = SS_CONNECTED;
++ sock_graft(tsk, newsock);
++ bus_state_unlock(tsk);
++ return 0;
++
++out:
++ return err;
++}
++
++
++static int bus_getname(struct socket *sock, struct sockaddr *uaddr,
++ int *uaddr_len, int peer)
++{
++ struct sock *sk = sock->sk;
++ struct bus_sock *u;
++ DECLARE_SOCKADDR(struct sockaddr_bus *, sbusaddr, uaddr);
++ int err = 0;
++
++ if (peer) {
++ sk = bus_peer_get(sk);
++
++ err = -ENOTCONN;
++ if (!sk)
++ goto out;
++ err = 0;
++ } else {
++ sock_hold(sk);
++ }
++
++ u = bus_sk(sk);
++
++ bus_state_lock(sk);
++ if (!u->addr) {
++ sbusaddr->sbus_family = AF_BUS;
++ sbusaddr->sbus_path[0] = 0;
++ *uaddr_len = sizeof(short);
++ } else {
++ struct bus_address *addr = u->addr;
++
++ *uaddr_len = sizeof(struct sockaddr_bus);
++ memcpy(sbusaddr, addr->name, *uaddr_len);
++ }
++ bus_state_unlock(sk);
++ sock_put(sk);
++out:
++ return err;
++}
++
++static void bus_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
++{
++ int i;
++
++ scm->fp = BUSCB(skb).fp;
++ BUSCB(skb).fp = NULL;
++
++ for (i = scm->fp->count-1; i >= 0; i--)
++ bus_notinflight(scm->fp->fp[i]);
++}
++
++static void bus_destruct_scm(struct sk_buff *skb)
++{
++ struct scm_cookie scm;
++ memset(&scm, 0, sizeof(scm));
++ scm.pid = BUSCB(skb).pid;
++ scm.cred = BUSCB(skb).cred;
++ if (BUSCB(skb).fp)
++ bus_detach_fds(&scm, skb);
++
++ scm_destroy(&scm);
++ if (skb->sk)
++ sock_wfree(skb);
++}
++
++#define MAX_RECURSION_LEVEL 4
++
++static int bus_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
++{
++ int i;
++ unsigned char max_level = 0;
++ int bus_sock_count = 0;
++
++ for (i = scm->fp->count - 1; i >= 0; i--) {
++ struct sock *sk = bus_get_socket(scm->fp->fp[i]);
++
++ if (sk) {
++ bus_sock_count++;
++ max_level = max(max_level,
++ bus_sk(sk)->recursion_level);
++ }
++ }
++ if (unlikely(max_level > MAX_RECURSION_LEVEL))
++ return -ETOOMANYREFS;
++
++ /*
++ * Need to duplicate file references for the sake of garbage
++ * collection. Otherwise a socket in the fps might become a
++ * candidate for GC while the skb is not yet queued.
++ */
++ BUSCB(skb).fp = scm_fp_dup(scm->fp);
++ if (!BUSCB(skb).fp)
++ return -ENOMEM;
++
++ if (bus_sock_count) {
++ for (i = scm->fp->count - 1; i >= 0; i--)
++ bus_inflight(scm->fp->fp[i]);
++ }
++ return max_level;
++}
++
++static int bus_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb,
++ bool send_fds)
++{
++ int err = 0;
++
++ BUSCB(skb).pid = get_pid(scm->pid);
++ if (scm->cred)
++ BUSCB(skb).cred = get_cred(scm->cred);
++ BUSCB(skb).fp = NULL;
++ if (scm->fp && send_fds)
++ err = bus_attach_fds(scm, skb);
++
++ skb->destructor = bus_destruct_scm;
++ return err;
++}
++
++/*
++ * Some apps rely on write() giving SCM_CREDENTIALS
++ * We include credentials if source or destination socket
++ * asserted SOCK_PASSCRED.
++ */
++static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
++ const struct sock *other)
++{
++ if (BUSCB(skb).cred)
++ return;
++ if (test_bit(SOCK_PASSCRED, &sock->flags) ||
++ !other->sk_socket ||
++ test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
++ BUSCB(skb).pid = get_pid(task_tgid(current));
++ BUSCB(skb).cred = get_current_cred();
++ }
++}
++
++/*
++ * Send AF_BUS data.
++ */
++
++static void bus_deliver_skb(struct sk_buff *skb)
++{
++ struct bus_send_context *sendctx = BUSCB(skb).sendctx;
++ struct socket *sock = sendctx->sender_socket;
++
++ if (sock_flag(sendctx->other, SOCK_RCVTSTAMP))
++ __net_timestamp(skb);
++ maybe_add_creds(skb, sock, sendctx->other);
++ skb_queue_tail(&sendctx->other->sk_receive_queue, skb);
++ if (sendctx->max_level > bus_sk(sendctx->other)->recursion_level)
++ bus_sk(sendctx->other)->recursion_level = sendctx->max_level;
++}
++
++/**
++ * bus_sendmsg_finish - delivery an skb to a destination
++ * @skb: sk_buff to deliver
++ *
++ * Delivers a packet to a destination. The skb control buffer has
++ * all the information about the destination contained on sending
++ * context. If the sending is unicast, then the skb is delivered
++ * and the receiver notified but if the sending is multicast, the
++ * skb is just marked as delivered and the actual delivery is made
++ * outside the function with the bus->send_lock held to ensure that
++ * the multicast sending is atomic.
++ */
++static int bus_sendmsg_finish(struct sk_buff *skb)
++{
++ int err;
++ struct bus_send_context *sendctx;
++ struct socket *sock;
++ struct sock *sk;
++ struct net *net;
++ size_t len = skb->len;
++
++ sendctx = BUSCB(skb).sendctx;
++ sock = sendctx->sender_socket;
++ sk = sock->sk;
++ net = sock_net(sk);
++
++restart:
++ if (!sendctx->other) {
++ err = -ECONNRESET;
++ if (sendctx->recipient == NULL)
++ goto out_free;
++
++ sendctx->other = bus_find_other(net, sendctx->recipient,
++ sendctx->namelen,
++ sk->sk_protocol,
++ sendctx->hash, &err);
++
++ if (sendctx->other == NULL ||
++ !bus_sk(sendctx->other)->authenticated) {
++
++ if (sendctx->other)
++ sock_put(sendctx->other);
++
++ if (!bus_sk(sk)->bus_master_side) {
++ err = -ENOTCONN;
++ sendctx->other = bus_peer_get(sk);
++ if (!sendctx->other)
++ goto out_free;
++ } else {
++ sendctx->other = sk;
++ sock_hold(sendctx->other);
++ }
++ }
++ }
++
++ if (sk_filter(sendctx->other, skb) < 0) {
++ /* Toss the packet but do not return any error to the sender */
++ err = len;
++ goto out_free;
++ }
++
++ bus_state_lock(sendctx->other);
++
++ if (sock_flag(sendctx->other, SOCK_DEAD)) {
++ /*
++ * Check with 1003.1g - what should
++ * datagram error
++ */
++ bus_state_unlock(sendctx->other);
++ sock_put(sendctx->other);
++
++ err = 0;
++ bus_state_lock(sk);
++ if (bus_peer(sk) == sendctx->other) {
++ bus_peer(sk) = NULL;
++ bus_state_unlock(sk);
++ sock_put(sendctx->other);
++ err = -ECONNREFUSED;
++ } else {
++ bus_state_unlock(sk);
++ }
++
++ sendctx->other = NULL;
++ if (err)
++ goto out_free;
++ goto restart;
++ }
++
++ err = -EPIPE;
++ if (sendctx->other->sk_shutdown & RCV_SHUTDOWN)
++ goto out_unlock;
++
++ if (bus_recvq_full(sendctx->other)) {
++ if (!sendctx->timeo) {
++ err = -EAGAIN;
++ goto out_unlock;
++ }
++
++ sendctx->timeo = bus_wait_for_peer(sendctx->other,
++ sendctx->timeo);
++
++ err = sock_intr_errno(sendctx->timeo);
++ if (signal_pending(current))
++ goto out_free;
++
++ goto restart;
++ }
++
++ if (!sendctx->multicast && !sendctx->eavesdropper) {
++ bus_deliver_skb(skb);
++ bus_state_unlock(sendctx->other);
++ sendctx->other->sk_data_ready(sendctx->other, 0);
++ sock_put(sendctx->other);
++ } else {
++ sendctx->deliver = 1;
++ bus_state_unlock(sendctx->other);
++ }
++
++ return len;
++
++out_unlock:
++ bus_state_unlock(sendctx->other);
++out_free:
++ kfree_skb(skb);
++ if (sendctx->other)
++ sock_put(sendctx->other);
++
++ return err;
++}
++
++/**
++ * bus_sendmsg_mcast - do a multicast sending
++ * @skb: sk_buff to deliver
++ *
++ * Send a packet to a multicast destination.
++ * The function is also called for unicast sending when eavesdropping
++ * is enabled. Since the unicast destination and the eavesdroppers
++ * have to receive the packet atomically.
++ */
++static int bus_sendmsg_mcast(struct sk_buff *skb)
++{
++ struct bus_send_context *sendctx;
++ struct bus_send_context *tmpctx;
++ struct socket *sock;
++ struct sock *sk;
++ struct net *net;
++ struct bus_sock *u, *s;
++ struct hlist_node *node;
++ u16 prefix = 0;
++ struct sk_buff **skb_set = NULL;
++ struct bus_send_context **sendctx_set = NULL;
++ int rcp_cnt, send_cnt;
++ int i;
++ int err;
++ int len = skb->len;
++ bool (*is_receiver) (struct sock *, u16);
++ bool main_rcp_found = false;
++
++ sendctx = BUSCB(skb).sendctx;
++ sendctx->deliver = 0;
++ sock = sendctx->sender_socket;
++ sk = sock->sk;
++ u = bus_sk(sk);
++ net = sock_net(sk);
++
++ if (sendctx->multicast) {
++ prefix = bus_addr_prefix(sendctx->recipient);
++ if (sendctx->eavesdropper)
++ is_receiver = &bus_has_prefix_eavesdropper;
++ else
++ is_receiver = &bus_has_prefix;
++ } else {
++ is_receiver = &bus_eavesdropper;
++
++ /*
++ * If the destination is not the peer accepted socket
++ * we have to get the correct destination.
++ */
++ if (!sendctx->to_master && sendctx->recipient) {
++ sendctx->other = bus_find_other(net, sendctx->recipient,
++ sendctx->namelen,
++ sk->sk_protocol,
++ sendctx->hash, &err);
++
++
++ if (sendctx->other == NULL ||
++ !bus_sk(sendctx->other)->authenticated) {
++
++ if (sendctx->other)
++ sock_put(sendctx->other);
++
++ if (sendctx->other == NULL) {
++ if (!bus_sk(sk)->bus_master_side) {
++ err = -ENOTCONN;
++ sendctx->other = bus_peer_get(sk);
++ if (!sendctx->other)
++ goto out;
++ } else {
++ sendctx->other = sk;
++ sock_hold(sendctx->other);
++ }
++ }
++ sendctx->to_master = 1;
++ }
++ }
++ }
++
++
++try_again:
++ rcp_cnt = 0;
++ main_rcp_found = false;
++
++ spin_lock(&u->bus->lock);
++
++ hlist_for_each_entry(s, node, &u->bus->peers, bus_node) {
++
++ if (!net_eq(sock_net(&s->sk), net))
++ continue;
++
++ if (is_receiver(&s->sk, prefix) ||
++ (!sendctx->multicast &&
++ !sendctx->to_master &&
++ &s->sk == sendctx->other))
++ rcp_cnt++;
++ }
++
++ spin_unlock(&u->bus->lock);
++
++ /*
++ * Memory can't be allocated while holding a spinlock so
++ * we have to release the lock, do the allocation for the
++ * array to store each destination peer sk_buff and grab
++ * the bus peer lock again. Peers could have joined the
++ * bus while we relesed the lock so we allocate 5 more
++ * recipients hoping that this will be enough to not having
++ * to try again in case only a few peers joined the bus.
++ */
++ rcp_cnt += 5;
++ skb_set = kzalloc(sizeof(struct sk_buff *) * rcp_cnt, GFP_KERNEL);
++
++ if (!skb_set) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ sendctx_set = kzalloc(sizeof(struct bus_send_context *) * rcp_cnt,
++ GFP_KERNEL);
++ if (!sendctx_set) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ for (i = 0; i < rcp_cnt; i++) {
++ skb_set[i] = skb_clone(skb, GFP_KERNEL);
++ if (!skb_set[i]) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ sendctx_set[i] = BUSCB(skb_set[i]).sendctx
++ = kmalloc(sizeof(*sendctx) * rcp_cnt, GFP_KERNEL);
++ if (!sendctx_set[i]) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ memcpy(sendctx_set[i], sendctx, sizeof(*sendctx));
++ err = bus_scm_to_skb(sendctx_set[i]->siocb->scm,
++ skb_set[i], true);
++ if (err < 0)
++ goto out_free;
++ bus_get_secdata(sendctx_set[i]->siocb->scm,
++ skb_set[i]);
++
++ sendctx_set[i]->other = NULL;
++ }
++
++ send_cnt = 0;
++
++ spin_lock(&u->bus->lock);
++
++ hlist_for_each_entry(s, node, &u->bus->peers, bus_node) {
++
++ if (!net_eq(sock_net(&s->sk), net))
++ continue;
++
++ if (send_cnt >= rcp_cnt) {
++ spin_unlock(&u->bus->lock);
++
++ for (i = 0; i < rcp_cnt; i++) {
++ sock_put(sendctx_set[i]->other);
++ kfree_skb(skb_set[i]);
++ kfree(sendctx_set[i]);
++ }
++ kfree(skb_set);
++ kfree(sendctx_set);
++ sendctx_set = NULL;
++ skb_set = NULL;
++ goto try_again;
++ }
++
++ if (is_receiver(&s->sk, prefix) ||
++ (!sendctx->multicast &&
++ !sendctx->to_master &&
++ &s->sk == sendctx->other)) {
++ skb_set_owner_w(skb_set[send_cnt], &s->sk);
++ tmpctx = BUSCB(skb_set[send_cnt]).sendctx;
++ sock_hold(&s->sk);
++ if (&s->sk == sendctx->other) {
++ tmpctx->main_recipient = 1;
++ main_rcp_found = true;
++ }
++ tmpctx->other = &s->sk;
++ tmpctx->recipient = s->addr->name;
++ tmpctx->eavesdropper = bus_eavesdropper(&s->sk, 0);
++
++ send_cnt++;
++ }
++ }
++
++ spin_unlock(&u->bus->lock);
++
++ /*
++ * Peers have left the bus so we have to free
++ * their pre-allocated bus_send_context and
++ * socket buffers.
++ */
++ if (send_cnt < rcp_cnt) {
++ for (i = send_cnt; i < rcp_cnt; i++) {
++ kfree_skb(skb_set[i]);
++ kfree(sendctx_set[i]);
++ }
++ rcp_cnt = send_cnt;
++ }
++
++ for (i = 0; i < send_cnt; i++) {
++ tmpctx = BUSCB(skb_set[i]).sendctx;
++ tmpctx->deliver = 0;
++ err = NF_HOOK(NFPROTO_BUS, NF_BUS_SENDING, skb_set[i],
++ NULL, NULL, bus_sendmsg_finish);
++ if (err == -EPERM)
++ sock_put(tmpctx->other);
++ }
++
++ /*
++ * If the send context is not multicast, the destination
++ * coud be either the peer accepted socket descriptor or
++ * a peer that is not an eavesdropper. If the peer is not
++ * the accepted socket descriptor and has been authenticated,
++ * it is a member of the bus peer list so it has already been
++ * marked for delivery.
++ * But if the destination is the accepted socket descriptor
++ * or is a non-authenticated peer it is not a member of the
++ * bus peer list so the packet has to be explicitly deliver
++ * to it.
++ */
++
++ if (!sendctx->multicast &&
++ (sendctx->to_master ||
++ (sendctx->bus_master_side && !main_rcp_found))) {
++ sendctx->main_recipient = 1;
++ err = NF_HOOK(NFPROTO_BUS, NF_BUS_SENDING, skb, NULL, NULL,
++ bus_sendmsg_finish);
++ if (err == -EPERM)
++ sock_put(sendctx->other);
++ }
++
++ spin_lock(&u->bus->send_lock);
++
++ for (i = 0; i < send_cnt; i++) {
++ tmpctx = sendctx_set[i];
++ if (tmpctx->deliver != 1)
++ continue;
++
++ bus_state_lock(tmpctx->other);
++ bus_deliver_skb(skb_set[i]);
++ bus_state_unlock(tmpctx->other);
++ }
++
++ if (!sendctx->multicast &&
++ sendctx->deliver == 1 &&
++ !bus_sk(sendctx->other)->eavesdropper) {
++ bus_state_lock(sendctx->other);
++ bus_deliver_skb(skb);
++ bus_state_unlock(sendctx->other);
++ }
++
++ spin_unlock(&u->bus->send_lock);
++
++ for (i = 0; i < send_cnt; i++) {
++ tmpctx = sendctx_set[i];
++ if (tmpctx->deliver != 1)
++ continue;
++
++ tmpctx->other->sk_data_ready(tmpctx->other, 0);
++ sock_put(tmpctx->other);
++ }
++
++ if (!sendctx->multicast &&
++ sendctx->deliver == 1 &&
++ !bus_sk(sendctx->other)->eavesdropper) {
++ sendctx->other->sk_data_ready(sendctx->other, 0);
++ sock_put(sendctx->other);
++ }
++
++ err = len;
++ goto out;
++
++out_free:
++ for (i = 0; i < rcp_cnt; i++) {
++ if (skb_set[i])
++ kfree_skb(skb_set[i]);
++ }
++
++out:
++ kfree(skb_set);
++ if (sendctx_set) {
++ for (i = 0; i < rcp_cnt; i++)
++ kfree(sendctx_set[i]);
++ kfree(sendctx_set);
++ }
++
++ if (sendctx->deliver == 0) {
++ if (!sendctx->to_master &&
++ !(sendctx->bus_master_side && !main_rcp_found))
++ kfree_skb(skb);
++ if (!sendctx->to_master &&
++ !(sendctx->bus_master_side && !main_rcp_found))
++ if (sendctx->other)
++ sock_put(sendctx->other);
++ }
++ scm_destroy(sendctx->siocb->scm);
++
++ return err;
++}
++
++static inline void bus_copy_path(struct sockaddr_bus *dest,
++ struct sockaddr_bus *src)
++{
++ int offset;
++
++ /*
++ * abstract path names start with a null byte character,
++ * so they have to be compared starting at the second char.
++ */
++ offset = (src->sbus_path[0] == '\0');
++
++ strncpy(dest->sbus_path + offset,
++ src->sbus_path + offset,
++ BUS_PATH_MAX);
++}
++
++/**
++ * bus_sendmsg - send an skb to a destination
++ * @kiocb: I/O control block info
++ * @sock: sender socket
++ * @msg: message header
++ * @len: message length
++ *
++ * Send an socket buffer to a destination. The destination could be
++ * either an unicast or a multicast address. In any case, a copy of
++ * the packet has to be send to all the sockets that are allowed to
++ * eavesdrop the communication bus.
++ *
++ * If the destination address is not associated with any socket, the
++ * packet is default routed to the bus master (the sender accepted
++ * socket).
++ *
++ * The af_bus sending path is hooked to the netfilter subsystem so
++ * netfilter hooks can filter or modify the packet before delivery.
++ */
++static int bus_sendmsg(struct kiocb *kiocb, struct socket *sock,
++ struct msghdr *msg, size_t len)
++{
++ struct sock *sk = sock->sk;
++ struct bus_sock *u = bus_sk(sk);
++ struct sockaddr_bus *sbusaddr = msg->msg_name;
++ int err;
++ struct sk_buff *skb;
++ struct scm_cookie tmp_scm;
++ bool to_master = false;
++ bool multicast = false;
++ struct bus_send_context sendctx;
++
++ err = sock_error(sk);
++ if (err)
++ return err;
++
++ if (sk->sk_state != BUS_ESTABLISHED)
++ return -ENOTCONN;
++
++ if (!msg->msg_namelen)
++ sbusaddr = NULL;
++
++ if (sbusaddr)
++ bus_copy_path(sbusaddr, u->addr->name);
++
++ if ((!sbusaddr && !u->bus_master_side) ||
++ (sbusaddr && sbusaddr->sbus_addr.s_addr == BUS_MASTER_ADDR))
++ to_master = true;
++ else if (sbusaddr && !u->bus_master_side && !u->authenticated)
++ return -EHOSTUNREACH;
++
++ sendctx.namelen = 0; /* fake GCC */
++ sendctx.siocb = kiocb_to_siocb(kiocb);
++ sendctx.other = NULL;
++
++ if (NULL == sendctx.siocb->scm)
++ sendctx.siocb->scm = &tmp_scm;
++ wait_for_bus_gc();
++ err = scm_send(sock, msg, sendctx.siocb->scm);
++ if (err < 0)
++ return err;
++
++ err = -EOPNOTSUPP;
++ if (msg->msg_flags&MSG_OOB)
++ goto out;
++
++ if (sbusaddr && !to_master) {
++ err = bus_mkname(sbusaddr, msg->msg_namelen, &sendctx.hash);
++ if (err < 0)
++ goto out;
++ sendctx.namelen = err;
++ multicast = bus_mc_addr(sbusaddr);
++ } else {
++ err = -ENOTCONN;
++ sendctx.other = bus_peer_get(sk);
++ if (!sendctx.other)
++ goto out;
++ }
++
++ err = -EMSGSIZE;
++ if (len > sk->sk_sndbuf - 32)
++ goto out;
++
++ sendctx.timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
++
++restart:
++ bus_state_lock(sk);
++ if (bus_recvq_full(sk)) {
++ err = -EAGAIN;
++ if (!sendctx.timeo) {
++ bus_state_unlock(sk);
++ goto out;
++ }
++
++ sendctx.timeo = bus_wait_for_peer(sk, sendctx.timeo);
++
++ err = sock_intr_errno(sendctx.timeo);
++ if (signal_pending(current))
++ goto out;
++
++ goto restart;
++ } else {
++ bus_state_unlock(sk);
++ }
++
++ skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err);
++ if (skb == NULL)
++ goto out;
++
++ err = bus_scm_to_skb(sendctx.siocb->scm, skb, true);
++ if (err < 0)
++ goto out_free;
++ sendctx.max_level = err + 1;
++ bus_get_secdata(sendctx.siocb->scm, skb);
++
++ skb_reset_transport_header(skb);
++ err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
++ if (err)
++ goto out_free;
++
++ sendctx.sender_socket = sock;
++ if (u->bus_master_side && sendctx.other) {
++ /* if the bus master sent an unicast message to a peer, we
++ * need the address of that peer
++ */
++ sendctx.sender = bus_sk(sendctx.other)->addr->name;
++ } else {
++ sendctx.sender = u->addr->name;
++ }
++ sendctx.recipient = sbusaddr;
++ sendctx.authenticated = u->authenticated;
++ sendctx.bus_master_side = u->bus_master_side;
++ sendctx.to_master = to_master;
++ sendctx.multicast = multicast;
++ sendctx.eavesdropper = atomic64_read(&u->bus->eavesdropper_cnt) ? 1 : 0;
++ BUSCB(skb).sendctx = &sendctx;
++
++ if (sendctx.multicast || sendctx.eavesdropper) {
++ sendctx.main_recipient = 0;
++ err = bus_sendmsg_mcast(skb);
++ return sendctx.multicast ? len : err;
++ } else {
++ sendctx.main_recipient = 1;
++ len = NF_HOOK(NFPROTO_BUS, NF_BUS_SENDING, skb, NULL, NULL,
++ bus_sendmsg_finish);
++
++ if (len == -EPERM) {
++ err = len;
++ goto out;
++ } else {
++ scm_destroy(sendctx.siocb->scm);
++ return len;
++ }
++ }
++
++out_free:
++ kfree_skb(skb);
++out:
++ if (sendctx.other)
++ sock_put(sendctx.other);
++ scm_destroy(sendctx.siocb->scm);
++ return err;
++}
++
++static void bus_copy_addr(struct msghdr *msg, struct sock *sk)
++{
++ struct bus_sock *u = bus_sk(sk);
++
++ msg->msg_namelen = 0;
++ if (u->addr) {
++ msg->msg_namelen = u->addr->len;
++ memcpy(msg->msg_name, u->addr->name,
++ sizeof(struct sockaddr_bus));
++ }
++}
++
++static int bus_recvmsg(struct kiocb *iocb, struct socket *sock,
++ struct msghdr *msg, size_t size, int flags)
++{
++ struct sock_iocb *siocb = kiocb_to_siocb(iocb);
++ struct scm_cookie tmp_scm;
++ struct sock *sk = sock->sk;
++ struct bus_sock *u = bus_sk(sk);
++ int noblock = flags & MSG_DONTWAIT;
++ struct sk_buff *skb;
++ int err;
++ int peeked, skip;
++
++ if (sk->sk_state != BUS_ESTABLISHED)
++ return -ENOTCONN;
++
++ err = -EOPNOTSUPP;
++ if (flags&MSG_OOB)
++ goto out;
++
++ msg->msg_namelen = 0;
++
++ err = mutex_lock_interruptible(&u->readlock);
++ if (err) {
++ err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
++ goto out;
++ }
++
++ skip = sk_peek_offset(sk, flags);
++
++ skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
++ if (!skb) {
++ bus_state_lock(sk);
++ /* Signal EOF on disconnected non-blocking SEQPACKET socket. */
++ if (err == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN))
++ err = 0;
++ bus_state_unlock(sk);
++ goto out_unlock;
++ }
++
++ wake_up_interruptible_sync_poll(&u->peer_wait,
++ POLLOUT | POLLWRNORM | POLLWRBAND);
++
++ if (msg->msg_name)
++ bus_copy_addr(msg, skb->sk);
++
++ if (size > skb->len - skip)
++ size = skb->len - skip;
++ else if (size < skb->len - skip)
++ msg->msg_flags |= MSG_TRUNC;
++
++ err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
++ if (err)
++ goto out_free;
++
++ if (sock_flag(sk, SOCK_RCVTSTAMP))
++ __sock_recv_timestamp(msg, sk, skb);
++
++ if (!siocb->scm) {
++ siocb->scm = &tmp_scm;
++ memset(&tmp_scm, 0, sizeof(tmp_scm));
++ }
++ scm_set_cred(siocb->scm, BUSCB(skb).pid, BUSCB(skb).cred);
++ bus_set_secdata(siocb->scm, skb);
++
++ if (!(flags & MSG_PEEK)) {
++ if (BUSCB(skb).fp)
++ bus_detach_fds(siocb->scm, skb);
++
++ sk_peek_offset_bwd(sk, skb->len);
++ } else {
++ /* It is questionable: on PEEK we could:
++ - do not return fds - good, but too simple 8)
++ - return fds, and do not return them on read (old strategy,
++ apparently wrong)
++ - clone fds (I chose it for now, it is the most universal
++ solution)
++
++ POSIX 1003.1g does not actually define this clearly
++ at all. POSIX 1003.1g doesn't define a lot of things
++ clearly however!
++
++ */
++
++ sk_peek_offset_fwd(sk, size);
++
++ if (BUSCB(skb).fp)
++ siocb->scm->fp = scm_fp_dup(BUSCB(skb).fp);
++ }
++ err = (flags & MSG_TRUNC) ? skb->len - skip : size;
++
++ scm_recv(sock, msg, siocb->scm, flags);
++
++out_free:
++ skb_free_datagram(sk, skb);
++out_unlock:
++ mutex_unlock(&u->readlock);
++out:
++ return err;
++}
++
++static int bus_shutdown(struct socket *sock, int mode)
++{
++ struct sock *sk = sock->sk;
++ struct sock *other;
++
++ mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
++
++ if (!mode)
++ return 0;
++
++ bus_state_lock(sk);
++ sk->sk_shutdown |= mode;
++ other = bus_peer(sk);
++ if (other)
++ sock_hold(other);
++ bus_state_unlock(sk);
++ sk->sk_state_change(sk);
++
++ if (other) {
++
++ int peer_mode = 0;
++
++ if (mode&RCV_SHUTDOWN)
++ peer_mode |= SEND_SHUTDOWN;
++ if (mode&SEND_SHUTDOWN)
++ peer_mode |= RCV_SHUTDOWN;
++ bus_state_lock(other);
++ other->sk_shutdown |= peer_mode;
++ bus_state_unlock(other);
++ other->sk_state_change(other);
++ if (peer_mode == SHUTDOWN_MASK)
++ sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
++ else if (peer_mode & RCV_SHUTDOWN)
++ sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
++ sock_put(other);
++ }
++
++ return 0;
++}
++
++static int bus_add_addr(struct sock *sk, struct bus_addr *sbus_addr)
++{
++ struct bus_address *addr;
++ struct sock *other;
++ struct bus_sock *u = bus_sk(sk);
++ struct net *net = sock_net(sk);
++ int ret = 0;
++
++ addr = kzalloc(sizeof(*addr) + sizeof(struct sockaddr_bus), GFP_KERNEL);
++ if (!addr) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ memcpy(addr->name, u->addr->name, sizeof(struct sockaddr_bus));
++ addr->len = u->addr->len;
++
++ addr->name->sbus_addr.s_addr = sbus_addr->s_addr;
++ addr->hash = bus_compute_hash(addr->name->sbus_addr);
++ other = bus_find_socket_byaddress(net, addr->name, addr->len,
++ sk->sk_protocol, addr->hash);
++
++ if (other) {
++ sock_put(other);
++ kfree(addr);
++ ret = -EADDRINUSE;
++ goto out;
++ }
++
++ atomic_set(&addr->refcnt, 1);
++ INIT_HLIST_NODE(&addr->addr_node);
++ INIT_HLIST_NODE(&addr->table_node);
++
++ addr->sock = sk;
++
++ hlist_add_head(&addr->addr_node, &u->addr_list);
++ bus_insert_address(&bus_address_table[addr->hash], addr);
++
++out:
++ sock_put(sk);
++
++ return ret;
++}
++
++static int bus_del_addr(struct sock *sk, struct bus_addr *sbus_addr)
++{
++ struct bus_address *addr;
++ int ret = 0;
++
++ bus_state_lock(sk);
++ addr = __bus_get_address(sk, sbus_addr);
++ if (!addr) {
++ ret = -EINVAL;
++ bus_state_unlock(sk);
++ goto out;
++ }
++ hlist_del(&addr->addr_node);
++ bus_state_unlock(sk);
++
++ bus_remove_address(addr);
++ bus_release_addr(addr);
++out:
++ sock_put(sk);
++
++ return ret;
++}
++
++static int bus_join_bus(struct sock *sk)
++{
++ struct sock *peer;
++ struct bus_sock *u = bus_sk(sk), *peeru;
++ int err = 0;
++
++ peer = bus_peer_get(sk);
++ if (!peer)
++ return -ENOTCONN;
++ peeru = bus_sk(peer);
++
++ if (!u->bus_master_side || peeru->authenticated) {
++ err = -EINVAL;
++ goto sock_put_out;
++ }
++
++ if (sk->sk_state != BUS_ESTABLISHED) {
++ err = -ENOTCONN;
++ goto sock_put_out;
++ }
++
++ if (peer->sk_shutdown != 0) {
++ err = -ENOTCONN;
++ goto sock_put_out;
++ }
++
++ bus_state_lock(peer);
++ peeru->authenticated = true;
++ bus_state_unlock(peer);
++
++ spin_lock(&u->bus->lock);
++ hlist_add_head(&peeru->bus_node, &u->bus->peers);
++ spin_unlock(&u->bus->lock);
++
++sock_put_out:
++ sock_put(peer);
++ return err;
++}
++
++static int __bus_set_eavesdrop(struct sock *sk, bool eavesdrop)
++{
++ struct sock *peer = bus_peer_get(sk);
++ struct bus_sock *u = bus_sk(sk), *peeru;
++ int err = 0;
++
++ if (!peer)
++ return -ENOTCONN;
++
++ if (sk->sk_state != BUS_ESTABLISHED) {
++ err = -ENOTCONN;
++ goto sock_put_out;
++ }
++
++ peeru = bus_sk(peer);
++
++ if (!u->bus_master_side || !peeru->authenticated) {
++ err = -EINVAL;
++ goto sock_put_out;
++ }
++
++ if (peer->sk_shutdown != 0) {
++ err = -ENOTCONN;
++ goto sock_put_out;
++ }
++
++ bus_state_lock(peeru);
++ if (peeru->eavesdropper != eavesdrop) {
++ peeru->eavesdropper = eavesdrop;
++ if (eavesdrop)
++ atomic64_inc(&u->bus->eavesdropper_cnt);
++ else
++ atomic64_dec(&u->bus->eavesdropper_cnt);
++ }
++ bus_state_unlock(peeru);
++
++sock_put_out:
++ sock_put(peer);
++ return err;
++}
++
++static int bus_set_eavesdrop(struct sock *sk)
++{
++ return __bus_set_eavesdrop(sk, true);
++}
++
++static int bus_unset_eavesdrop(struct sock *sk)
++{
++ return __bus_set_eavesdrop(sk, false);
++}
++
++static inline void sk_sendbuf_set(struct sock *sk, int sndbuf)
++{
++ bus_state_lock(sk);
++ sk->sk_sndbuf = sndbuf;
++ bus_state_unlock(sk);
++}
++
++static inline void sk_maxqlen_set(struct sock *sk, int qlen)
++{
++ bus_state_lock(sk);
++ sk->sk_max_ack_backlog = qlen;
++ bus_state_unlock(sk);
++}
++
++static int bus_get_qlenfull(struct sock *sk)
++{
++ struct sock *peer;
++ struct bus_sock *u = bus_sk(sk), *peeru;
++ int ret = 0;
++
++ peer = bus_peer_get(sk);
++ if (!peer)
++ return -ENOTCONN;
++
++ peeru = bus_sk(peer);
++
++ if (!u->bus_master_side || peeru->authenticated) {
++ ret = -EINVAL;
++ goto sock_put_out;
++ }
++
++ if (sk->sk_state != BUS_ESTABLISHED) {
++ ret = -ENOTCONN;
++ goto sock_put_out;
++ }
++
++ if (peer->sk_shutdown != 0) {
++ ret = -ENOTCONN;
++ goto sock_put_out;
++ }
++
++ ret = bus_recvq_full(peer);
++
++sock_put_out:
++ sock_put(peer);
++ return ret;
++}
++
++static int bus_setsockopt(struct socket *sock, int level, int optname,
++ char __user *optval, unsigned int optlen)
++{
++ struct bus_addr addr;
++ int res;
++ int val;
++
++ if (level != SOL_BUS)
++ return -ENOPROTOOPT;
++
++ switch (optname) {
++ case BUS_ADD_ADDR:
++ case BUS_DEL_ADDR:
++ if (optlen < sizeof(struct bus_addr))
++ return -EINVAL;
++
++ if (!bus_sk(sock->sk)->bus_master_side)
++ return -EINVAL;
++
++ if (copy_from_user(&addr, optval, sizeof(struct bus_addr)))
++ return -EFAULT;
++
++ if (optname == BUS_ADD_ADDR)
++ res = bus_add_addr(bus_peer_get(sock->sk), &addr);
++ else
++ res = bus_del_addr(bus_peer_get(sock->sk), &addr);
++ break;
++ case BUS_JOIN_BUS:
++ res = bus_join_bus(sock->sk);
++ break;
++ case BUS_SET_EAVESDROP:
++ res = bus_set_eavesdrop(sock->sk);
++ break;
++ case BUS_UNSET_EAVESDROP:
++ res = bus_unset_eavesdrop(sock->sk);
++ break;
++ case BUS_SET_SENDBUF:
++ case BUS_SET_MAXQLEN:
++ if (sock->sk->sk_state != BUS_LISTEN) {
++ res = -EINVAL;
++ } else {
++ res = -EFAULT;
++
++ if (copy_from_user(&val, optval, optlen))
++ break;
++
++ res = 0;
++
++ if (optname == BUS_SET_SENDBUF)
++ sk_sendbuf_set(sock->sk, val);
++ else
++ sk_maxqlen_set(sock->sk, val);
++ }
++ break;
++ case BUS_GET_QLENFULL:
++ res = bus_get_qlenfull(sock->sk);
++
++ if (copy_to_user(&res, optval, optlen)) {
++ res = -EFAULT;
++ break;
++ }
++ res = 0;
++ break;
++ default:
++ res = -EINVAL;
++ break;
++ }
++
++ return res;
++}
++
++long bus_inq_len(struct sock *sk)
++{
++ struct sk_buff *skb;
++ long amount = 0;
++
++ if (sk->sk_state == BUS_LISTEN)
++ return -EINVAL;
++
++ spin_lock(&sk->sk_receive_queue.lock);
++ skb_queue_walk(&sk->sk_receive_queue, skb)
++ amount += skb->len;
++ spin_unlock(&sk->sk_receive_queue.lock);
++
++ return amount;
++}
++EXPORT_SYMBOL_GPL(bus_inq_len);
++
++long bus_outq_len(struct sock *sk)
++{
++ return sk_wmem_alloc_get(sk);
++}
++EXPORT_SYMBOL_GPL(bus_outq_len);
++
++static int bus_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
++{
++ struct sock *sk = sock->sk;
++ long amount = 0;
++ int err;
++
++ switch (cmd) {
++ case SIOCOUTQ:
++ amount = bus_outq_len(sk);
++ err = put_user(amount, (int __user *)arg);
++ break;
++ case SIOCINQ:
++ amount = bus_inq_len(sk);
++ if (amount < 0)
++ err = amount;
++ else
++ err = put_user(amount, (int __user *)arg);
++ break;
++ default:
++ err = -ENOIOCTLCMD;
++ break;
++ }
++ return err;
++}
++
++static unsigned int bus_poll(struct file *file, struct socket *sock,
++ poll_table *wait)
++{
++ struct sock *sk = sock->sk, *other;
++ unsigned int mask, writable;
++ struct bus_sock *u = bus_sk(sk), *p;
++ struct hlist_node *node;
++
++ sock_poll_wait(file, sk_sleep(sk), wait);
++ mask = 0;
++
++ /* exceptional events? */
++ if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
++ mask |= POLLERR;
++ if (sk->sk_shutdown & RCV_SHUTDOWN)
++ mask |= POLLRDHUP | POLLIN | POLLRDNORM;
++ if (sk->sk_shutdown == SHUTDOWN_MASK)
++ mask |= POLLHUP;
++
++ /* readable? */
++ if (!skb_queue_empty(&sk->sk_receive_queue))
++ mask |= POLLIN | POLLRDNORM;
++
++ /* Connection-based need to check for termination and startup */
++ if (sk->sk_state == BUS_CLOSE)
++ mask |= POLLHUP;
++
++ /* No write status requested, avoid expensive OUT tests. */
++ if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT)))
++ return mask;
++
++ writable = bus_writable(sk);
++ other = bus_peer_get(sk);
++ if (other) {
++ if (bus_recvq_full(other))
++ writable = 0;
++ sock_put(other);
++ }
++
++ /*
++ * If the socket has already joined the bus we have to check
++ * that each peer receiver queue on the bus is not full.
++ */
++ if (!u->bus_master_side && u->authenticated) {
++ spin_lock(&u->bus->lock);
++ hlist_for_each_entry(p, node, &u->bus->peers, bus_node) {
++ if (bus_recvq_full(&p->sk)) {
++ writable = 0;
++ break;
++ }
++ }
++ spin_unlock(&u->bus->lock);
++ }
++
++ if (writable)
++ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
++ else
++ set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
++
++ return mask;
++}
++
++#ifdef CONFIG_PROC_FS
++static struct sock *first_bus_socket(int *i)
++{
++ for (*i = 0; *i <= BUS_HASH_SIZE; (*i)++) {
++ if (!hlist_empty(&bus_socket_table[*i]))
++ return __sk_head(&bus_socket_table[*i]);
++ }
++ return NULL;
++}
++
++static struct sock *next_bus_socket(int *i, struct sock *s)
++{
++ struct sock *next = sk_next(s);
++ /* More in this chain? */
++ if (next)
++ return next;
++ /* Look for next non-empty chain. */
++ for ((*i)++; *i <= BUS_HASH_SIZE; (*i)++) {
++ if (!hlist_empty(&bus_socket_table[*i]))
++ return __sk_head(&bus_socket_table[*i]);
++ }
++ return NULL;
++}
++
++struct bus_iter_state {
++ struct seq_net_private p;
++ int i;
++};
++
++static struct sock *bus_seq_idx(struct seq_file *seq, loff_t pos)
++{
++ struct bus_iter_state *iter = seq->private;
++ loff_t off = 0;
++ struct sock *s;
++
++ for (s = first_bus_socket(&iter->i); s;
++ s = next_bus_socket(&iter->i, s)) {
++ if (sock_net(s) != seq_file_net(seq))
++ continue;
++ if (off == pos)
++ return s;
++ ++off;
++ }
++ return NULL;
++}
++
++static void *bus_seq_start(struct seq_file *seq, loff_t *pos)
++ __acquires(bus_table_lock)
++{
++ spin_lock(&bus_table_lock);
++ return *pos ? bus_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN;
++}
++
++static void *bus_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++ struct bus_iter_state *iter = seq->private;
++ struct sock *sk = v;
++ ++*pos;
++
++ if (v == SEQ_START_TOKEN)
++ sk = first_bus_socket(&iter->i);
++ else
++ sk = next_bus_socket(&iter->i, sk);
++ while (sk && (sock_net(sk) != seq_file_net(seq)))
++ sk = next_bus_socket(&iter->i, sk);
++ return sk;
++}
++
++static void bus_seq_stop(struct seq_file *seq, void *v)
++ __releases(bus_table_lock)
++{
++ spin_unlock(&bus_table_lock);
++}
++
++static int bus_seq_show(struct seq_file *seq, void *v)
++{
++
++ if (v == SEQ_START_TOKEN)
++ seq_puts(seq, "Num RefCount Protocol Flags Type St " \
++ "Inode Path\n");
++ else {
++ struct sock *s = v;
++ struct bus_sock *u = bus_sk(s);
++ bus_state_lock(s);
++
++ seq_printf(seq, "%pK: %08X %08X %08X %04X %02X %5lu",
++ s,
++ atomic_read(&s->sk_refcnt),
++ 0,
++ s->sk_state == BUS_LISTEN ? __SO_ACCEPTCON : 0,
++ s->sk_type,
++ s->sk_socket ?
++ (s->sk_state == BUS_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
++ (s->sk_state == BUS_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
++ sock_i_ino(s));
++
++ if (u->addr) {
++ int i, len;
++ seq_putc(seq, ' ');
++
++ i = 0;
++ len = u->addr->len - sizeof(short);
++ if (!BUS_ABSTRACT(s))
++ len--;
++ else {
++ seq_putc(seq, '@');
++ i++;
++ }
++ for ( ; i < len; i++)
++ seq_putc(seq, u->addr->name->sbus_path[i]);
++ }
++ bus_state_unlock(s);
++ seq_putc(seq, '\n');
++ }
++
++ return 0;
++}
++
++static const struct seq_operations bus_seq_ops = {
++ .start = bus_seq_start,
++ .next = bus_seq_next,
++ .stop = bus_seq_stop,
++ .show = bus_seq_show,
++};
++
++static int bus_seq_open(struct inode *inode, struct file *file)
++{
++ return seq_open_net(inode, file, &bus_seq_ops,
++ sizeof(struct bus_iter_state));
++}
++
++static const struct file_operations bus_seq_fops = {
++ .owner = THIS_MODULE,
++ .open = bus_seq_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = seq_release_net,
++};
++
++#endif
++
++static const struct net_proto_family bus_family_ops = {
++ .family = PF_BUS,
++ .create = bus_create,
++ .owner = THIS_MODULE,
++};
++
++static int __init af_bus_init(void)
++{
++ int rc = -1;
++ struct sk_buff *dummy_skb;
++
++ BUILD_BUG_ON(sizeof(struct bus_skb_parms) > sizeof(dummy_skb->cb));
++
++ rc = proto_register(&bus_proto, 1);
++ if (rc != 0) {
++ pr_crit("%s: Cannot create bus_sock SLAB cache!\n", __func__);
++ return rc;
++ }
++
++ sock_register(&bus_family_ops);
++ return rc;
++}
++
++static void __exit af_bus_exit(void)
++{
++ sock_unregister(PF_BUS);
++ proto_unregister(&bus_proto);
++}
++
++module_init(af_bus_init);
++module_exit(af_bus_exit);
++
++MODULE_AUTHOR("Alban Crequy, Javier Martinez Canillas");
++MODULE_DESCRIPTION("Linux Bus domain sockets");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_NETPROTO(PF_BUS);
+Index: git/net/bus/garbage.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/bus/garbage.c 2012-10-05 13:37:11.000000000 +0300
+@@ -0,0 +1,322 @@
++/*
++ * Garbage Collector For AF_BUS sockets
++ *
++ * Based on Garbage Collector For AF_UNIX sockets (net/unix/garbage.c).
++ */
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/socket.h>
++#include <linux/un.h>
++#include <linux/net.h>
++#include <linux/fs.h>
++#include <linux/skbuff.h>
++#include <linux/netdevice.h>
++#include <linux/file.h>
++#include <linux/proc_fs.h>
++#include <linux/mutex.h>
++#include <linux/wait.h>
++
++#include <net/sock.h>
++#include <net/af_bus.h>
++#include <net/scm.h>
++#include <net/tcp_states.h>
++
++/* Internal data structures and random procedures: */
++
++static LIST_HEAD(gc_inflight_list);
++static LIST_HEAD(gc_candidates);
++static DEFINE_SPINLOCK(bus_gc_lock);
++static DECLARE_WAIT_QUEUE_HEAD(bus_gc_wait);
++
++unsigned int bus_tot_inflight;
++
++
++struct sock *bus_get_socket(struct file *filp)
++{
++ struct sock *u_sock = NULL;
++ struct inode *inode = filp->f_path.dentry->d_inode;
++
++ /*
++ * Socket ?
++ */
++ if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) {
++ struct socket *sock = SOCKET_I(inode);
++ struct sock *s = sock->sk;
++
++ /*
++ * PF_BUS ?
++ */
++ if (s && sock->ops && sock->ops->family == PF_BUS)
++ u_sock = s;
++ }
++ return u_sock;
++}
++
++/*
++ * Keep the number of times in flight count for the file
++ * descriptor if it is for an AF_BUS socket.
++ */
++
++void bus_inflight(struct file *fp)
++{
++ struct sock *s = bus_get_socket(fp);
++ if (s) {
++ struct bus_sock *u = bus_sk(s);
++ spin_lock(&bus_gc_lock);
++ if (atomic_long_inc_return(&u->inflight) == 1) {
++ BUG_ON(!list_empty(&u->link));
++ list_add_tail(&u->link, &gc_inflight_list);
++ } else {
++ BUG_ON(list_empty(&u->link));
++ }
++ bus_tot_inflight++;
++ spin_unlock(&bus_gc_lock);
++ }
++}
++
++void bus_notinflight(struct file *fp)
++{
++ struct sock *s = bus_get_socket(fp);
++ if (s) {
++ struct bus_sock *u = bus_sk(s);
++ spin_lock(&bus_gc_lock);
++ BUG_ON(list_empty(&u->link));
++ if (atomic_long_dec_and_test(&u->inflight))
++ list_del_init(&u->link);
++ bus_tot_inflight--;
++ spin_unlock(&bus_gc_lock);
++ }
++}
++
++static void scan_inflight(struct sock *x, void (*func)(struct bus_sock *),
++ struct sk_buff_head *hitlist)
++{
++ struct sk_buff *skb;
++ struct sk_buff *next;
++
++ spin_lock(&x->sk_receive_queue.lock);
++ skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
++ /*
++ * Do we have file descriptors ?
++ */
++ if (BUSCB(skb).fp) {
++ bool hit = false;
++ /*
++ * Process the descriptors of this socket
++ */
++ int nfd = BUSCB(skb).fp->count;
++ struct file **fp = BUSCB(skb).fp->fp;
++ while (nfd--) {
++ /*
++ * Get the socket the fd matches
++ * if it indeed does so
++ */
++ struct sock *sk = bus_get_socket(*fp++);
++ if (sk) {
++ struct bus_sock *u = bus_sk(sk);
++
++ /*
++ * Ignore non-candidates, they could
++ * have been added to the queues after
++ * starting the garbage collection
++ */
++ if (u->gc_candidate) {
++ hit = true;
++ func(u);
++ }
++ }
++ }
++ if (hit && hitlist != NULL) {
++ __skb_unlink(skb, &x->sk_receive_queue);
++ __skb_queue_tail(hitlist, skb);
++ }
++ }
++ }
++ spin_unlock(&x->sk_receive_queue.lock);
++}
++
++static void scan_children(struct sock *x, void (*func)(struct bus_sock *),
++ struct sk_buff_head *hitlist)
++{
++ if (x->sk_state != TCP_LISTEN)
++ scan_inflight(x, func, hitlist);
++ else {
++ struct sk_buff *skb;
++ struct sk_buff *next;
++ struct bus_sock *u;
++ LIST_HEAD(embryos);
++
++ /*
++ * For a listening socket collect the queued embryos
++ * and perform a scan on them as well.
++ */
++ spin_lock(&x->sk_receive_queue.lock);
++ skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
++ u = bus_sk(skb->sk);
++
++ /*
++ * An embryo cannot be in-flight, so it's safe
++ * to use the list link.
++ */
++ BUG_ON(!list_empty(&u->link));
++ list_add_tail(&u->link, &embryos);
++ }
++ spin_unlock(&x->sk_receive_queue.lock);
++
++ while (!list_empty(&embryos)) {
++ u = list_entry(embryos.next, struct bus_sock, link);
++ scan_inflight(&u->sk, func, hitlist);
++ list_del_init(&u->link);
++ }
++ }
++}
++
++static void dec_inflight(struct bus_sock *usk)
++{
++ atomic_long_dec(&usk->inflight);
++}
++
++static void inc_inflight(struct bus_sock *usk)
++{
++ atomic_long_inc(&usk->inflight);
++}
++
++static void inc_inflight_move_tail(struct bus_sock *u)
++{
++ atomic_long_inc(&u->inflight);
++ /*
++ * If this still might be part of a cycle, move it to the end
++ * of the list, so that it's checked even if it was already
++ * passed over
++ */
++ if (u->gc_maybe_cycle)
++ list_move_tail(&u->link, &gc_candidates);
++}
++
++static bool gc_in_progress = false;
++#define BUS_INFLIGHT_TRIGGER_GC 16000
++
++void wait_for_bus_gc(void)
++{
++ /*
++ * If number of inflight sockets is insane,
++ * force a garbage collect right now.
++ */
++ if (bus_tot_inflight > BUS_INFLIGHT_TRIGGER_GC && !gc_in_progress)
++ bus_gc();
++ wait_event(bus_gc_wait, gc_in_progress == false);
++}
++
++/* The external entry point: bus_gc() */
++void bus_gc(void)
++{
++ struct bus_sock *u;
++ struct bus_sock *next;
++ struct sk_buff_head hitlist;
++ struct list_head cursor;
++ LIST_HEAD(not_cycle_list);
++
++ spin_lock(&bus_gc_lock);
++
++ /* Avoid a recursive GC. */
++ if (gc_in_progress)
++ goto out;
++
++ gc_in_progress = true;
++ /*
++ * First, select candidates for garbage collection. Only
++ * in-flight sockets are considered, and from those only ones
++ * which don't have any external reference.
++ *
++ * Holding bus_gc_lock will protect these candidates from
++ * being detached, and hence from gaining an external
++ * reference. Since there are no possible receivers, all
++ * buffers currently on the candidates' queues stay there
++ * during the garbage collection.
++ *
++ * We also know that no new candidate can be added onto the
++ * receive queues. Other, non candidate sockets _can_ be
++ * added to queue, so we must make sure only to touch
++ * candidates.
++ */
++ list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
++ long total_refs;
++ long inflight_refs;
++
++ total_refs = file_count(u->sk.sk_socket->file);
++ inflight_refs = atomic_long_read(&u->inflight);
++
++ BUG_ON(inflight_refs < 1);
++ BUG_ON(total_refs < inflight_refs);
++ if (total_refs == inflight_refs) {
++ list_move_tail(&u->link, &gc_candidates);
++ u->gc_candidate = 1;
++ u->gc_maybe_cycle = 1;
++ }
++ }
++
++ /*
++ * Now remove all internal in-flight reference to children of
++ * the candidates.
++ */
++ list_for_each_entry(u, &gc_candidates, link)
++ scan_children(&u->sk, dec_inflight, NULL);
++
++ /*
++ * Restore the references for children of all candidates,
++ * which have remaining references. Do this recursively, so
++ * only those remain, which form cyclic references.
++ *
++ * Use a "cursor" link, to make the list traversal safe, even
++ * though elements might be moved about.
++ */
++ list_add(&cursor, &gc_candidates);
++ while (cursor.next != &gc_candidates) {
++ u = list_entry(cursor.next, struct bus_sock, link);
++
++ /* Move cursor to after the current position. */
++ list_move(&cursor, &u->link);
++
++ if (atomic_long_read(&u->inflight) > 0) {
++ list_move_tail(&u->link, &not_cycle_list);
++ u->gc_maybe_cycle = 0;
++ scan_children(&u->sk, inc_inflight_move_tail, NULL);
++ }
++ }
++ list_del(&cursor);
++
++ /*
++ * not_cycle_list contains those sockets which do not make up a
++ * cycle. Restore these to the inflight list.
++ */
++ while (!list_empty(&not_cycle_list)) {
++ u = list_entry(not_cycle_list.next, struct bus_sock, link);
++ u->gc_candidate = 0;
++ list_move_tail(&u->link, &gc_inflight_list);
++ }
++
++ /*
++ * Now gc_candidates contains only garbage. Restore original
++ * inflight counters for these as well, and remove the skbuffs
++ * which are creating the cycle(s).
++ */
++ skb_queue_head_init(&hitlist);
++ list_for_each_entry(u, &gc_candidates, link)
++ scan_children(&u->sk, inc_inflight, &hitlist);
++
++ spin_unlock(&bus_gc_lock);
++
++ /* Here we are. Hitlist is filled. Die. */
++ __skb_queue_purge(&hitlist);
++
++ spin_lock(&bus_gc_lock);
++
++ /* All candidates should have been detached by now. */
++ BUG_ON(!list_empty(&gc_candidates));
++ gc_in_progress = false;
++ wake_up(&bus_gc_wait);
++
++ out:
++ spin_unlock(&bus_gc_lock);
++}
+Index: git/net/core/scm.c
+===================================================================
+--- git.orig/net/core/scm.c 2012-10-05 12:12:51.000000000 +0300
++++ git/net/core/scm.c 2012-10-05 13:38:54.000000000 +0300
+@@ -158,7 +158,8 @@
+ switch (cmsg->cmsg_type)
+ {
+ case SCM_RIGHTS:
+- if (!sock->ops || sock->ops->family != PF_UNIX)
++ if (!sock->ops || (sock->ops->family != PF_UNIX &&
++ sock->ops->family != PF_BUS))
+ goto error;
+ err=scm_fp_copy(cmsg, &p->fp);
+ if (err<0)
+Index: git/net/core/sock.c
+===================================================================
+--- git.orig/net/core/sock.c 2012-10-05 12:12:51.000000000 +0300
++++ git/net/core/sock.c 2012-10-05 13:42:37.000000000 +0300
+@@ -205,7 +205,7 @@
+ "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" ,
+ "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" ,
+ "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" ,
+- "sk_lock-AF_NFC" , "sk_lock-AF_MAX"
++ "sk_lock-AF_NFC" , "sk_lock-AF_BUS" , "sk_lock-AF_MAX"
+ };
+ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
+ "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" ,
+@@ -221,7 +221,7 @@
+ "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" ,
+ "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" ,
+ "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" ,
+- "slock-AF_NFC" , "slock-AF_MAX"
++ "slock-AF_NFC" , "slock-AF_BUS" , "slock-AF_MAX"
+ };
+ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
+ "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" ,
+@@ -237,7 +237,7 @@
+ "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" ,
+ "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" ,
+ "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" ,
+- "clock-AF_NFC" , "clock-AF_MAX"
++ "clock-AF_NFC" , "clock-AF_BUS" , "clock-AF_MAX"
+ };
+
+ /*
+Index: git/net/netfilter/Kconfig
+===================================================================
+--- git.orig/net/netfilter/Kconfig 2012-10-05 12:13:57.000000000 +0300
++++ git/net/netfilter/Kconfig 2012-10-05 13:43:47.000000000 +0300
+@@ -1193,3 +1193,5 @@
+ source "net/netfilter/ipset/Kconfig"
+
+ source "net/netfilter/ipvs/Kconfig"
++
++source "net/netfilter/nfdbus/Kconfig"
+Index: git/net/netfilter/Makefile
+===================================================================
+--- git.orig/net/netfilter/Makefile 2012-10-05 12:13:57.000000000 +0300
++++ git/net/netfilter/Makefile 2012-10-05 13:44:39.000000000 +0300
+@@ -121,3 +121,6 @@
+
+ # IPVS
+ obj-$(CONFIG_IP_VS) += ipvs/
++
++# Dbus
++obj-$(CONFIG_NETFILTER_DBUS) += nfdbus/
+Index: git/net/netfilter/nfdbus/Kconfig
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/Kconfig 2012-10-05 13:47:00.000000000 +0300
+@@ -0,0 +1,12 @@
++#
++# Netfilter D-Bus module configuration
++#
++config NETFILTER_DBUS
++ tristate "Netfilter D-bus (EXPERIMENTAL)"
++ depends on AF_BUS && CONNECTOR && EXPERIMENTAL
++ ---help---
++ If you say Y here, you will include support for a netfilter hook to
++ parse D-Bus messages sent using the AF_BUS socket address family.
++
++ To compile this as a module, choose M here: the module will be
++ called netfilter_dbus.
+Index: git/net/netfilter/nfdbus/Makefile
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/Makefile 2012-10-05 13:47:47.000000000 +0300
+@@ -0,0 +1,6 @@
++#
++# Makefile for the netfilter D-Bus module
++#
++obj-$(CONFIG_NETFILTER_DBUS) += netfilter_dbus.o
++
++netfilter_dbus-y := nfdbus.o message.o matchrule.o
+Index: git/net/netfilter/nfdbus/matchrule.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/matchrule.c 2012-10-05 13:50:04.000000000 +0300
+@@ -0,0 +1,1132 @@
++/*
++ * matchrule.c D-Bus match rule implementation
++ *
++ * Based on signals.c from dbus
++ *
++ * Copyright (C) 2010 Collabora, Ltd.
++ * Copyright (C) 2003, 2005 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#include "matchrule.h"
++
++#include <linux/rbtree.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++
++#include "message.h"
++
++enum bus_match_flags {
++ BUS_MATCH_MESSAGE_TYPE = 1 << 0,
++ BUS_MATCH_INTERFACE = 1 << 1,
++ BUS_MATCH_MEMBER = 1 << 2,
++ BUS_MATCH_SENDER = 1 << 3,
++ BUS_MATCH_DESTINATION = 1 << 4,
++ BUS_MATCH_PATH = 1 << 5,
++ BUS_MATCH_ARGS = 1 << 6,
++ BUS_MATCH_PATH_NAMESPACE = 1 << 7,
++ BUS_MATCH_CLIENT_IS_EAVESDROPPING = 1 << 8
++};
++
++struct bus_match_rule {
++ /* For debugging only*/
++ char *rule_text;
++
++ unsigned int flags; /**< BusMatchFlags */
++
++ int message_type;
++ char *interface;
++ char *member;
++ char *sender;
++ char *destination;
++ char *path;
++
++ unsigned int *arg_lens;
++ char **args;
++ int args_len;
++
++ /* bus_match_rule is attached to rule_pool, either in a simple
++ * double-linked list if the rule does not have any interface, or in a
++ * red-black tree sorted by interface. If several rules can have the
++ * same interface, the first one is attached with struct rb_node and the
++ * next ones are in the list
++ */
++
++ struct rb_node node;
++ /* Doubly-linked non-circular list. If the rule has an interface, it is
++ * in the rb tree and the single head is right here. Otherwise, the
++ * single head is in rule_pool->rules_without_iface. With this data
++ * structure, we don't need any allocation to insert or remove the rule.
++ */
++ struct hlist_head first;
++ struct hlist_node list;
++
++ /* used to delete all names from the tree */
++ struct list_head del_list;
++};
++
++struct dbus_name {
++ struct rb_node node;
++ char *name;
++
++ /* used to delete all names from the tree */
++ struct list_head del_list;
++};
++
++#define BUS_MATCH_ARG_IS_PATH 0x8000000u
++
++#define DBUS_STRING_MAX_LENGTH 1024
++
++/** Max length of a match rule string; to keep people from hosing the
++ * daemon with some huge rule
++ */
++#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
++
++struct bus_match_rule *bus_match_rule_new(gfp_t gfp_flags)
++{
++ struct bus_match_rule *rule;
++
++ rule = kzalloc(sizeof(struct bus_match_rule), gfp_flags);
++ if (rule == NULL)
++ return NULL;
++
++ return rule;
++}
++
++void bus_match_rule_free(struct bus_match_rule *rule)
++{
++ kfree(rule->rule_text);
++ kfree(rule->interface);
++ kfree(rule->member);
++ kfree(rule->sender);
++ kfree(rule->destination);
++ kfree(rule->path);
++ kfree(rule->arg_lens);
++
++ /* can't use dbus_free_string_array() since there
++ * are embedded NULL
++ */
++ if (rule->args) {
++ int i;
++
++ i = 0;
++ while (i < rule->args_len) {
++ kfree(rule->args[i]);
++ ++i;
++ }
++
++ kfree(rule->args);
++ }
++
++ kfree(rule);
++}
++
++static int
++bus_match_rule_set_message_type(struct bus_match_rule *rule,
++ int type,
++ gfp_t gfp_flags)
++{
++ rule->flags |= BUS_MATCH_MESSAGE_TYPE;
++
++ rule->message_type = type;
++
++ return 1;
++}
++
++static int
++bus_match_rule_set_interface(struct bus_match_rule *rule,
++ const char *interface,
++ gfp_t gfp_flags)
++{
++ char *new;
++
++ WARN_ON(!interface);
++
++ new = kstrdup(interface, gfp_flags);
++ if (new == NULL)
++ return 0;
++
++ rule->flags |= BUS_MATCH_INTERFACE;
++ kfree(rule->interface);
++ rule->interface = new;
++
++ return 1;
++}
++
++static int
++bus_match_rule_set_member(struct bus_match_rule *rule,
++ const char *member,
++ gfp_t gfp_flags)
++{
++ char *new;
++
++ WARN_ON(!member);
++
++ new = kstrdup(member, gfp_flags);
++ if (new == NULL)
++ return 0;
++
++ rule->flags |= BUS_MATCH_MEMBER;
++ kfree(rule->member);
++ rule->member = new;
++
++ return 1;
++}
++
++static int
++bus_match_rule_set_sender(struct bus_match_rule *rule,
++ const char *sender,
++ gfp_t gfp_flags)
++{
++ char *new;
++
++ WARN_ON(!sender);
++
++ new = kstrdup(sender, gfp_flags);
++ if (new == NULL)
++ return 0;
++
++ rule->flags |= BUS_MATCH_SENDER;
++ kfree(rule->sender);
++ rule->sender = new;
++
++ return 1;
++}
++
++static int
++bus_match_rule_set_destination(struct bus_match_rule *rule,
++ const char *destination,
++ gfp_t gfp_flags)
++{
++ char *new;
++
++ WARN_ON(!destination);
++
++ new = kstrdup(destination, gfp_flags);
++ if (new == NULL)
++ return 0;
++
++ rule->flags |= BUS_MATCH_DESTINATION;
++ kfree(rule->destination);
++ rule->destination = new;
++
++ return 1;
++}
++
++#define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || \
++ ((c) == '\r'))
++
++static int find_key(const char *str, int start, char *key, int *value_pos)
++{
++ const char *p;
++ const char *s;
++ const char *key_start;
++ const char *key_end;
++
++ s = str;
++
++ p = s + start;
++
++ while (*p && ISWHITE(*p))
++ ++p;
++
++ key_start = p;
++
++ while (*p && *p != '=' && !ISWHITE(*p))
++ ++p;
++
++ key_end = p;
++
++ while (*p && ISWHITE(*p))
++ ++p;
++
++ if (key_start == key_end) {
++ /* Empty match rules or trailing whitespace are OK */
++ *value_pos = p - s;
++ return 1;
++ }
++
++ if (*p != '=') {
++ pr_warn("Match rule has a key with no subsequent '=' character");
++ return 0;
++ }
++ ++p;
++
++ strncat(key, key_start, key_end - key_start);
++
++ *value_pos = p - s;
++
++ return 1;
++}
++
++static int find_value(const char *str, int start, const char *key, char *value,
++ int *value_end)
++{
++ const char *p;
++ const char *s;
++ char quote_char;
++ int orig_len;
++
++ orig_len = strlen(value);
++
++ s = str;
++
++ p = s + start;
++
++ quote_char = '\0';
++
++ while (*p) {
++ if (quote_char == '\0') {
++ switch (*p) {
++ case '\0':
++ goto done;
++
++ case '\'':
++ quote_char = '\'';
++ goto next;
++
++ case ',':
++ ++p;
++ goto done;
++
++ case '\\':
++ quote_char = '\\';
++ goto next;
++
++ default:
++ strncat(value, p, 1);
++ }
++ } else if (quote_char == '\\') {
++ /*\ only counts as an escape if escaping a quote mark */
++ if (*p != '\'')
++ strncat(value, "\\", 1);
++
++ strncat(value, p, 1);
++
++ quote_char = '\0';
++ } else {
++ if (*p == '\'')
++ quote_char = '\0';
++ else
++ strncat(value, p, 1);
++ }
++
++next:
++ ++p;
++ }
++
++done:
++
++ if (quote_char == '\\')
++ strncat(value, "\\", 1);
++ else if (quote_char == '\'') {
++ pr_warn("Unbalanced quotation marks in match rule");
++ return 0;
++ }
++
++ /* Zero-length values are allowed */
++
++ *value_end = p - s;
++
++ return 1;
++}
++
++/* duplicates aren't allowed so the real legitimate max is only 6 or
++ * so. Leaving extra so we don't have to bother to update it.
++ * FIXME this is sort of busted now with arg matching, but we let
++ * you match on up to 10 args for now
++ */
++#define MAX_RULE_TOKENS 16
++
++/* this is slightly too high level to be termed a "token"
++ * but let's not be pedantic.
++ */
++struct rule_token {
++ char *key;
++ char *value;
++};
++
++static int tokenize_rule(const char *rule_text,
++ struct rule_token tokens[MAX_RULE_TOKENS],
++ gfp_t gfp_flags)
++{
++ int i;
++ int pos;
++ int retval;
++
++ retval = 0;
++
++ i = 0;
++ pos = 0;
++ while (i < MAX_RULE_TOKENS &&
++ pos < strlen(rule_text)) {
++ char *key;
++ char *value;
++
++ key = kzalloc(DBUS_STRING_MAX_LENGTH, gfp_flags);
++ if (!key) {
++ pr_err("Out of memory");
++ return 0;
++ }
++
++ value = kzalloc(DBUS_STRING_MAX_LENGTH, gfp_flags);
++ if (!value) {
++ kfree(key);
++ pr_err("Out of memory");
++ return 0;
++ }
++
++ if (!find_key(rule_text, pos, key, &pos))
++ goto out;
++
++ if (strlen(key) == 0)
++ goto next;
++
++ tokens[i].key = key;
++
++ if (!find_value(rule_text, pos, tokens[i].key, value, &pos))
++ goto out;
++
++ tokens[i].value = value;
++
++next:
++ ++i;
++ }
++
++ retval = 1;
++
++out:
++ if (!retval) {
++ i = 0;
++ while (tokens[i].key || tokens[i].value) {
++ kfree(tokens[i].key);
++ kfree(tokens[i].value);
++ tokens[i].key = NULL;
++ tokens[i].value = NULL;
++ ++i;
++ }
++ }
++
++ return retval;
++}
++
++/*
++ * The format is comma-separated with strings quoted with single quotes
++ * as for the shell (to escape a literal single quote, use '\'').
++ *
++ * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',
++ * member='Foo', path='/bar/foo',destination=':452345.34'
++ *
++ */
++struct bus_match_rule *bus_match_rule_parse(const char *rule_text,
++ gfp_t gfp_flags)
++{
++ struct bus_match_rule *rule;
++ struct rule_token tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
++ int i;
++
++ if (strlen(rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH) {
++ pr_warn("Match rule text is %ld bytes, maximum is %d",
++ strlen(rule_text),
++ DBUS_MAXIMUM_MATCH_RULE_LENGTH);
++ return NULL;
++ }
++
++ memset(tokens, '\0', sizeof(tokens));
++
++ rule = bus_match_rule_new(gfp_flags);
++ if (rule == NULL) {
++ pr_err("Out of memory");
++ goto failed;
++ }
++
++ rule->rule_text = kstrdup(rule_text, gfp_flags);
++ if (rule->rule_text == NULL) {
++ pr_err("Out of memory");
++ goto failed;
++ }
++
++ if (!tokenize_rule(rule_text, tokens, gfp_flags))
++ goto failed;
++
++ i = 0;
++ while (tokens[i].key != NULL) {
++ const char *key = tokens[i].key;
++ const char *value = tokens[i].value;
++
++ if (strcmp(key, "type") == 0) {
++ int t;
++
++ if (rule->flags & BUS_MATCH_MESSAGE_TYPE) {
++ pr_warn("Key %s specified twice in match rule\n",
++ key);
++ goto failed;
++ }
++
++ t = dbus_message_type_from_string(value);
++
++ if (t == DBUS_MESSAGE_TYPE_INVALID) {
++ pr_warn("Invalid message type (%s) in match rule\n",
++ value);
++ goto failed;
++ }
++
++ if (!bus_match_rule_set_message_type(rule, t,
++ gfp_flags)) {
++ pr_err("Out of memeory");
++ goto failed;
++ }
++ } else if (strcmp(key, "sender") == 0) {
++ if (rule->flags & BUS_MATCH_SENDER) {
++ pr_warn("Key %s specified twice in match rule\n",
++ key);
++ goto failed;
++ }
++
++ if (!bus_match_rule_set_sender(rule, value,
++ gfp_flags)) {
++ pr_err("Out of memeory");
++ goto failed;
++ }
++ } else if (strcmp(key, "interface") == 0) {
++ if (rule->flags & BUS_MATCH_INTERFACE) {
++ pr_warn("Key %s specified twice in match rule\n",
++ key);
++ goto failed;
++ }
++
++ if (!bus_match_rule_set_interface(rule, value,
++ gfp_flags)) {
++ pr_err("Out of memeory");
++ goto failed;
++ }
++ } else if (strcmp(key, "member") == 0) {
++ if (rule->flags & BUS_MATCH_MEMBER) {
++ pr_warn("Key %s specified twice in match rule\n",
++ key);
++ goto failed;
++ }
++
++ if (!bus_match_rule_set_member(rule, value,
++ gfp_flags)) {
++ pr_err("Out of memeory");
++ goto failed;
++ }
++ } else if (strcmp(key, "destination") == 0) {
++ if (rule->flags & BUS_MATCH_DESTINATION) {
++ pr_warn("Key %s specified twice in match rule\n",
++ key);
++ goto failed;
++ }
++
++ if (!bus_match_rule_set_destination(rule, value,
++ gfp_flags)) {
++ pr_err("Out of memeory");
++ goto failed;
++ }
++ } else if (strcmp(key, "eavesdrop") == 0) {
++ if (strcmp(value, "true") == 0) {
++ rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING;
++ } else if (strcmp(value, "false") == 0) {
++ rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING);
++ } else {
++ pr_warn("eavesdrop='%s' is invalid, " \
++ "it should be 'true' or 'false'\n",
++ value);
++ goto failed;
++ }
++ } else if (strncmp(key, "arg", 3) != 0) {
++ pr_warn("Unknown key \"%s\" in match rule\n",
++ key);
++ goto failed;
++ }
++
++ ++i;
++ }
++
++ goto out;
++
++failed:
++ if (rule) {
++ bus_match_rule_free(rule);
++ rule = NULL;
++ }
++
++out:
++
++ i = 0;
++ while (tokens[i].key || tokens[i].value) {
++ WARN_ON(i >= MAX_RULE_TOKENS);
++ kfree(tokens[i].key);
++ kfree(tokens[i].value);
++ ++i;
++ }
++
++ return rule;
++}
++
++/* return the match rule containing the hlist_head. It may not be the first
++ * match rule in the list. */
++struct bus_match_rule *match_rule_search(struct rb_root *root,
++ const char *interface)
++{
++ struct rb_node *node = root->rb_node;
++
++ while (node) {
++ struct bus_match_rule *data =
++ container_of(node, struct bus_match_rule, node);
++ int result;
++
++ result = strcmp(interface, data->interface);
++
++ if (result < 0)
++ node = node->rb_left;
++ else if (result > 0)
++ node = node->rb_right;
++ else
++ return data;
++ }
++ return NULL;
++}
++
++void match_rule_insert(struct rb_root *root, struct bus_match_rule *data)
++{
++ struct rb_node **new = &(root->rb_node), *parent = NULL;
++
++ /* Figure out where to put new node */
++ while (*new) {
++ struct bus_match_rule *this =
++ container_of(*new, struct bus_match_rule, node);
++ int result = strcmp(data->interface, this->interface);
++
++ parent = *new;
++ if (result < 0)
++ new = &((*new)->rb_left);
++ else if (result > 0)
++ new = &((*new)->rb_right);
++ else {
++ /* the head is not used */
++ INIT_HLIST_HEAD(&data->first);
++ /* Add it at the beginning of the list */
++ hlist_add_head(&data->list, &this->first);
++ return;
++ }
++ }
++
++ /* this rule is single in its list */
++ INIT_HLIST_HEAD(&data->first);
++ hlist_add_head(&data->list, &data->first);
++
++ /* Add new node and rebalance tree. */
++ rb_link_node(&data->node, parent, new);
++ rb_insert_color(&data->node, root);
++}
++
++struct bus_match_maker *bus_matchmaker_new(gfp_t gfp_flags)
++{
++ struct bus_match_maker *matchmaker;
++ int i;
++
++ matchmaker = kzalloc(sizeof(struct bus_match_maker), gfp_flags);
++ if (matchmaker == NULL)
++ return NULL;
++
++ for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) {
++ struct rule_pool *p = matchmaker->rules_by_type + i;
++
++ p->rules_by_iface = RB_ROOT;
++ }
++
++ kref_init(&matchmaker->kref);
++
++ return matchmaker;
++}
++
++void bus_matchmaker_free(struct kref *kref)
++{
++ struct bus_match_maker *matchmaker;
++ struct list_head del_list;
++ struct rb_node *n;
++ int i;
++
++ matchmaker = container_of(kref, struct bus_match_maker, kref);
++
++ /* free names */
++ INIT_LIST_HEAD(&del_list);
++ n = matchmaker->names.rb_node;
++ if (n) {
++ struct dbus_name *dbus_name, *cur, *tmp;
++
++ dbus_name = rb_entry(n, struct dbus_name, node);
++ list_add_tail(&dbus_name->del_list, &del_list);
++
++ list_for_each_entry(cur, &del_list, del_list) {
++ struct dbus_name *right, *left;
++ if (cur->node.rb_right) {
++ right = rb_entry(cur->node.rb_right,
++ struct dbus_name, node);
++ list_add_tail(&right->del_list, &del_list);
++ }
++ if (cur->node.rb_left) {
++ left = rb_entry(cur->node.rb_left,
++ struct dbus_name, node);
++ list_add_tail(&left->del_list, &del_list);
++ }
++ }
++ list_for_each_entry_safe(dbus_name, tmp, &del_list, del_list) {
++ kfree(dbus_name->name);
++ list_del(&dbus_name->del_list);
++ kfree(dbus_name);
++ }
++ }
++ WARN_ON(!list_empty_careful(&del_list));
++
++ /* free match rules */
++ for (i = 0 ; i < DBUS_NUM_MESSAGE_TYPES ; i++) {
++ struct rule_pool *pool = matchmaker->rules_by_type + i;
++ struct bus_match_rule *match_rule, *cur, *tmp;
++ struct hlist_node *list_tmp, *list_tmp2;
++
++ /* free match rules from the list */
++ hlist_for_each_entry_safe(cur, list_tmp, list_tmp2,
++ &pool->rules_without_iface, list) {
++ bus_match_rule_free(cur);
++ }
++
++ /* free match rules from the tree */
++ if (!pool->rules_by_iface.rb_node)
++ continue;
++ match_rule = rb_entry(pool->rules_by_iface.rb_node,
++ struct bus_match_rule, node);
++ list_add_tail(&match_rule->del_list, &del_list);
++
++ list_for_each_entry(cur, &del_list, del_list) {
++ struct bus_match_rule *right, *left;
++ if (cur->node.rb_right) {
++ right = rb_entry(cur->node.rb_right,
++ struct bus_match_rule, node);
++ list_add_tail(&right->del_list, &del_list);
++ }
++ if (cur->node.rb_left) {
++ left = rb_entry(cur->node.rb_left,
++ struct bus_match_rule, node);
++ list_add_tail(&left->del_list, &del_list);
++ }
++ }
++ list_for_each_entry_safe(match_rule, tmp, &del_list, del_list) {
++ /* keep a ref during the loop to ensure the first
++ * iteration of the loop does not delete it */
++ hlist_for_each_entry_safe(cur, list_tmp, list_tmp2,
++ &match_rule->first, list) {
++ if (cur != match_rule)
++ bus_match_rule_free(cur);
++ }
++ list_del(&match_rule->del_list);
++ bus_match_rule_free(match_rule);
++ }
++ WARN_ON(!list_empty_careful(&del_list));
++ }
++
++ kfree(matchmaker);
++}
++
++/* The rule can't be modified after it's added. */
++int bus_matchmaker_add_rule(struct bus_match_maker *matchmaker,
++ struct bus_match_rule *rule)
++{
++ struct rule_pool *pool;
++
++ WARN_ON(rule->message_type < 0);
++ WARN_ON(rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
++
++ pool = matchmaker->rules_by_type + rule->message_type;
++
++ if (rule->interface)
++ match_rule_insert(&pool->rules_by_iface, rule);
++ else
++ hlist_add_head(&rule->list, &pool->rules_without_iface);
++
++ return 1;
++}
++
++static int match_rule_equal(struct bus_match_rule *a,
++ struct bus_match_rule *b)
++{
++ if (a->flags != b->flags)
++ return 0;
++
++ if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
++ a->message_type != b->message_type)
++ return 0;
++
++ if ((a->flags & BUS_MATCH_MEMBER) &&
++ strcmp(a->member, b->member) != 0)
++ return 0;
++
++ if ((a->flags & BUS_MATCH_PATH) &&
++ strcmp(a->path, b->path) != 0)
++ return 0;
++
++ if ((a->flags & BUS_MATCH_INTERFACE) &&
++ strcmp(a->interface, b->interface) != 0)
++ return 0;
++
++ if ((a->flags & BUS_MATCH_SENDER) &&
++ strcmp(a->sender, b->sender) != 0)
++ return 0;
++
++ if ((a->flags & BUS_MATCH_DESTINATION) &&
++ strcmp(a->destination, b->destination) != 0)
++ return 0;
++
++ if (a->flags & BUS_MATCH_ARGS) {
++ int i;
++
++ if (a->args_len != b->args_len)
++ return 0;
++
++ i = 0;
++ while (i < a->args_len) {
++ int length;
++
++ if ((a->args[i] != NULL) != (b->args[i] != NULL))
++ return 0;
++
++ if (a->arg_lens[i] != b->arg_lens[i])
++ return 0;
++
++ length = a->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
++
++ if (a->args[i] != NULL) {
++ WARN_ON(!b->args[i]);
++ if (memcmp(a->args[i], b->args[i], length) != 0)
++ return 0;
++ }
++
++ ++i;
++ }
++ }
++
++ return 1;
++}
++
++/* Remove a single rule which is equal to the given rule by value */
++void bus_matchmaker_remove_rule_by_value(struct bus_match_maker *matchmaker,
++ struct bus_match_rule *rule)
++{
++ struct rule_pool *pool;
++
++ WARN_ON(rule->message_type < 0);
++ WARN_ON(rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
++
++ pool = matchmaker->rules_by_type + rule->message_type;
++
++ if (rule->interface) {
++ struct bus_match_rule *head =
++ match_rule_search(&pool->rules_by_iface,
++ rule->interface);
++
++ struct hlist_node *cur;
++ struct bus_match_rule *cur_rule;
++ hlist_for_each_entry(cur_rule, cur, &head->first, list) {
++ if (match_rule_equal(cur_rule, rule)) {
++ hlist_del(cur);
++ if (hlist_empty(&head->first))
++ rb_erase(&head->node,
++ &pool->rules_by_iface);
++ bus_match_rule_free(cur_rule);
++ break;
++ }
++ }
++ } else {
++ struct hlist_head *head = &pool->rules_without_iface;
++
++ struct hlist_node *cur;
++ struct bus_match_rule *cur_rule;
++ hlist_for_each_entry(cur_rule, cur, head, list) {
++ if (match_rule_equal(cur_rule, rule)) {
++ hlist_del(cur);
++ bus_match_rule_free(cur_rule);
++ break;
++ }
++ }
++ }
++
++}
++
++static int connection_is_primary_owner(struct bus_match_maker *connection,
++ const char *service_name)
++{
++ struct rb_node *node = connection->names.rb_node;
++
++ if (!service_name)
++ return 0;
++
++ while (node) {
++ struct dbus_name *data = container_of(node, struct dbus_name,
++ node);
++ int result;
++
++ result = strcmp(service_name, data->name);
++
++ if (result < 0)
++ node = node->rb_left;
++ else if (result > 0)
++ node = node->rb_right;
++ else
++ return 1;
++ }
++ return 0;
++}
++
++static int match_rule_matches(struct bus_match_maker *matchmaker,
++ struct bus_match_maker *sender,
++ int eavesdrop,
++ struct bus_match_rule *rule,
++ const struct dbus_message *message)
++{
++ /* Don't consider the rule if this is a eavesdropping match rule
++ * and eavesdropping is not allowed on that peer */
++ if ((rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) && !eavesdrop)
++ return 0;
++
++ /* Since D-Bus 1.5.6, match rules do not match messages which have a
++ * DESTINATION field unless the match rule specifically requests this
++ * by specifying eavesdrop='true' in the match rule. */
++ if (message->destination &&
++ !(rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING))
++ return 0;
++
++ if (rule->flags & BUS_MATCH_MEMBER) {
++ const char *member;
++
++ WARN_ON(!rule->member);
++
++ member = message->member;
++ if (member == NULL)
++ return 0;
++
++ if (strcmp(member, rule->member) != 0)
++ return 0;
++ }
++
++ if (rule->flags & BUS_MATCH_SENDER) {
++ WARN_ON(!rule->sender);
++
++ if (sender == NULL) {
++ if (strcmp(rule->sender,
++ "org.freedesktop.DBus") != 0)
++ return 0;
++ } else
++ if (!connection_is_primary_owner(sender, rule->sender))
++ return 0;
++ }
++
++ if (rule->flags & BUS_MATCH_DESTINATION) {
++ const char *destination;
++
++ WARN_ON(!rule->destination);
++
++ destination = message->destination;
++ if (destination == NULL)
++ return 0;
++
++ /* This will not just work out of the box because it this is
++ * an eavesdropping match rule. */
++ if (matchmaker == NULL) {
++ if (strcmp(rule->destination,
++ "org.freedesktop.DBus") != 0)
++ return 0;
++ } else
++ if (!connection_is_primary_owner(matchmaker,
++ rule->destination))
++ return 0;
++ }
++
++ if (rule->flags & BUS_MATCH_PATH) {
++ const char *path;
++
++ WARN_ON(!rule->path);
++
++ path = message->path;
++ if (path == NULL)
++ return 0;
++
++ if (strcmp(path, rule->path) != 0)
++ return 0;
++ }
++
++ return 1;
++}
++
++static bool get_recipients_from_list(struct bus_match_maker *matchmaker,
++ struct bus_match_maker *sender,
++ int eavesdrop,
++ struct hlist_head *rules,
++ const struct dbus_message *message)
++{
++ struct hlist_node *cur;
++ struct bus_match_rule *rule;
++
++ if (rules == NULL) {
++ pr_debug("no rules of this type\n");
++ return 0;
++ }
++
++ hlist_for_each_entry(rule, cur, rules, list) {
++ if (match_rule_matches(matchmaker, sender, eavesdrop, rule,
++ message)) {
++ pr_debug("[YES] deliver with match rule \"%s\"\n",
++ rule->rule_text);
++ return 1;
++ } else {
++ pr_debug("[NO] deliver with match rule \"%s\"\n",
++ rule->rule_text);
++ }
++ }
++ pr_debug("[NO] no match rules\n");
++ return 0;
++}
++
++static struct hlist_head
++*bus_matchmaker_get_rules(struct bus_match_maker *matchmaker,
++ int message_type, const char *interface)
++{
++ static struct hlist_head empty = {0,};
++ struct rule_pool *p;
++
++ WARN_ON(message_type < 0);
++ WARN_ON(message_type >= DBUS_NUM_MESSAGE_TYPES);
++
++ p = matchmaker->rules_by_type + message_type;
++
++ if (interface == NULL)
++ return &p->rules_without_iface;
++ else {
++ struct bus_match_rule *rule =
++ match_rule_search(&p->rules_by_iface, interface);
++ if (rule)
++ return &rule->first;
++ else
++ return &empty;
++ }
++}
++
++bool bus_matchmaker_filter(struct bus_match_maker *matchmaker,
++ struct bus_match_maker *sender,
++ int eavesdrop,
++ const struct dbus_message *message)
++{
++ int type;
++ const char *interface;
++ struct hlist_head *neither, *just_type, *just_iface, *both;
++
++ type = message->type;
++ interface = message->interface;
++
++ neither = bus_matchmaker_get_rules(matchmaker,
++ DBUS_MESSAGE_TYPE_INVALID, NULL);
++ just_type = just_iface = both = NULL;
++
++ if (interface != NULL)
++ just_iface = bus_matchmaker_get_rules(matchmaker,
++ DBUS_MESSAGE_TYPE_INVALID,
++ interface);
++
++ if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES) {
++ just_type = bus_matchmaker_get_rules(matchmaker, type, NULL);
++
++ if (interface != NULL)
++ both = bus_matchmaker_get_rules(matchmaker, type,
++ interface);
++ }
++
++ if (get_recipients_from_list(matchmaker, sender, eavesdrop, neither,
++ message))
++ return 1;
++ if (get_recipients_from_list(matchmaker, sender, eavesdrop, just_iface,
++ message))
++ return 1;
++ if (get_recipients_from_list(matchmaker, sender, eavesdrop, just_type,
++ message))
++ return 1;
++ if (get_recipients_from_list(matchmaker, sender, eavesdrop, both,
++ message))
++ return 1;
++
++ return connection_is_primary_owner(matchmaker, message->destination);
++}
++
++void bus_matchmaker_add_name(struct bus_match_maker *matchmaker,
++ const char *name,
++ gfp_t gfp_flags)
++{
++ struct dbus_name *dbus_name;
++ struct rb_node **new = &(matchmaker->names.rb_node), *parent = NULL;
++
++ dbus_name = kmalloc(sizeof(struct dbus_name), gfp_flags);
++ if (!dbus_name)
++ return;
++ dbus_name->name = kstrdup(name, gfp_flags);
++ if (!dbus_name->name)
++ return;
++
++ /* Figure out where to put new node */
++ while (*new) {
++ struct dbus_name *this = container_of(*new, struct dbus_name,
++ node);
++ int result = strcmp(dbus_name->name, this->name);
++
++ parent = *new;
++ if (result < 0)
++ new = &((*new)->rb_left);
++ else if (result > 0)
++ new = &((*new)->rb_right);
++ else
++ return;
++ }
++
++ /* Add new node and rebalance tree. */
++ rb_link_node(&dbus_name->node, parent, new);
++ rb_insert_color(&dbus_name->node, &matchmaker->names);
++}
++
++void bus_matchmaker_remove_name(struct bus_match_maker *matchmaker,
++ const char *name)
++{
++ struct rb_node *node = matchmaker->names.rb_node;
++
++ while (node) {
++ struct dbus_name *data = container_of(node, struct dbus_name,
++ node);
++ int result;
++
++ result = strcmp(name, data->name);
++
++ if (result < 0)
++ node = node->rb_left;
++ else if (result > 0)
++ node = node->rb_right;
++ else {
++ rb_erase(&data->node, &matchmaker->names);
++ kfree(data->name);
++ kfree(data);
++ }
++ }
++
++}
++
+Index: git/net/netfilter/nfdbus/matchrule.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/matchrule.h 2012-10-05 13:51:44.000000000 +0300
+@@ -0,0 +1,82 @@
++/*
++ * signals.h Bus signal connection implementation
++ *
++ * Copyright (C) 2003 Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#ifndef BUS_SIGNALS_H
++#define BUS_SIGNALS_H
++
++#include <linux/gfp.h>
++#include <linux/list.h>
++#include <linux/rbtree.h>
++#include <linux/slab.h>
++#include <net/af_bus.h>
++
++#include "message.h"
++
++struct bus_match_rule *bus_match_rule_new(gfp_t gfp_flags);
++void bus_match_rule_free(struct bus_match_rule *rule);
++
++struct bus_match_rule *bus_match_rule_parse(const char *rule_text,
++ gfp_t gfp_flags);
++
++struct rule_pool {
++ /* Maps non-NULL interface names to a list of bus_match_rule */
++ struct rb_root rules_by_iface;
++
++ /* List of bus_match_rule which don't specify an interface */
++ struct hlist_head rules_without_iface;
++};
++
++struct bus_match_maker {
++ struct sockaddr_bus addr;
++
++ struct hlist_node table_node;
++
++ /* Pools of rules, grouped by the type of message they match. 0
++ * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a
++ * message type.
++ */
++ struct rule_pool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
++
++ struct rb_root names;
++
++ struct kref kref;
++};
++
++
++struct bus_match_maker *bus_matchmaker_new(gfp_t gfp_flags);
++void bus_matchmaker_free(struct kref *kref);
++
++int bus_matchmaker_add_rule(struct bus_match_maker *matchmaker,
++ struct bus_match_rule *rule);
++void bus_matchmaker_remove_rule_by_value(struct bus_match_maker *matchmaker,
++ struct bus_match_rule *value);
++
++bool bus_matchmaker_filter(struct bus_match_maker *matchmaker,
++ struct bus_match_maker *sender,
++ int eavesdrop,
++ const struct dbus_message *message);
++
++void bus_matchmaker_add_name(struct bus_match_maker *matchmaker,
++ const char *name, gfp_t gfp_flags);
++void bus_matchmaker_remove_name(struct bus_match_maker *matchmaker,
++ const char *name);
++
++#endif /* BUS_SIGNALS_H */
+Index: git/net/netfilter/nfdbus/message.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/message.c 2012-10-05 13:52:50.000000000 +0300
+@@ -0,0 +1,194 @@
++/*
++ * message.c Basic D-Bus message parsing
++ *
++ * Copyright (C) 2010-2012 Collabora Ltd
++ * Authors: Alban Crequy <alban.crequy@collabora.co.uk>
++ * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
++ * Copyright (C) 2002, 2003 CodeFactory AB
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#include <linux/slab.h>
++
++#include "message.h"
++
++int dbus_message_type_from_string(const char *type_str)
++{
++ if (strcmp(type_str, "method_call") == 0)
++ return DBUS_MESSAGE_TYPE_METHOD_CALL;
++ if (strcmp(type_str, "method_return") == 0)
++ return DBUS_MESSAGE_TYPE_METHOD_RETURN;
++ else if (strcmp(type_str, "signal") == 0)
++ return DBUS_MESSAGE_TYPE_SIGNAL;
++ else if (strcmp(type_str, "error") == 0)
++ return DBUS_MESSAGE_TYPE_ERROR;
++ else
++ return DBUS_MESSAGE_TYPE_INVALID;
++}
++
++int dbus_message_parse(unsigned char *message, size_t len,
++ struct dbus_message *dbus_message)
++{
++ unsigned char *cur;
++ int array_header_len;
++
++ dbus_message->message = message;
++
++ if (len < 4 + 4 + 4 + 4 || message[1] == 0 || message[1] > 4)
++ return -EINVAL;
++
++ dbus_message->type = message[1];
++ dbus_message->body_length = *((u32 *)(message + 4));
++ cur = message + 12;
++ array_header_len = *(u32 *)cur;
++ dbus_message->len_offset = 12;
++ cur += 4;
++ while (cur < message + len
++ && cur < message + 12 + 4 + array_header_len) {
++ int header_code;
++ int signature_len;
++ unsigned char *signature;
++ int str_len;
++ unsigned char *str;
++
++ /* D-Bus alignment craziness */
++ if ((cur - message) % 8 != 0)
++ cur += 8 - (cur - message) % 8;
++
++ header_code = *(char *)cur;
++ cur++;
++ signature_len = *(char *)cur;
++ /* All header fields of the current D-Bus spec have a simple
++ * type, either o, s, g, or u */
++ if (signature_len != 1)
++ return -EINVAL;
++ cur++;
++ signature = cur;
++ cur += signature_len + 1;
++ if (signature[0] != 'o' &&
++ signature[0] != 's' &&
++ signature[0] != 'g' &&
++ signature[0] != 'u')
++ return -EINVAL;
++
++ if (signature[0] == 'u') {
++ cur += 4;
++ continue;
++ }
++
++ if (signature[0] != 'g') {
++ str_len = *(u32 *)cur;
++ cur += 4;
++ } else {
++ str_len = *(char *)cur;
++ cur += 1;
++ }
++
++ str = cur;
++ switch (header_code) {
++ case 1:
++ dbus_message->path = str;
++ break;
++ case 2:
++ dbus_message->interface = str;
++ break;
++ case 3:
++ dbus_message->member = str;
++ break;
++ case 6:
++ dbus_message->destination = str;
++ break;
++ case 7:
++ dbus_message->sender = str;
++ break;
++ case 8:
++ dbus_message->body_signature = str;
++ break;
++ }
++ cur += str_len + 1;
++ }
++
++ dbus_message->padding_end = (8 - (cur - message) % 8) % 8;
++
++ /* Jump to body D-Bus alignment craziness */
++ if ((cur - message) % 8 != 0)
++ cur += 8 - (cur - message) % 8;
++ dbus_message->new_header_offset = cur - message;
++
++ if (dbus_message->new_header_offset
++ + dbus_message->body_length != len) {
++ pr_warn("Message truncated? " \
++ "Header %d + Body %d != Length %zd\n",
++ dbus_message->new_header_offset,
++ dbus_message->body_length, len);
++ return -EINVAL;
++ }
++
++ if (dbus_message->body_signature &&
++ dbus_message->body_signature[0] == 's') {
++ int str_len;
++ str_len = *(u32 *)cur;
++ cur += 4;
++ dbus_message->arg0 = cur;
++ cur += str_len + 1;
++ }
++
++ if ((cur - message) % 4 != 0)
++ cur += 4 - (cur - message) % 4;
++
++ if (dbus_message->body_signature &&
++ dbus_message->body_signature[0] == 's' &&
++ dbus_message->body_signature[1] == 's') {
++ int str_len;
++ str_len = *(u32 *)cur;
++ cur += 4;
++ dbus_message->arg1 = cur;
++ cur += str_len + 1;
++ }
++
++ if ((cur - message) % 4 != 0)
++ cur += 4 - (cur - message) % 4;
++
++ if (dbus_message->body_signature &&
++ dbus_message->body_signature[0] == 's' &&
++ dbus_message->body_signature[1] == 's' &&
++ dbus_message->body_signature[2] == 's') {
++ int str_len;
++ str_len = *(u32 *)cur;
++ cur += 4;
++ dbus_message->arg2 = cur;
++ cur += str_len + 1;
++ }
++
++ if ((cur - message) % 4 != 0)
++ cur += 4 - (cur - message) % 4;
++
++ if (dbus_message->type == DBUS_MESSAGE_TYPE_SIGNAL &&
++ dbus_message->sender && dbus_message->path &&
++ dbus_message->interface && dbus_message->member &&
++ dbus_message->arg0 &&
++ strcmp(dbus_message->sender, "org.freedesktop.DBus") == 0 &&
++ strcmp(dbus_message->interface, "org.freedesktop.DBus") == 0 &&
++ strcmp(dbus_message->path, "/org/freedesktop/DBus") == 0) {
++ if (strcmp(dbus_message->member, "NameAcquired") == 0)
++ dbus_message->name_acquired = dbus_message->arg0;
++ else if (strcmp(dbus_message->member, "NameLost") == 0)
++ dbus_message->name_lost = dbus_message->arg0;
++ }
++
++ return 0;
++}
+Index: git/net/netfilter/nfdbus/message.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/message.h 2012-10-05 13:53:47.000000000 +0300
+@@ -0,0 +1,71 @@
++/*
++ * message.h Basic D-Bus message parsing
++ *
++ * Copyright (C) 2010 Collabora Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#ifndef DBUS_MESSAGE_H
++#define DBUS_MESSAGE_H
++
++#include <linux/list.h>
++
++#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
++
++/* Types of message */
++
++#define DBUS_MESSAGE_TYPE_INVALID 0
++#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
++#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
++#define DBUS_MESSAGE_TYPE_ERROR 3
++#define DBUS_MESSAGE_TYPE_SIGNAL 4
++#define DBUS_NUM_MESSAGE_TYPES 5
++
++/* No need to implement a feature-complete parser. It only implement what is
++ * needed by the bus. */
++struct dbus_message {
++ char *message;
++ size_t len;
++ size_t new_len;
++
++ /* direct pointers to the fields */
++ int type;
++ char *path;
++ char *interface;
++ char *member;
++ char *destination;
++ char *sender;
++ char *body_signature;
++ int body_length;
++ char *arg0;
++ char *arg1;
++ char *arg2;
++ char *name_acquired;
++ char *name_lost;
++
++ /* How to add the 'sender' field in the headers */
++ int new_header_offset;
++ int len_offset;
++ int padding_end;
++};
++
++int dbus_message_type_from_string(const char *type_str);
++
++int dbus_message_parse(unsigned char *message, size_t len,
++ struct dbus_message *dbus_message);
++
++#endif /* DBUS_MESSAGE_H */
+Index: git/net/netfilter/nfdbus/nfdbus.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/nfdbus.c 2012-10-05 13:55:08.000000000 +0300
+@@ -0,0 +1,456 @@
++/*
++ * nfdbus.c - Netfilter module for AF_BUS/BUS_PROTO_DBUS.
++ */
++
++#define DRIVER_AUTHOR "Alban Crequy"
++#define DRIVER_DESC "Netfilter module for AF_BUS/BUS_PROTO_DBUS."
++
++#include "nfdbus.h"
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/netfilter.h>
++#include <linux/connector.h>
++#include <net/af_bus.h>
++
++#include "message.h"
++#include "matchrule.h"
++
++static struct nf_hook_ops nfho_dbus;
++
++static struct cb_id cn_cmd_id = { CN_IDX_NFDBUS, CN_VAL_NFDBUS };
++
++static unsigned int hash;
++
++/* Scoped by AF_BUS address */
++struct hlist_head matchrules_table[BUS_HASH_SIZE];
++DEFINE_SPINLOCK(matchrules_lock);
++
++static struct bus_match_maker *find_match_maker(struct sockaddr_bus *addr,
++ bool create, bool delete)
++{
++ u64 hash;
++ struct hlist_node *node;
++ struct bus_match_maker *matchmaker;
++ int path_len = strlen(addr->sbus_path);
++
++ hash = csum_partial(addr->sbus_path,
++ strlen(addr->sbus_path), 0);
++ hash ^= addr->sbus_addr.s_addr;
++ hash ^= hash >> 32;
++ hash ^= hash >> 16;
++ hash ^= hash >> 8;
++ hash &= 0xff;
++
++ spin_lock(&matchrules_lock);
++ hlist_for_each_entry(matchmaker, node, &matchrules_table[hash],
++ table_node) {
++ if (addr->sbus_family == matchmaker->addr.sbus_family &&
++ addr->sbus_addr.s_addr == matchmaker->addr.sbus_addr.s_addr &&
++ !memcmp(addr->sbus_path, matchmaker->addr.sbus_path,
++ path_len)) {
++ kref_get(&matchmaker->kref);
++ if (delete)
++ hlist_del(&matchmaker->table_node);
++ spin_unlock(&matchrules_lock);
++ pr_debug("Found matchmaker for hash %llu", hash);
++ return matchmaker;
++ }
++ }
++ spin_unlock(&matchrules_lock);
++
++ if (!create) {
++ pr_debug("Matchmaker for hash %llu not found", hash);
++ return NULL;
++ }
++
++ matchmaker = bus_matchmaker_new(GFP_ATOMIC);
++ matchmaker->addr.sbus_family = addr->sbus_family;
++ matchmaker->addr.sbus_addr.s_addr = addr->sbus_addr.s_addr;
++ memcpy(matchmaker->addr.sbus_path, addr->sbus_path, BUS_PATH_MAX);
++
++ pr_debug("Create new matchmaker for hash %llu\n", hash);
++ spin_lock(&matchrules_lock);
++ hlist_add_head(&matchmaker->table_node, &matchrules_table[hash]);
++ kref_get(&matchmaker->kref);
++ spin_unlock(&matchrules_lock);
++ return matchmaker;
++}
++
++static unsigned int dbus_filter(unsigned int hooknum,
++ struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ int (*okfn)(struct sk_buff *))
++{
++ struct bus_send_context *sendctx;
++ struct bus_match_maker *matchmaker = NULL;
++ struct bus_match_maker *sender = NULL;
++ struct dbus_message msg = {0,};
++ unsigned char *data;
++ size_t len;
++ int err;
++ int ret;
++
++ if (!skb->sk || skb->sk->sk_family != PF_BUS) {
++ WARN(1, "netfilter_dbus received an invalid skb");
++ return NF_DROP;
++ }
++
++ data = skb->data;
++ sendctx = BUSCB(skb).sendctx;
++ if (!sendctx || !sendctx->sender || !sendctx->sender_socket) {
++ WARN(1, "netfilter_dbus received an AF_BUS packet" \
++ " without context. This is a bug. Dropping the"
++ " packet.");
++ return NF_DROP;
++ }
++
++ if (sendctx->sender_socket->sk->sk_protocol != BUS_PROTO_DBUS) {
++ /* This kernel module is for D-Bus. It must not
++ * interfere with other users of AF_BUS. */
++ return NF_ACCEPT;
++ }
++ if (sendctx->recipient)
++ matchmaker = find_match_maker(sendctx->recipient, false, false);
++
++ len = skb_tail_pointer(skb) - data;
++
++ if (sendctx->to_master && sendctx->main_recipient) {
++ pr_debug("AF_BUS packet to the bus master. ACCEPT.\n");
++ ret = NF_ACCEPT;
++ goto out;
++ }
++
++ if (sendctx->main_recipient && !sendctx->bus_master_side) {
++ pr_debug("AF_BUS packet from a peer to a peer (unicast). ACCEPT.\n");
++ ret = NF_ACCEPT;
++ goto out;
++ }
++
++ err = dbus_message_parse(data, len, &msg);
++ if (err) {
++ if (!sendctx->main_recipient) {
++ pr_debug("AF_BUS packet for an eavesdropper or " \
++ "multicast is not parsable. DROP.\n");
++ ret = NF_DROP;
++ goto out;
++ } else if (sendctx->bus_master_side) {
++ pr_debug("AF_BUS packet from bus master is not parsable. ACCEPT.\n");
++ ret = NF_ACCEPT;
++ goto out;
++ } else {
++ pr_debug("AF_BUS packet from peer is not parsable. DROP.\n");
++ ret = NF_DROP;
++ goto out;
++ }
++ }
++
++ if (sendctx->bus_master_side && !sendctx->main_recipient) {
++ pr_debug("AF_BUS packet '%s' from the bus master is for an " \
++ "eavesdropper. DROP.\n",
++ msg.member ? msg.member : "");
++ ret = NF_DROP;
++ goto out;
++ }
++ if (sendctx->bus_master_side) {
++ if (msg.name_acquired) {
++ pr_debug("New name: %s [%p %p].\n",
++ msg.name_acquired, sendctx->sender,
++ sendctx->recipient);
++
++ sender = find_match_maker(sendctx->sender, true, false);
++ bus_matchmaker_add_name(sender, msg.name_acquired,
++ GFP_ATOMIC);
++ }
++ if (msg.name_lost) {
++ pr_debug("Lost name: %s [%p %p].\n",
++ msg.name_lost, sendctx->sender,
++ sendctx->recipient);
++
++ sender = find_match_maker(sendctx->sender, true, false);
++ bus_matchmaker_remove_name(sender, msg.name_acquired);
++ }
++
++ pr_debug("AF_BUS packet '%s' from the bus master. ACCEPT.\n",
++ msg.member ? msg.member : "");
++ ret = NF_ACCEPT;
++ goto out;
++ }
++
++ pr_debug("Multicast AF_BUS packet, %ld bytes, " \
++ "considering recipient %lld...\n", len,
++ sendctx->recipient ? sendctx->recipient->sbus_addr.s_addr : 0);
++
++ pr_debug("Message type %d %s->%s [iface: %s][member: %s][matchmaker=%p]...\n",
++ msg.type,
++ msg.sender ? msg.sender : "",
++ msg.destination ? msg.destination : "",
++ msg.interface ? msg.interface : "",
++ msg.member ? msg.member : "",
++ matchmaker);
++
++ if (!matchmaker) {
++ pr_debug("No match rules for this recipient. DROP.\n");
++ ret = NF_DROP;
++ goto out;
++ }
++
++ sender = find_match_maker(sendctx->sender, true, false);
++ err = bus_matchmaker_filter(matchmaker, sender, sendctx->eavesdropper,
++ &msg);
++ if (err) {
++ pr_debug("Matchmaker: ACCEPT.\n");
++ ret = NF_ACCEPT;
++ goto out;
++ } else {
++ pr_debug("Matchmaker: DROP.\n");
++ ret = NF_DROP;
++ goto out;
++ }
++
++out:
++ if (matchmaker)
++ kref_put(&matchmaker->kref, bus_matchmaker_free);
++ if (sender)
++ kref_put(&sender->kref, bus_matchmaker_free);
++ return ret;
++}
++
++/* Taken from drbd_nl_send_reply() */
++static void nfdbus_nl_send_reply(struct cn_msg *msg, int ret_code)
++{
++ char buffer[sizeof(struct cn_msg)+sizeof(struct nfdbus_nl_cfg_reply)];
++ struct cn_msg *cn_reply = (struct cn_msg *) buffer;
++ struct nfdbus_nl_cfg_reply *reply =
++ (struct nfdbus_nl_cfg_reply *)cn_reply->data;
++ int rr;
++
++ memset(buffer, 0, sizeof(buffer));
++ cn_reply->id = msg->id;
++
++ cn_reply->seq = msg->seq;
++ cn_reply->ack = msg->ack + 1;
++ cn_reply->len = sizeof(struct nfdbus_nl_cfg_reply);
++ cn_reply->flags = 0;
++
++ reply->ret_code = ret_code;
++
++ rr = cn_netlink_send(cn_reply, 0, GFP_NOIO);
++ if (rr && rr != -ESRCH)
++ pr_debug("nfdbus: cn_netlink_send()=%d\n", rr);
++}
++
++/**
++ * nfdbus_check_perm - check if a pid is allowed to update match rules
++ * @sockaddr_bus: the socket address of the bus
++ * @pid: the process id that wants to update the match rules set
++ *
++ * Test if a given process id is allowed to update the match rules set
++ * for this bus. Only the process that owns the bus master listen socket
++ * is allowed to update the match rules set for the bus.
++ */
++static bool nfdbus_check_perm(struct sockaddr_bus *sbusname, pid_t pid)
++{
++ struct net *net = get_net_ns_by_pid(pid);
++ struct sock *s;
++ struct bus_address *addr;
++ struct hlist_node *node;
++ int offset = (sbusname->sbus_path[0] == '\0');
++ int path_len = strnlen(sbusname->sbus_path + offset, BUS_PATH_MAX);
++ int len;
++ if (!net)
++ return false;
++
++ len = path_len + 1 + sizeof(__kernel_sa_family_t) +
++ sizeof(struct bus_addr);
++
++ spin_lock(&bus_address_lock);
++
++ hlist_for_each_entry(addr, node, &bus_address_table[hash],
++ table_node) {
++ s = addr->sock;
++
++ if (s->sk_protocol != BUS_PROTO_DBUS)
++ continue;
++
++ if (!net_eq(sock_net(s), net))
++ continue;
++
++ if (addr->len == len &&
++ addr->name->sbus_family == sbusname->sbus_family &&
++ addr->name->sbus_addr.s_addr == BUS_MASTER_ADDR &&
++ bus_same_bus(addr->name, sbusname) &&
++ pid_nr(s->sk_peer_pid) == pid) {
++ spin_unlock(&bus_address_lock);
++ return true;
++ }
++ }
++
++ spin_unlock(&bus_address_lock);
++
++ return false;
++}
++
++static void cn_cmd_cb(struct cn_msg *msg, struct netlink_skb_parms *nsp)
++{
++ struct nfdbus_nl_cfg_req *nlp = (struct nfdbus_nl_cfg_req *)msg->data;
++ struct cn_msg *cn_reply;
++ struct nfdbus_nl_cfg_reply *reply;
++ int retcode, rr;
++ pid_t pid = task_tgid_vnr(current);
++ int reply_size = sizeof(struct cn_msg)
++ + sizeof(struct nfdbus_nl_cfg_reply);
++
++ pr_debug("nfdbus: %s nsp->pid=%d pid=%d\n", __func__, nsp->pid, pid);
++
++ if (!nfdbus_check_perm(&nlp->addr, pid)) {
++ pr_debug(KERN_ERR "nfdbus: pid=%d is not allowed!\n", pid);
++ retcode = EPERM;
++ goto fail;
++ }
++
++ cn_reply = kzalloc(reply_size, GFP_KERNEL);
++ if (!cn_reply) {
++ retcode = ENOMEM;
++ goto fail;
++ }
++ reply = (struct nfdbus_nl_cfg_reply *) cn_reply->data;
++
++ if (msg->len < sizeof(struct nfdbus_nl_cfg_req)) {
++ reply->ret_code = EINVAL;
++ } else if (nlp->cmd == NFDBUS_CMD_ADDMATCH) {
++ struct bus_match_rule *rule;
++ struct bus_match_maker *matchmaker;
++ reply->ret_code = 0;
++
++ if (msg->len == 0)
++ reply->ret_code = EINVAL;
++
++ rule = bus_match_rule_parse(nlp->data, GFP_ATOMIC);
++ if (rule) {
++ matchmaker = find_match_maker(&nlp->addr, true, false);
++ pr_debug("Add match rule for matchmaker %p\n",
++ matchmaker);
++ bus_matchmaker_add_rule(matchmaker, rule);
++ kref_put(&matchmaker->kref, bus_matchmaker_free);
++ } else {
++ reply->ret_code = EINVAL;
++ }
++ } else if (nlp->cmd == NFDBUS_CMD_REMOVEMATCH) {
++ struct bus_match_rule *rule;
++ struct bus_match_maker *matchmaker;
++
++ rule = bus_match_rule_parse(nlp->data, GFP_ATOMIC);
++ matchmaker = find_match_maker(&nlp->addr, false, false);
++ if (!matchmaker) {
++ reply->ret_code = EINVAL;
++ } else {
++ pr_debug("Remove match rule for matchmaker %p\n",
++ matchmaker);
++ bus_matchmaker_remove_rule_by_value(matchmaker, rule);
++ kref_put(&matchmaker->kref, bus_matchmaker_free);
++ reply->ret_code = 0;
++ }
++ bus_match_rule_free(rule);
++
++ } else if (nlp->cmd == NFDBUS_CMD_REMOVEALLMATCH) {
++ struct bus_match_maker *matchmaker;
++
++ matchmaker = find_match_maker(&nlp->addr, false, true);
++ if (!matchmaker) {
++ reply->ret_code = EINVAL;
++ } else {
++ pr_debug("Remove matchmaker %p\n", matchmaker);
++ kref_put(&matchmaker->kref, bus_matchmaker_free);
++ kref_put(&matchmaker->kref, bus_matchmaker_free);
++ reply->ret_code = 0;
++ }
++
++ } else {
++ reply->ret_code = EINVAL;
++ }
++
++ cn_reply->id = msg->id;
++ cn_reply->seq = msg->seq;
++ cn_reply->ack = msg->ack + 1;
++ cn_reply->len = sizeof(struct nfdbus_nl_cfg_reply);
++ cn_reply->flags = 0;
++
++ rr = cn_netlink_reply(cn_reply, nsp->pid, GFP_KERNEL);
++ if (rr && rr != -ESRCH)
++ pr_debug("nfdbus: cn_netlink_send()=%d\n", rr);
++ pr_debug("nfdbus: cn_netlink_reply(pid=%d)=%d\n", nsp->pid, rr);
++
++ kfree(cn_reply);
++ return;
++fail:
++ nfdbus_nl_send_reply(msg, retcode);
++}
++
++static int __init nfdbus_init(void)
++{
++ int err;
++ struct bus_addr master_addr;
++
++ master_addr.s_addr = BUS_MASTER_ADDR;
++ hash = bus_compute_hash(master_addr);
++
++ pr_debug("Loading netfilter_dbus\n");
++
++ /* Install D-Bus netfilter hook */
++ nfho_dbus.hook = dbus_filter;
++ nfho_dbus.hooknum = NF_BUS_SENDING;
++ nfho_dbus.pf = NFPROTO_BUS; /* Do not use PF_BUS, you fool! */
++ nfho_dbus.priority = 0;
++ nfho_dbus.owner = THIS_MODULE;
++ err = nf_register_hook(&nfho_dbus);
++ if (err)
++ return err;
++ pr_debug("Netfilter hook for D-Bus: installed.\n");
++
++ /* Install connector hook */
++ err = cn_add_callback(&cn_cmd_id, "nfdbus", cn_cmd_cb);
++ if (err)
++ goto err_cn_cmd_out;
++ pr_debug("Connector hook: installed.\n");
++
++ return 0;
++
++err_cn_cmd_out:
++ nf_unregister_hook(&nfho_dbus);
++
++ return err;
++}
++
++static void __exit nfdbus_cleanup(void)
++{
++ int i;
++ struct hlist_node *node, *tmp;
++ struct bus_match_maker *matchmaker;
++ nf_unregister_hook(&nfho_dbus);
++
++ cn_del_callback(&cn_cmd_id);
++
++ spin_lock(&matchrules_lock);
++ for (i = 0; i < BUS_HASH_SIZE; i++) {
++ hlist_for_each_entry_safe(matchmaker, node, tmp,
++ &matchrules_table[i], table_node) {
++ hlist_del(&matchmaker->table_node);
++ kref_put(&matchmaker->kref, bus_matchmaker_free);
++ }
++ }
++ spin_unlock(&matchrules_lock);
++
++ pr_debug("Unloading netfilter_dbus\n");
++}
++
++module_init(nfdbus_init);
++module_exit(nfdbus_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_ALIAS_NET_PF_PROTO(PF_BUS, BUS_PROTO_DBUS);
+Index: git/net/netfilter/nfdbus/nfdbus.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ git/net/netfilter/nfdbus/nfdbus.h 2012-10-05 13:56:39.000000000 +0300
+@@ -0,0 +1,44 @@
++/*
++ * nfdbus.h Netfilter module for AF_BUS/BUS_PROTO_DBUS.
++ *
++ * Copyright (C) 2012 Collabora Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#ifndef NETFILTER_DBUS_H
++#define NETFILTER_DBUS_H
++
++#include <linux/types.h>
++#include <linux/bus.h>
++
++#define NFDBUS_CMD_ADDMATCH 0x01
++#define NFDBUS_CMD_REMOVEMATCH 0x02
++#define NFDBUS_CMD_REMOVEALLMATCH 0x03
++
++struct nfdbus_nl_cfg_req {
++ __u32 cmd;
++ __u32 len;
++ struct sockaddr_bus addr;
++ __u64 pad;
++ unsigned char data[0];
++};
++
++struct nfdbus_nl_cfg_reply {
++ __u32 ret_code;
++};
++
++#endif /* NETFILTER_DBUS_H */
+Index: git/security/capability.c
+===================================================================
+--- git.orig/security/capability.c 2012-10-05 12:14:13.000000000 +0300
++++ git/security/capability.c 2012-10-05 13:58:36.000000000 +0300
+@@ -563,6 +563,12 @@
+ return 0;
+ }
+
++static int cap_bus_connect(struct sock *sock, struct sock *other,
++ struct sock *newsk)
++{
++return 0;
++}
++
+ static int cap_socket_create(int family, int type, int protocol, int kern)
+ {
+ return 0;
+@@ -1015,6 +1021,7 @@
+ #ifdef CONFIG_SECURITY_NETWORK
+ set_to_cap_if_null(ops, unix_stream_connect);
+ set_to_cap_if_null(ops, unix_may_send);
++ set_to_cap_if_null(ops, bus_connect);
+ set_to_cap_if_null(ops, socket_create);
+ set_to_cap_if_null(ops, socket_post_create);
+ set_to_cap_if_null(ops, socket_bind);
+Index: git/security/security.c
+===================================================================
+--- git.orig/security/security.c 2012-10-05 12:14:13.000000000 +0300
++++ git/security/security.c 2012-10-05 14:00:06.000000000 +0300
+@@ -1018,6 +1018,12 @@
+ }
+ EXPORT_SYMBOL(security_unix_may_send);
+
++int security_bus_connect(struct sock *sock, struct sock *other, struct sock *newsk)
++{
++ return security_ops->bus_connect(sock, other, newsk);
++}
++EXPORT_SYMBOL(security_bus_connect);
++
+ int security_socket_create(int family, int type, int protocol, int kern)
+ {
+ return security_ops->socket_create(family, type, protocol, kern);
+Index: git/security/selinux/hooks.c
+===================================================================
+--- git.orig/security/selinux/hooks.c 2012-10-05 12:14:13.000000000 +0300
++++ git/security/selinux/hooks.c 2012-10-05 14:04:06.000000000 +0300
+@@ -4102,6 +4102,38 @@
+ &ad);
+ }
+
++static int selinux_socket_bus_connect(struct sock *sock, struct sock *other, struct sock *newsk)
++{
++ struct sk_security_struct *sksec_sock = sock->sk_security;
++ struct sk_security_struct *sksec_other = other->sk_security;
++ struct sk_security_struct *sksec_new = newsk->sk_security;
++ struct common_audit_data ad;
++ struct lsm_network_audit net = {0,};
++ int err;
++
++ ad.type = LSM_AUDIT_DATA_NET;
++ ad.u.net = &net;
++ ad.u.net->sk = other;
++
++ err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
++ sksec_other->sclass,
++ UNIX_STREAM_SOCKET__CONNECTTO, &ad);
++ if (err)
++ return err;
++
++ /* server child socket */
++ sksec_new->peer_sid = sksec_sock->sid;
++ err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
++ &sksec_new->sid);
++ if (err)
++ return err;
++
++ /* connecting socket */
++ sksec_sock->peer_sid = sksec_new->sid;
++
++ return 0;
++}
++
+ static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
+ u32 peer_sid,
+ struct common_audit_data *ad)
+@@ -5656,6 +5688,7 @@
+
+ .unix_stream_connect = selinux_socket_unix_stream_connect,
+ .unix_may_send = selinux_socket_unix_may_send,
++ .bus_connect = selinux_socket_bus_connect,
+
+ .socket_create = selinux_socket_create,
+ .socket_post_create = selinux_socket_post_create,
diff --git a/recipes-kernel/linux/linux-omap4_3.4.0.bb b/recipes-kernel/linux/linux-omap4_3.4.0.bb
new file mode 100644
index 0000000..5228847
--- /dev/null
+++ b/recipes-kernel/linux/linux-omap4_3.4.0.bb
@@ -0,0 +1,21 @@
+COMPATIBLE_MACHINE = "pandaboard"
+
+require linux.inc
+
+# The main PR is now using MACHINE_KERNEL_PR, for omap4 see conf/machine/include/omap4.inc
+MACHINE_KERNEL_PR_append = "a"
+
+CORTEXA8FIXUP = "no"
+
+# Linaro workign kernel 3.4.11+
+#SRCREV = "a5c60c099296fcfc0c8fa8085c40883971486512"
+SRCREV = "67c858c2ac6bf304f700246501d574861ea4b0b3"
+
+
+
+SRC_URI = "git://git.linaro.org/landing-teams/working/ti/kernel.git;protocol=git \
+ file://kernel_af_bus.patch \
+ file://defconfig \
+ "
+
+S = "${WORKDIR}/git"
diff --git a/recipes-kernel/linux/linux.inc b/recipes-kernel/linux/linux.inc
new file mode 100644
index 0000000..ac51dae
--- /dev/null
+++ b/recipes-kernel/linux/linux.inc
@@ -0,0 +1,277 @@
+DESCRIPTION = "Linux Kernel"
+SECTION = "kernel"
+LICENSE = "GPLv2"
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7"
+
+inherit kernel siteinfo
+
+# Enable OABI compat for people stuck with obsolete userspace
+ARM_KEEP_OABI ?= "1"
+
+# Quirk for udev greater or equal 141
+UDEV_GE_141 ?= "0"
+
+# Specify the commandline for your device
+
+# Boot from mmc
+CMDLINE_at91sam9263ek = "mem=64M console=ttyS0,115200 root=/dev/mmcblk0p1 rootfstype=ext2 rootdelay=5"
+# Boot from nfs
+#CMDLINE_at91sam9263ek = "mem=64M console=ttyS0,115200 root=301 root=/dev/nfs nfsroot=172.20.3.1:/data/at91 ip=172.20.0.5:::255.255.0.0"
+
+# Set the verbosity of kernel messages during runtime
+# You can define CMDLINE_DEBUG in your local.conf or distro.conf to override this behaviour
+CMDLINE_DEBUG ?= '${@base_conditional("DISTRO_TYPE", "release", "quiet", "debug", d)}'
+CMDLINE_append = " ${CMDLINE_DEBUG} "
+
+# Kernel bootlogo is distro-specific (default is OE logo).
+# Logo resolution (qvga, vga, ...) is machine-specific.
+LOGO_SIZE ?= "."
+
+# Support for binary device tree generation
+
+FILES_kernel-devicetree = "/boot/devicetree*"
+
+KERNEL_DEVICETREE_boc01 = "${WORKDIR}/boc01.dts"
+KERNEL_DEVICETREE_calamari = "arch/${ARCH}/boot/dts/mpc8536ds.dts"
+KERNEL_DEVICETREE_canyonlands = "arch/${ARCH}/boot/dts/canyonlands.dts"
+KERNEL_DEVICETREE_kilauea = "arch/${ARCH}/boot/dts/kilauea.dts"
+KERNEL_DEVICETREE_lite5200 = "arch/${ARCH}/boot/dts/lite5200.dts"
+KERNEL_DEVICETREE_lsppchd = "arch/${ARCH}/boot/dts/kuroboxHD.dts"
+KERNEL_DEVICETREE_lsppchg = "arch/${ARCH}/boot/dts/kuroboxHG.dts"
+KERNEL_DEVICETREE_mpc8313e-rdb = "arch/${ARCH}/boot/dts/mpc8313erdb.dts"
+KERNEL_DEVICETREE_mpc8315e-rdb = "arch/${ARCH}/boot/dts/mpc8315erdb.dts"
+KERNEL_DEVICETREE_mpc8323e-rdb = "arch/${ARCH}/boot/dts/mpc832x_rdb.dts"
+KERNEL_DEVICETREE_mpc8544ds = "arch/${ARCH}/boot/dts/mpc8544ds.dts"
+KERNEL_DEVICETREE_mpc8641-hpcn = "arch/${ARCH}/boot/dts/mpc8641_hpcn.dts"
+KERNEL_DEVICETREE_p1020rdb = "arch/${ARCH}/boot/dts/p1020rdb.dts"
+KERNEL_DEVICETREE_p2020ds = "arch/${ARCH}/boot/dts/p2020ds.dts"
+KERNEL_DEVICETREE_sequoia = "arch/${ARCH}/boot/dts/sequoia.dts"
+KERNEL_DEVICETREE_tqm8540 = "arch/${ARCH}/boot/dts/tqm8540.dts"
+KERNEL_DEVICETREE_xilinx-ml507 = "arch/${ARCH}/boot/dts/virtex440-ml507.dts"
+
+KERNEL_DEVICETREE_FLAGS = "-R 8 -S 0x3000"
+
+CORTEXA8FIXUP ?= "yes"
+
+python __anonymous () {
+
+ import bb
+
+ devicetree = bb.data.getVar('KERNEL_DEVICETREE', d, 1) or ''
+ if devicetree:
+ depends = bb.data.getVar("DEPENDS", d, 1)
+ bb.data.setVar("DEPENDS", "%s dtc-native" % depends, d)
+ packages = bb.data.getVar("PACKAGES", d, 1)
+ bb.data.setVar("PACKAGES", "%s kernel-devicetree" % packages, d)
+}
+
+do_configure_prepend() {
+
+ # Rename getline in ./scripts/unifdef.c
+ # Kernels up to 2.6.29 are currently failing to build unifdef.c,
+ # clashing with exposed getline() from <stdio.h>
+ # see https://patchwork.kernel.org/patch/11166/
+ # committed in 2.6.29 (commit d15bd1067b1fcb2b7250d22bc0c7c7fea0b759f7)
+
+ sed -i -e 's/getline/parseline/g' ${S}/scripts/unifdef.c
+
+
+ echo "" > ${S}/.config
+
+ #
+ # logo support, if you supply logo_linux_clut224.ppm in SRC_URI, then it's going to be used
+ #
+ if [ -e ${WORKDIR}/${LOGO_SIZE}/logo_linux_clut224.ppm ]; then
+ install -m 0644 ${WORKDIR}/${LOGO_SIZE}/logo_linux_clut224.ppm drivers/video/logo/logo_linux_clut224.ppm
+ echo "CONFIG_LOGO=y" >> ${S}/.config
+ echo "CONFIG_LOGO_LINUX_CLUT224=y" >> ${S}/.config
+ fi
+
+ #
+ # oabi / eabi support
+ #
+ if [ "${TARGET_OS}" = "linux-gnueabi" -o "${TARGET_OS}" = "linux-uclibceabi" ]; then
+ echo "CONFIG_AEABI=y" >> ${S}/.config
+ if [ "${ARM_KEEP_OABI}" = "1" ] ; then
+ echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config
+ else
+ echo "# CONFIG_OABI_COMPAT is not set" >> ${S}/.config
+ fi
+ else
+ echo "# CONFIG_AEABI is not set" >> ${S}/.config
+ echo "# CONFIG_OABI_COMPAT is not set" >> ${S}/.config
+ fi
+
+ # When enabling thumb for userspace we also need thumb support in the kernel
+ if [ "${ARM_INSTRUCTION_SET}" = "thumb" ] ; then
+ sed -i -e /CONFIG_ARM_THUMB/d ${WORKDIR}/defconfig
+ echo "CONFIG_ARM_THUMB=y" >> ${S}/.config
+ fi
+
+ # Enable thumb2 fixup for specific issue in angstrom toolchains when used on A8 r1p[012] silicon
+ if [ "${CORTEXA8FIXUP}" = "yes" ] ; then
+ sed -i -e /CONFIG_ARM_ERRATA_430973/d ${WORKDIR}/defconfig
+ echo "CONFIG_ARM_ERRATA_430973=y" >> ${S}/.config
+ fi
+
+ #
+ # endian support
+ #
+ if [ "${SITEINFO_ENDIANNESS}" = "be" ]; then
+ echo "CONFIG_CPU_BIG_ENDIAN=y" >> ${S}/.config
+ fi
+
+ echo "CONFIG_CMDLINE=\"${CMDLINE}\"" >> ${S}/.config
+
+ sed -e '/CONFIG_AEABI/d' \
+ -e '/CONFIG_OABI_COMPAT=/d' \
+ -e '/CONFIG_CMDLINE=/d' \
+ -e '/CONFIG_CPU_BIG_ENDIAN/d' \
+ -e '/CONFIG_LOGO=/d' \
+ -e '/CONFIG_LOGO_LINUX_CLUT224=/d' \
+ -e '/CONFIG_LOCALVERSION/d' \
+ -e '/CONFIG_LOCALVERSION_AUTO/d' \
+ < '${WORKDIR}/defconfig' >>'${S}/.config'
+
+ echo 'CONFIG_LOCALVERSION=""' >>${S}/.config
+ echo '# CONFIG_LOCALVERSION_AUTO is not set' >>${S}/.config
+
+ #
+ # Udev quirks
+ #
+
+ # Newer versions of udev mandate that sysfs doesn't have deprecated entries
+ if [ "${UDEV_GE_141}" = "1" ] ; then
+ sed -e /CONFIG_SYSFS_DEPRECATED/d \
+ -e /CONFIG_SYSFS_DEPRECATED_V2/d \
+ -e /CONFIG_HOTPLUG/d \
+ -e /CONFIG_UEVENT_HELPER_PATH/d \
+ -e /CONFIG_UNIX/d \
+ -e /CONFIG_SYSFS/d \
+ -e /CONFIG_PROC_FS/d \
+ -e /CONFIG_TMPFS/d \
+ -e /CONFIG_INOTIFY_USER/d \
+ -e /CONFIG_SIGNALFD/d \
+ -e /CONFIG_TMPFS_POSIX_ACL/d \
+ -e /CONFIG_BLK_DEV_BSG/d \
+ -i '${S}/.config'
+
+ echo '# CONFIG_SYSFS_DEPRECATED is not set' >> ${S}/.config
+ echo '# CONFIG_SYSFS_DEPRECATED_V2 is not set' >> ${S}/.config
+ echo 'CONFIG_HOTPLUG=y' >> ${S}/.config
+ echo 'CONFIG_UEVENT_HELPER_PATH=""' >> ${S}/.config
+ echo 'CONFIG_UNIX=y' >> ${S}/.config
+ echo 'CONFIG_SYSFS=y' >> ${S}/.config
+ echo 'CONFIG_PROC_FS=y' >> ${S}/.config
+ echo 'CONFIG_TMPFS=y' >> ${S}/.config
+ echo 'CONFIG_INOTIFY_USER=y' >> ${S}/.config
+ echo 'CONFIG_SIGNALFD=y' >> ${S}/.config
+ echo 'CONFIG_TMPFS_POSIX_ACL=y' >> ${S}/.config
+ echo 'CONFIG_BLK_DEV_BSG=y' >> ${S}/.config
+ echo 'CONFIG_DEVTMPFS=y' >> ${S}/.config
+ echo 'CONFIG_DEVTMPFS_MOUNT=y' >> ${S}/.config
+ fi
+
+ # Newer inits like systemd need cgroup support
+ if [ "${KERNEL_ENABLE_CGROUPS}" = "1" ] ; then
+ sed -e /CONFIG_CGROUP_SCHED/d \
+ -e /CONFIG_CGROUPS/d \
+ -i '${S}/.config'
+
+ echo 'CONFIG_CGROUP_SCHED=y' >> ${S}/.config
+ echo 'CONFIG_CGROUPS=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_NS=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_FREEZER=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_DEVICE=y' >> ${S}/.config
+ echo 'CONFIG_CPUSETS=y' >> ${S}/.config
+ echo 'CONFIG_PROC_PID_CPUSET=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_CPUACCT=y' >> ${S}/.config
+ echo 'CONFIG_RESOURCE_COUNTERS=y' >> ${S}/.config
+ fi
+
+ #
+ # root-over-nfs-over-usb-eth support. Limited, but should cover some cases.
+ # Enable this by setting a proper CMDLINE_NFSROOT_USB.
+ #
+ if [ ! -z "${CMDLINE_NFSROOT_USB}" ]; then
+ oenote "Configuring the kernel for root-over-nfs-over-usb-eth with CMDLINE ${CMDLINE_NFSROOT_USB}"
+ sed -e '/CONFIG_INET/d' \
+ -e '/CONFIG_IP_PNP=/d' \
+ -e '/CONFIG_USB_GADGET=/d' \
+ -e '/CONFIG_USB_GADGET_SELECTED=/d' \
+ -e '/CONFIG_USB_ETH=/d' \
+ -e '/CONFIG_NFS_FS=/d' \
+ -e '/CONFIG_ROOT_NFS=/d' \
+ -e '/CONFIG_CMDLINE=/d' \
+ -i ${S}/.config
+ echo "CONFIG_INET=y" >> ${S}/.config
+ echo "CONFIG_IP_PNP=y" >> ${S}/.config
+ echo "CONFIG_USB_GADGET=y" >> ${S}/.config
+ echo "CONFIG_USB_GADGET_SELECTED=y" >> ${S}/.config
+ echo "CONFIG_USB_ETH=y" >> ${S}/.config
+ echo "CONFIG_NFS_FS=y" >> ${S}/.config
+ echo "CONFIG_ROOT_NFS=y" >> ${S}/.config
+ echo "CONFIG_CMDLINE=\"${CMDLINE_NFSROOT_USB}\"" >> ${S}/.config
+ fi
+ yes '' | oe_runmake oldconfig
+}
+
+do_configure_append() {
+ if test -e scripts/Makefile.fwinst ; then
+ sed -i -e "s:-m0644:-m 0644:g" scripts/Makefile.fwinst
+ fi
+}
+
+# bitbake.conf only prepends PARALLEL make in tasks called do_compile, which isn't the case for compile_modules
+# So explicitly enable it for that in here
+EXTRA_OEMAKE = "${PARALLEL_MAKE} "
+
+do_install_append() {
+ oe_runmake headers_install INSTALL_HDR_PATH=${D}${exec_prefix}/src/linux-${KERNEL_VERSION} ARCH=$ARCH
+}
+
+PACKAGES =+ "kernel-headers"
+FILES_kernel-headers = "${exec_prefix}/src/linux*"
+
+do_devicetree_image() {
+ if test -n "${KERNEL_DEVICETREE}" ; then
+ dtc -I dts -O dtb ${KERNEL_DEVICETREE_FLAGS} -o devicetree ${KERNEL_DEVICETREE}
+ install -d ${D}/boot
+ install -m 0644 devicetree ${D}/boot/devicetree-${KERNEL_VERSION}
+ install -d ${DEPLOY_DIR_IMAGE}
+ install -m 0644 devicetree ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_BASE_NAME}.dtb
+ package_stagefile_shell ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_BASE_NAME}.dtb
+ cd ${DEPLOY_DIR_IMAGE}
+ rm -f ${KERNEL_IMAGE_SYMLINK_NAME}.dtb
+ ln -sf ${KERNEL_IMAGE_BASE_NAME}.dtb ${KERNEL_IMAGE_SYMLINK_NAME}.dtb
+ package_stagefile_shell ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_SYMLINK_NAME}.dtb
+ fi
+}
+
+addtask devicetree_image after do_install before do_package do_deploy
+
+pkg_postinst_kernel-devicetree () {
+ cd /${KERNEL_IMAGEDEST}; update-alternatives --install /${KERNEL_IMAGEDEST}/devicetree devicetree devicetree-${KERNEL_VERSION} ${KERNEL_PRIORITY} || true
+}
+
+pkg_postrm_kernel-devicetree () {
+ cd /${KERNEL_IMAGEDEST}; update-alternatives --remove devicetree devicetree-${KERNEL_VERSION} || true
+}
+
+# Automatically depend on lzop-native if CONFIG_KERNEL_LZO is enabled
+python () {
+ try:
+ defconfig = bb.fetch2.localpath('file://defconfig', d)
+ except bb.fetch2.FetchError:
+ return
+
+ try:
+ configfile = open(defconfig)
+ except IOError:
+ return
+
+ if 'CONFIG_KERNEL_LZO=y\n' in configfile.readlines():
+ depends = d.getVar('DEPENDS', False)
+ d.setVar('DEPENDS', depends + ' lzop-native')
+}