Merge branch 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML changes from Richard Weinberger:
 "Mostly bug fixes and cleanups"

* 'for-linus-3.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (35 commits)
  um: Update defconfig
  um: Switch to large mcmodel on x86_64
  MTD: Relax dependencies
  um: Wire CONFIG_GENERIC_IO up
  um: Serve io_remap_pfn_range()
  Introduce CONFIG_GENERIC_IO
  um: allow SUBARCH=x86
  um: most of the SUBARCH uses can be killed
  um: deadlock in line_write_interrupt()
  um: don't bother trying to rebuild CHECKFLAGS for USER_OBJS
  um: use the right ifdef around exports in user_syms.c
  um: a bunch of headers can be killed by using generic-y
  um: ptrace-generic.h doesn't need user.h
  um: kill HOST_TASK_PID
  um: remove pointless include of asm/fixmap.h from asm/pgtable.h
  um: asm-offsets.h might as well come from underlying arch...
  um: merge processor_{32,64}.h a bit...
  um: switch close_chan() to struct line
  um: race fix: initialize delayed_work *before* registering IRQ
  um: line->have_irq is never checked...
  ...
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index b37ae70..20a49ba 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -9,6 +9,7 @@
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_SHOW
 	select GENERIC_CPU_DEVICES
+	select GENERIC_IO
 
 config MMU
 	bool
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 28688e6..55c0661 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -28,6 +28,7 @@
 endif
 ifeq ($(SUBARCH),x86_64)
         HEADER_ARCH := x86
+	KBUILD_CFLAGS += -mcmodel=large
 endif
 
 HOST_DIR := arch/$(HEADER_ARCH)
@@ -50,7 +51,7 @@
 #
 # These apply to USER_CFLAGS to.
 
-KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \
 	$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap	\
 	-Din6addr_loopback=kernel_in6addr_loopback \
 	-Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr
@@ -99,7 +100,7 @@
 
 archheaders:
 	$(Q)$(MAKE) -C '$(srctree)' KBUILD_SRC= \
-		ARCH=$(SUBARCH) O='$(objtree)' archheaders
+		ARCH=$(HEADER_ARCH) O='$(objtree)' archheaders
 
 archprepare: include/generated/user_constants.h
 
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 761f5e1..fdc97e2 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,10 +1,8 @@
 #
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24
-# Thu Feb  7 11:48:55 2008
+# Automatically generated file; DO NOT EDIT.
+# User Mode Linux/i386 3.3.0 Kernel Configuration
 #
 CONFIG_DEFCONFIG_LIST="arch/$ARCH/defconfig"
-CONFIG_GENERIC_HARDIRQS=y
 CONFIG_UML=y
 CONFIG_MMU=y
 CONFIG_NO_IOMEM=y
@@ -20,12 +18,10 @@
 #
 # UML-specific options
 #
-# CONFIG_STATIC_LINK is not set
 
 #
 # Host processor type and features
 #
-# CONFIG_M386 is not set
 # CONFIG_M486 is not set
 # CONFIG_M586 is not set
 # CONFIG_M586TSC is not set
@@ -41,17 +37,17 @@
 # CONFIG_MCRUSOE is not set
 # CONFIG_MEFFICEON is not set
 # CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
 # CONFIG_MWINCHIP3D is not set
+# CONFIG_MELAN is not set
 # CONFIG_MGEODEGX1 is not set
 # CONFIG_MGEODE_LX is not set
 # CONFIG_MCYRIXIII is not set
 # CONFIG_MVIAC3_2 is not set
 # CONFIG_MVIAC7 is not set
-# CONFIG_MPSC is not set
 # CONFIG_MCORE2 is not set
-# CONFIG_GENERIC_CPU is not set
+# CONFIG_MATOM is not set
 # CONFIG_X86_GENERIC is not set
+CONFIG_X86_INTERNODE_CACHE_SHIFT=5
 CONFIG_X86_CMPXCHG=y
 CONFIG_X86_L1_CACHE_SHIFT=5
 CONFIG_X86_XADD=y
@@ -60,47 +56,59 @@
 CONFIG_X86_INVLPG=y
 CONFIG_X86_BSWAP=y
 CONFIG_X86_POPAD_OK=y
-CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
 CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
 CONFIG_X86_CMOV=y
-CONFIG_X86_MINIMUM_CPU_FAMILY=4
-CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CPU_SUP_UMC_32=y
 CONFIG_UML_X86=y
-CONFIG_X86_32=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_64BIT is not set
-CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_X86_32=y
+# CONFIG_X86_64 is not set
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_3_LEVEL_PGTABLES is not set
 CONFIG_ARCH_HAS_SC_SIGNALS=y
 CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
 CONFIG_GENERIC_HWEIGHT=y
+# CONFIG_STATIC_LINK is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_LD_SCRIPT_DYN=y
 CONFIG_BINFMT_ELF=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HOSTFS=y
 # CONFIG_HPPFS is not set
 CONFIG_MCONSOLE=y
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_HIGHMEM is not set
 CONFIG_KERNEL_STACK_ORDER=0
+# CONFIG_MMAPPER is not set
+CONFIG_NO_DMA=y
 
 #
 # General setup
@@ -108,99 +116,169 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=128
+CONFIG_CROSS_COMPILE=""
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_DEFAULT_HOSTNAME="(none)"
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_FHANDLE is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_SHOW=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_TREE_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_MEM_RES_CTLR=y
+CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
+# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set
+# CONFIG_CGROUP_MEM_RES_CTLR_KMEM is not set
+CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_BLK_CGROUP=m
+# CONFIG_DEBUG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+CONFIG_MM_OWNER=y
 CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EXPERT is not set
 CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+
+#
+# Kernel Performance Events And Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-# CONFIG_HAVE_OPROFILE is not set
-# CONFIG_HAVE_KPROBES is not set
-CONFIG_PROC_PAGE_MONITOR=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
+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 is not set
+CONFIG_MSDOS_PARTITION=y
 
 #
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=m
+# CONFIG_CFQ_GROUP_IOSCHED is not set
+CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
-CONFIG_BLK_DEV=y
-CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
-CONFIG_BLK_DEV_COW_COMMON=y
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_ATA_OVER_ETH is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
 
 #
-# Character Devices
+# UML Character Devices
 #
 CONFIG_STDERR_CONSOLE=y
 CONFIG_STDIO_CONSOLE=y
@@ -214,40 +292,191 @@
 CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
 CONFIG_CON_CHAN="xterm"
 CONFIG_SSL_CHAN="pts"
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-# CONFIG_RAW_DRIVER is not set
-CONFIG_LEGACY_PTY_COUNT=32
-# CONFIG_WATCHDOG is not set
 CONFIG_UML_SOUND=m
 CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_HOSTAUDIO=m
-# CONFIG_HW_RANDOM is not set
-CONFIG_UML_RANDOM=y
-# CONFIG_MMAPPER 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 is not set
+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=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_UBD=y
+# CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 
 #
-# Networking
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
 #
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+
+#
+# Altera FPGA firmware download module
+#
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+CONFIG_DUMMY=m
+# CONFIG_EQUALIZER is not set
+# CONFIG_MII is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_CHELSIO=y
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_PHYLIB is not set
+CONFIG_PPP=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_SLIP=m
+CONFIG_SLHC=m
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_WLAN=y
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+
+#
+# Character devices
+#
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=32
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_UML_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_NSC_GPIO is not set
+# CONFIG_RAW_DRIVER 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_POWER_SUPPLY is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_REGULATOR is not set
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_BALLOON is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_IOMMU_SUPPORT=y
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
 CONFIG_NET=y
 
 #
 # Networking options
 #
 CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=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
@@ -257,10 +486,9 @@
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
 # CONFIG_IP_PNP is not set
 # CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
 # CONFIG_ARPD is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
@@ -274,20 +502,23 @@
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL 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
@@ -297,7 +528,14 @@
 # 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_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_NETPRIO_CGROUP is not set
+CONFIG_BQL=y
 
 #
 # Network testing
@@ -308,16 +546,19 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
 
 #
-# Wireless
+# CFG80211 needs to be enabled for MAC80211
 #
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
 
 #
 # UML Network Devices
@@ -331,76 +572,51 @@
 CONFIG_UML_NET_MCAST=y
 # CONFIG_UML_NET_PCAP is not set
 CONFIG_UML_NET_SLIRP=y
-CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_VETH is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_WAN is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPP_MPPE is not set
-# CONFIG_PPPOE is not set
-# CONFIG_PPPOL2TP is not set
-CONFIG_SLIP=m
-# CONFIG_SLIP_COMPRESSED is not set
-CONFIG_SLHC=m
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_CONNECTOR is not set
 
 #
 # 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_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT23=y
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
 CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
 CONFIG_QUOTA=y
 # CONFIG_QUOTA_NETLINK_INTERFACE is not set
 CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
 CONFIG_QUOTACTL=y
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=m
@@ -421,15 +637,14 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -437,26 +652,26 @@
 # 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_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 is not set
 # CONFIG_NFSD is not set
-# CONFIG_SMB_FS 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
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
@@ -497,119 +712,191 @@
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-# CONFIG_DLM is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
 # CONFIG_SECURITY is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=m
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_CBC is not set
-# CONFIG_CRYPTO_PCBC is not set
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_XTS is not set
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_TWOFISH_586 is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
 # CONFIG_CRYPTO_AES_586 is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_SEED is not set
 # CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SALSA20_586 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
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+
+#
+# Compression
+#
 # CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
-CONFIG_BITREVERSE=m
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_IO=y
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=m
+CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
-CONFIG_PLIST=y
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
-# CONFIG_SCSI_NETLINK is not set
-# CONFIG_MD is not set
-# CONFIG_INPUT is not set
+# CONFIG_CRC8 is not set
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_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_SPINLOCK_SLEEP is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 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=y
 # 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_FORCED_INLINING=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
 # CONFIG_SAMPLES is not set
+# CONFIG_TEST_KSTRTOX is not set
 # CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_EARLY_PRINTK=y
diff --git a/arch/um/drivers/chan.h b/arch/um/drivers/chan.h
index 8df0fd9..02b5a76 100644
--- a/arch/um/drivers/chan.h
+++ b/arch/um/drivers/chan.h
@@ -27,24 +27,24 @@
 	void *data;
 };
 
-extern void chan_interrupt(struct list_head *chans, struct delayed_work *task,
+extern void chan_interrupt(struct line *line,
 			   struct tty_struct *tty, int irq);
 extern int parse_chan_pair(char *str, struct line *line, int device,
 			   const struct chan_opts *opts, char **error_out);
-extern int write_chan(struct list_head *chans, const char *buf, int len,
+extern int write_chan(struct chan *chan, const char *buf, int len,
 			     int write_irq);
-extern int console_write_chan(struct list_head *chans, const char *buf, 
+extern int console_write_chan(struct chan *chan, const char *buf, 
 			      int len);
 extern int console_open_chan(struct line *line, struct console *co);
-extern void deactivate_chan(struct list_head *chans, int irq);
-extern void reactivate_chan(struct list_head *chans, int irq);
-extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
+extern void deactivate_chan(struct chan *chan, int irq);
+extern void reactivate_chan(struct chan *chan, int irq);
+extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty);
 extern int enable_chan(struct line *line);
-extern void close_chan(struct list_head *chans, int delay_free_irq);
-extern int chan_window_size(struct list_head *chans, 
+extern void close_chan(struct line *line);
+extern int chan_window_size(struct line *line, 
 			     unsigned short *rows_out, 
 			     unsigned short *cols_out);
-extern int chan_config_string(struct list_head *chans, char *str, int size,
+extern int chan_config_string(struct line *line, char *str, int size,
 			      char **error_out);
 
 #endif
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 420e2c8..ca4c7eb 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -140,18 +140,18 @@
 	return err;
 }
 
-void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
+void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
 {
-	struct list_head *ele;
-	struct chan *chan;
+	if (chan && chan->primary && chan->ops->winch)
+		register_winch(chan->fd, tty);
+}
 
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-		if (chan->primary && chan->output && chan->ops->winch) {
-			register_winch(chan->fd, tty);
-			return;
-		}
-	}
+static void line_timer_cb(struct work_struct *work)
+{
+	struct line *line = container_of(work, struct line, task.work);
+
+	if (!line->throttled)
+		chan_interrupt(line, line->tty, line->driver->read_irq);
 }
 
 int enable_chan(struct line *line)
@@ -160,6 +160,8 @@
 	struct chan *chan;
 	int err;
 
+	INIT_DELAYED_WORK(&line->task, line_timer_cb);
+
 	list_for_each(ele, &line->chan_list) {
 		chan = list_entry(ele, struct chan, list);
 		err = open_one_chan(chan);
@@ -183,7 +185,7 @@
 	return 0;
 
  out_close:
-	close_chan(&line->chan_list, 0);
+	close_chan(line);
 	return err;
 }
 
@@ -244,7 +246,7 @@
 	chan->fd = -1;
 }
 
-void close_chan(struct list_head *chans, int delay_free_irq)
+void close_chan(struct line *line)
 {
 	struct chan *chan;
 
@@ -253,77 +255,50 @@
 	 * state.  Then, the first one opened will have the original state,
 	 * so it must be the last closed.
 	 */
-	list_for_each_entry_reverse(chan, chans, list) {
-		close_one_chan(chan, delay_free_irq);
+	list_for_each_entry_reverse(chan, &line->chan_list, list) {
+		close_one_chan(chan, 0);
 	}
 }
 
-void deactivate_chan(struct list_head *chans, int irq)
+void deactivate_chan(struct chan *chan, int irq)
 {
-	struct list_head *ele;
-
-	struct chan *chan;
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-
-		if (chan->enabled && chan->input)
-			deactivate_fd(chan->fd, irq);
-	}
+	if (chan && chan->enabled)
+		deactivate_fd(chan->fd, irq);
 }
 
-void reactivate_chan(struct list_head *chans, int irq)
+void reactivate_chan(struct chan *chan, int irq)
 {
-	struct list_head *ele;
-	struct chan *chan;
-
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-
-		if (chan->enabled && chan->input)
-			reactivate_fd(chan->fd, irq);
-	}
+	if (chan && chan->enabled)
+		reactivate_fd(chan->fd, irq);
 }
 
-int write_chan(struct list_head *chans, const char *buf, int len,
+int write_chan(struct chan *chan, const char *buf, int len,
 	       int write_irq)
 {
-	struct list_head *ele;
-	struct chan *chan = NULL;
 	int n, ret = 0;
 
-	if (len == 0)
+	if (len == 0 || !chan || !chan->ops->write)
 		return 0;
 
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-		if (!chan->output || (chan->ops->write == NULL))
-			continue;
-
-		n = chan->ops->write(chan->fd, buf, len, chan->data);
-		if (chan->primary) {
-			ret = n;
-			if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
-				reactivate_fd(chan->fd, write_irq);
-		}
+	n = chan->ops->write(chan->fd, buf, len, chan->data);
+	if (chan->primary) {
+		ret = n;
+		if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
+			reactivate_fd(chan->fd, write_irq);
 	}
 	return ret;
 }
 
-int console_write_chan(struct list_head *chans, const char *buf, int len)
+int console_write_chan(struct chan *chan, const char *buf, int len)
 {
-	struct list_head *ele;
-	struct chan *chan;
 	int n, ret = 0;
 
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-		if (!chan->output || (chan->ops->console_write == NULL))
-			continue;
+	if (!chan || !chan->ops->console_write)
+		return 0;
 
-		n = chan->ops->console_write(chan->fd, buf, len);
-		if (chan->primary)
-			ret = n;
-	}
+	n = chan->ops->console_write(chan->fd, buf, len);
+	if (chan->primary)
+		ret = n;
 	return ret;
 }
 
@@ -340,20 +315,24 @@
 	return 0;
 }
 
-int chan_window_size(struct list_head *chans, unsigned short *rows_out,
+int chan_window_size(struct line *line, unsigned short *rows_out,
 		      unsigned short *cols_out)
 {
-	struct list_head *ele;
 	struct chan *chan;
 
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-		if (chan->primary) {
-			if (chan->ops->window_size == NULL)
-				return 0;
-			return chan->ops->window_size(chan->fd, chan->data,
-						      rows_out, cols_out);
-		}
+	chan = line->chan_in;
+	if (chan && chan->primary) {
+		if (chan->ops->window_size == NULL)
+			return 0;
+		return chan->ops->window_size(chan->fd, chan->data,
+					      rows_out, cols_out);
+	}
+	chan = line->chan_out;
+	if (chan && chan->primary) {
+		if (chan->ops->window_size == NULL)
+			return 0;
+		return chan->ops->window_size(chan->fd, chan->data,
+					      rows_out, cols_out);
 	}
 	return 0;
 }
@@ -429,21 +408,15 @@
 	return n;
 }
 
-int chan_config_string(struct list_head *chans, char *str, int size,
+int chan_config_string(struct line *line, char *str, int size,
 		       char **error_out)
 {
-	struct list_head *ele;
-	struct chan *chan, *in = NULL, *out = NULL;
+	struct chan *in = line->chan_in, *out = line->chan_out;
 
-	list_for_each(ele, chans) {
-		chan = list_entry(ele, struct chan, list);
-		if (!chan->primary)
-			continue;
-		if (chan->input)
-			in = chan;
-		if (chan->output)
-			out = chan;
-	}
+	if (in && !in->primary)
+		in = NULL;
+	if (out && !out->primary)
+		out = NULL;
 
 	return chan_pair_config_string(in, out, str, size, error_out);
 }
@@ -547,10 +520,14 @@
 	char *in, *out;
 
 	if (!list_empty(chans)) {
+		line->chan_in = line->chan_out = NULL;
 		free_chan(chans);
 		INIT_LIST_HEAD(chans);
 	}
 
+	if (!str)
+		return 0;
+
 	out = strchr(str, ',');
 	if (out != NULL) {
 		in = str;
@@ -562,6 +539,7 @@
 
 		new->input = 1;
 		list_add(&new->list, chans);
+		line->chan_in = new;
 
 		new = parse_chan(line, out, device, opts, error_out);
 		if (new == NULL)
@@ -569,6 +547,7 @@
 
 		list_add(&new->list, chans);
 		new->output = 1;
+		line->chan_out = new;
 	}
 	else {
 		new = parse_chan(line, str, device, opts, error_out);
@@ -578,43 +557,42 @@
 		list_add(&new->list, chans);
 		new->input = 1;
 		new->output = 1;
+		line->chan_in = line->chan_out = new;
 	}
 	return 0;
 }
 
-void chan_interrupt(struct list_head *chans, struct delayed_work *task,
-		    struct tty_struct *tty, int irq)
+void chan_interrupt(struct line *line, struct tty_struct *tty, int irq)
 {
-	struct list_head *ele, *next;
-	struct chan *chan;
+	struct chan *chan = line->chan_in;
 	int err;
 	char c;
 
-	list_for_each_safe(ele, next, chans) {
-		chan = list_entry(ele, struct chan, list);
-		if (!chan->input || (chan->ops->read == NULL))
-			continue;
-		do {
-			if (tty && !tty_buffer_request_room(tty, 1)) {
-				schedule_delayed_work(task, 1);
-				goto out;
-			}
-			err = chan->ops->read(chan->fd, &c, chan->data);
-			if (err > 0)
-				tty_receive_char(tty, c);
-		} while (err > 0);
+	if (!chan || !chan->ops->read)
+		goto out;
 
-		if (err == 0)
-			reactivate_fd(chan->fd, irq);
-		if (err == -EIO) {
-			if (chan->primary) {
-				if (tty != NULL)
-					tty_hangup(tty);
-				close_chan(chans, 1);
-				return;
-			}
-			else close_one_chan(chan, 1);
+	do {
+		if (tty && !tty_buffer_request_room(tty, 1)) {
+			schedule_delayed_work(&line->task, 1);
+			goto out;
 		}
+		err = chan->ops->read(chan->fd, &c, chan->data);
+		if (err > 0)
+			tty_receive_char(tty, c);
+	} while (err > 0);
+
+	if (err == 0)
+		reactivate_fd(chan->fd, irq);
+	if (err == -EIO) {
+		if (chan->primary) {
+			if (tty != NULL)
+				tty_hangup(tty);
+			if (line->chan_out != chan)
+				close_one_chan(line->chan_out, 1);
+		}
+		close_one_chan(chan, 1);
+		if (chan->primary)
+			return;
 	}
  out:
 	if (tty)
diff --git a/arch/um/drivers/chan_user.h b/arch/um/drivers/chan_user.h
index 9b9ced8..6257b7a 100644
--- a/arch/um/drivers/chan_user.h
+++ b/arch/um/drivers/chan_user.h
@@ -14,8 +14,6 @@
 	const int raw;
 };
 
-enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
-
 struct chan_ops {
 	char *type;
 	void *(*init)(char *, int, const struct chan_opts *);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index c1cf220..4ab0d9c 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -21,19 +21,10 @@
 	struct line *line = chan->line;
 
 	if (line)
-		chan_interrupt(&line->chan_list, &line->task, line->tty, irq);
+		chan_interrupt(line, line->tty, irq);
 	return IRQ_HANDLED;
 }
 
-static void line_timer_cb(struct work_struct *work)
-{
-	struct line *line = container_of(work, struct line, task.work);
-
-	if (!line->throttled)
-		chan_interrupt(&line->chan_list, &line->task, line->tty,
-			       line->driver->read_irq);
-}
-
 /*
  * Returns the free space inside the ring buffer of this line.
  *
@@ -145,7 +136,7 @@
 		/* line->buffer + LINE_BUFSIZE is the end of the buffer! */
 		count = line->buffer + LINE_BUFSIZE - line->head;
 
-		n = write_chan(&line->chan_list, line->head, count,
+		n = write_chan(line->chan_out, line->head, count,
 			       line->driver->write_irq);
 		if (n < 0)
 			return n;
@@ -162,7 +153,7 @@
 	}
 
 	count = line->tail - line->head;
-	n = write_chan(&line->chan_list, line->head, count,
+	n = write_chan(line->chan_out, line->head, count,
 		       line->driver->write_irq);
 
 	if (n < 0)
@@ -206,7 +197,7 @@
 	if (line->head != line->tail)
 		ret = buffer_data(line, buf, len);
 	else {
-		n = write_chan(&line->chan_list, buf, len,
+		n = write_chan(line->chan_out, buf, len,
 			       line->driver->write_irq);
 		if (n < 0) {
 			ret = n;
@@ -318,7 +309,7 @@
 {
 	struct line *line = tty->driver_data;
 
-	deactivate_chan(&line->chan_list, line->driver->read_irq);
+	deactivate_chan(line->chan_in, line->driver->read_irq);
 	line->throttled = 1;
 }
 
@@ -327,8 +318,7 @@
 	struct line *line = tty->driver_data;
 
 	line->throttled = 0;
-	chan_interrupt(&line->chan_list, &line->task, tty,
-		       line->driver->read_irq);
+	chan_interrupt(line, tty, line->driver->read_irq);
 
 	/*
 	 * Maybe there is enough stuff pending that calling the interrupt
@@ -336,7 +326,7 @@
 	 * again and we shouldn't turn the interrupt back on.
 	 */
 	if (!line->throttled)
-		reactivate_chan(&line->chan_list, line->driver->read_irq);
+		reactivate_chan(line->chan_in, line->driver->read_irq);
 }
 
 static irqreturn_t line_write_interrupt(int irq, void *data)
@@ -347,13 +337,14 @@
 	int err;
 
 	/*
-	 * Interrupts are disabled here because we registered the interrupt with
-	 * IRQF_DISABLED (see line_setup_irq).
+	 * Interrupts are disabled here because genirq keep irqs disabled when
+	 * calling the action handler.
 	 */
 
 	spin_lock(&line->lock);
 	err = flush_buffer(line);
 	if (err == 0) {
+		spin_unlock(&line->lock);
 		return IRQ_NONE;
 	} else if (err < 0) {
 		line->head = line->buffer;
@@ -371,7 +362,7 @@
 int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
 {
 	const struct line_driver *driver = line->driver;
-	int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
+	int err = 0, flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
 
 	if (input)
 		err = um_request_irq(driver->read_irq, fd, IRQ_READ,
@@ -383,7 +374,6 @@
 		err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
 					line_write_interrupt, flags,
 					driver->write_irq_name, data);
-	line->have_irq = 1;
 	return err;
 }
 
@@ -409,7 +399,7 @@
 	struct line *line = &lines[tty->index];
 	int err = -ENODEV;
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 	if (!line->valid)
 		goto out_unlock;
 
@@ -421,25 +411,19 @@
 	tty->driver_data = line;
 	line->tty = tty;
 
-	spin_unlock(&line->count_lock);
 	err = enable_chan(line);
 	if (err) /* line_close() will be called by our caller */
-		return err;
-
-	INIT_DELAYED_WORK(&line->task, line_timer_cb);
+		goto out_unlock;
 
 	if (!line->sigio) {
-		chan_enable_winch(&line->chan_list, tty);
+		chan_enable_winch(line->chan_out, tty);
 		line->sigio = 1;
 	}
 
-	chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+	chan_window_size(line, &tty->winsize.ws_row,
 			 &tty->winsize.ws_col);
-
-	return 0;
-
 out_unlock:
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 	return err;
 }
 
@@ -459,7 +443,7 @@
 	/* We ignore the error anyway! */
 	flush_buffer(line);
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 	BUG_ON(!line->valid);
 
 	if (--line->count)
@@ -468,17 +452,13 @@
 	line->tty = NULL;
 	tty->driver_data = NULL;
 
-	spin_unlock(&line->count_lock);
-
 	if (line->sigio) {
 		unregister_winch(tty);
 		line->sigio = 0;
 	}
 
-	return;
-
 out_unlock:
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 }
 
 void close_lines(struct line *lines, int nlines)
@@ -486,34 +466,60 @@
 	int i;
 
 	for(i = 0; i < nlines; i++)
-		close_chan(&lines[i].chan_list, 0);
+		close_chan(&lines[i]);
 }
 
-static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
-			  char **error_out)
+int setup_one_line(struct line *lines, int n, char *init,
+		   const struct chan_opts *opts, char **error_out)
 {
 	struct line *line = &lines[n];
+	struct tty_driver *driver = line->driver->driver;
 	int err = -EINVAL;
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 
 	if (line->count) {
 		*error_out = "Device is already open";
 		goto out;
 	}
 
-	if (line->init_pri <= init_prio) {
-		line->init_pri = init_prio;
-		if (!strcmp(init, "none"))
+	if (!strcmp(init, "none")) {
+		if (line->valid) {
 			line->valid = 0;
-		else {
-			line->init_str = init;
-			line->valid = 1;
+			kfree(line->init_str);
+			tty_unregister_device(driver, n);
+			parse_chan_pair(NULL, line, n, opts, error_out);
+			err = 0;
+		}
+	} else {
+		char *new = kstrdup(init, GFP_KERNEL);
+		if (!new) {
+			*error_out = "Failed to allocate memory";
+			return -ENOMEM;
+		}
+		if (line->valid) {
+			tty_unregister_device(driver, n);
+			kfree(line->init_str);
+		}
+		line->init_str = new;
+		line->valid = 1;
+		err = parse_chan_pair(new, line, n, opts, error_out);
+		if (!err) {
+			struct device *d = tty_register_device(driver, n, NULL);
+			if (IS_ERR(d)) {
+				*error_out = "Failed to register device";
+				err = PTR_ERR(d);
+				parse_chan_pair(NULL, line, n, opts, error_out);
+			}
+		}
+		if (err) {
+			line->init_str = NULL;
+			line->valid = 0;
+			kfree(new);
 		}
 	}
-	err = 0;
 out:
-	spin_unlock(&line->count_lock);
+	mutex_unlock(&line->count_lock);
 	return err;
 }
 
@@ -524,54 +530,43 @@
  * @error_out is an error string in the case of failure;
  */
 
-int line_setup(struct line *lines, unsigned int num, char *init,
-	       char **error_out)
+int line_setup(char **conf, unsigned int num, char **def,
+	       char *init, char *name)
 {
-	int i, n, err;
-	char *end;
+	char *error;
 
 	if (*init == '=') {
 		/*
 		 * We said con=/ssl= instead of con#=, so we are configuring all
 		 * consoles at once.
 		 */
-		n = -1;
-	}
-	else {
-		n = simple_strtoul(init, &end, 0);
-		if (*end != '=') {
-			*error_out = "Couldn't parse device number";
-			return -EINVAL;
-		}
-		init = end;
-	}
-	init++;
+		*def = init + 1;
+	} else {
+		char *end;
+		unsigned n = simple_strtoul(init, &end, 0);
 
-	if (n >= (signed int) num) {
-		*error_out = "Device number out of range";
-		return -EINVAL;
-	}
-	else if (n >= 0) {
-		err = setup_one_line(lines, n, init, INIT_ONE, error_out);
-		if (err)
-			return err;
-	}
-	else {
-		for(i = 0; i < num; i++) {
-			err = setup_one_line(lines, i, init, INIT_ALL,
-					     error_out);
-			if (err)
-				return err;
+		if (*end != '=') {
+			error = "Couldn't parse device number";
+			goto out;
 		}
+		if (n >= num) {
+			error = "Device number out of range";
+			goto out;
+		}
+		conf[n] = end + 1;
 	}
-	return n == -1 ? num : n;
+	return 0;
+
+out:
+	printk(KERN_ERR "Failed to set up %s with "
+	       "configuration string \"%s\" : %s\n", name, init, error);
+	return -EINVAL;
 }
 
 int line_config(struct line *lines, unsigned int num, char *str,
 		const struct chan_opts *opts, char **error_out)
 {
-	struct line *line;
-	char *new;
+	char *end;
 	int n;
 
 	if (*str == '=') {
@@ -579,17 +574,17 @@
 		return -EINVAL;
 	}
 
-	new = kstrdup(str, GFP_KERNEL);
-	if (new == NULL) {
-		*error_out = "Failed to allocate memory";
-		return -ENOMEM;
+	n = simple_strtoul(str, &end, 0);
+	if (*end++ != '=') {
+		*error_out = "Couldn't parse device number";
+		return -EINVAL;
 	}
-	n = line_setup(lines, num, new, error_out);
-	if (n < 0)
-		return n;
+	if (n >= num) {
+		*error_out = "Device number out of range";
+		return -EINVAL;
+	}
 
-	line = &lines[n];
-	return parse_chan_pair(line->init_str, line, n, opts, error_out);
+	return setup_one_line(lines, n, end, opts, error_out);
 }
 
 int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -612,13 +607,13 @@
 
 	line = &lines[dev];
 
-	spin_lock(&line->count_lock);
+	mutex_lock(&line->count_lock);
 	if (!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if (line->tty == NULL)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
-	else n = chan_config_string(&line->chan_list, str, size, error_out);
-	spin_unlock(&line->count_lock);
+	else n = chan_config_string(line, str, size, error_out);
+	mutex_unlock(&line->count_lock);
 
 	return n;
 }
@@ -640,25 +635,23 @@
 
 int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
 {
-	int err;
-	char config[sizeof("conxxxx=none\0")];
-
-	sprintf(config, "%d=none", n);
-	err = line_setup(lines, num, config, error_out);
-	if (err >= 0)
-		err = 0;
-	return err;
+	if (n >= num) {
+		*error_out = "Device number out of range";
+		return -EINVAL;
+	}
+	return setup_one_line(lines, n, "none", NULL, error_out);
 }
 
-struct tty_driver *register_lines(struct line_driver *line_driver,
-				  const struct tty_operations *ops,
-				  struct line *lines, int nlines)
+int register_lines(struct line_driver *line_driver,
+		   const struct tty_operations *ops,
+		   struct line *lines, int nlines)
 {
-	int i;
 	struct tty_driver *driver = alloc_tty_driver(nlines);
+	int err;
+	int i;
 
 	if (!driver)
-		return NULL;
+		return -ENOMEM;
 
 	driver->driver_name = line_driver->name;
 	driver->name = line_driver->device_name;
@@ -666,54 +659,33 @@
 	driver->minor_start = line_driver->minor_start;
 	driver->type = line_driver->type;
 	driver->subtype = line_driver->subtype;
-	driver->flags = TTY_DRIVER_REAL_RAW;
+	driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 	driver->init_termios = tty_std_termios;
+	
+	for (i = 0; i < nlines; i++) {
+		spin_lock_init(&lines[i].lock);
+		mutex_init(&lines[i].count_lock);
+		lines[i].driver = line_driver;
+		INIT_LIST_HEAD(&lines[i].chan_list);
+	}
 	tty_set_operations(driver, ops);
 
-	if (tty_register_driver(driver)) {
+	err = tty_register_driver(driver);
+	if (err) {
 		printk(KERN_ERR "register_lines : can't register %s driver\n",
 		       line_driver->name);
 		put_tty_driver(driver);
-		return NULL;
+		return err;
 	}
 
-	for(i = 0; i < nlines; i++) {
-		if (!lines[i].valid)
-			tty_unregister_device(driver, i);
-	}
-
+	line_driver->driver = driver;
 	mconsole_register_dev(&line_driver->mc);
-	return driver;
+	return 0;
 }
 
 static DEFINE_SPINLOCK(winch_handler_lock);
 static LIST_HEAD(winch_handlers);
 
-void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
-{
-	struct line *line;
-	char *error;
-	int i;
-
-	for(i = 0; i < nlines; i++) {
-		line = &lines[i];
-		INIT_LIST_HEAD(&line->chan_list);
-
-		if (line->init_str == NULL)
-			continue;
-
-		line->init_str = kstrdup(line->init_str, GFP_KERNEL);
-		if (line->init_str == NULL)
-			printk(KERN_ERR "lines_init - kstrdup returned NULL\n");
-
-		if (parse_chan_pair(line->init_str, line, i, opts, &error)) {
-			printk(KERN_ERR "parse_chan_pair failed for "
-			       "device %d : %s\n", i, error);
-			line->valid = 0;
-		}
-	}
-}
-
 struct winch {
 	struct list_head list;
 	int fd;
@@ -777,7 +749,7 @@
 	if (tty != NULL) {
 		line = tty->driver_data;
 		if (line != NULL) {
-			chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+			chan_window_size(line, &tty->winsize.ws_row,
 					 &tty->winsize.ws_col);
 			kill_pgrp(tty->pgrp, SIGWINCH, 1);
 		}
@@ -807,7 +779,7 @@
 				   .stack	= stack });
 
 	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-			   IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			   IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			   "winch", winch) < 0) {
 		printk(KERN_ERR "register_winch_irq - failed to register "
 		       "IRQ\n");
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 63df3ca..0a18347 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -15,7 +15,7 @@
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
-/* There's only one modifiable field in this - .mc.list */
+/* There's only two modifiable fields in this - .mc.list and .driver */
 struct line_driver {
 	const char *name;
 	const char *device_name;
@@ -28,17 +28,18 @@
 	const int write_irq;
 	const char *write_irq_name;
 	struct mc_device mc;
+	struct tty_driver *driver;
 };
 
 struct line {
 	struct tty_struct *tty;
-	spinlock_t count_lock;
+	struct mutex count_lock;
 	unsigned long count;
 	int valid;
 
 	char *init_str;
-	int init_pri;
 	struct list_head chan_list;
+	struct chan *chan_in, *chan_out;
 
 	/*This lock is actually, mostly, local to*/
 	spinlock_t lock;
@@ -55,21 +56,12 @@
 	int sigio;
 	struct delayed_work task;
 	const struct line_driver *driver;
-	int have_irq;
 };
 
-#define LINE_INIT(str, d) \
-	{ .count_lock =	__SPIN_LOCK_UNLOCKED((str).count_lock), \
-	  .init_str =	str,	\
-	  .init_pri =	INIT_STATIC, \
-	  .valid =	1, \
-	  .lock =	__SPIN_LOCK_UNLOCKED((str).lock), \
-	  .driver =	d }
-
 extern void line_close(struct tty_struct *tty, struct file * filp);
 extern int line_open(struct line *lines, struct tty_struct *tty);
-extern int line_setup(struct line *lines, unsigned int sizeof_lines,
-		      char *init, char **error_out);
+extern int line_setup(char **conf, unsigned nlines, char **def,
+		      char *init, char *name);
 extern int line_write(struct tty_struct *tty, const unsigned char *buf,
 		      int len);
 extern int line_put_char(struct tty_struct *tty, unsigned char ch);
@@ -87,10 +79,11 @@
 extern int line_setup_irq(int fd, int input, int output, struct line *line,
 			  void *data);
 extern void line_close_chan(struct line *line);
-extern struct tty_driver *register_lines(struct line_driver *line_driver,
-					 const struct tty_operations *driver,
-					 struct line *lines, int nlines);
-extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
+extern int register_lines(struct line_driver *line_driver,
+			  const struct tty_operations *driver,
+			  struct line *lines, int nlines);
+extern int setup_one_line(struct line *lines, int n, char *init,
+			  const struct chan_opts *opts, char **error_out);
 extern void close_lines(struct line *lines, int nlines);
 
 extern int line_config(struct line *lines, unsigned int sizeof_lines,
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index c70e047..e672bd6 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -773,7 +773,7 @@
 	register_reboot_notifier(&reboot_notifier);
 
 	err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
-			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			     IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			     "mconsole", (void *)sock);
 	if (err) {
 		printk(KERN_ERR "Failed to get IRQ for management console\n");
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index d299618..95f4416 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -161,7 +161,7 @@
 	}
 
 	err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt,
-			     IRQF_DISABLED | IRQF_SHARED, dev->name, dev);
+			     IRQF_SHARED, dev->name, dev);
 	if (err != 0) {
 		printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err);
 		err = -ENETUNREACH;
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index a11573b..e31680e 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -100,7 +100,7 @@
 		  .port 	= port });
 
 	if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			  IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			  "telnetd", conn)) {
 		printk(KERN_ERR "port_accept : failed to get IRQ for "
 		       "telnetd\n");
@@ -184,7 +184,7 @@
 	}
 
 	if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			  IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			  "port", port)) {
 		printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
 		goto out_close;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 981085a..b25296e 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -131,7 +131,7 @@
 	random_fd = err;
 
 	err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
-			     IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
+			     IRQF_SAMPLE_RANDOM, "random",
 			     NULL);
 	if (err)
 		goto err_out_cleanup_hw;
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 9d8c20a..e09801a 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -20,12 +20,6 @@
 
 static const int ssl_version = 1;
 
-/* Referenced only by tty_driver below - presumably it's locked correctly
- * by the tty driver.
- */
-
-static struct tty_driver *ssl_driver;
-
 #define NR_PORTS 64
 
 static void ssl_announce(char *dev_name, int dev)
@@ -71,8 +65,9 @@
 /* The array is initialized by line_init, at initcall time.  The
  * elements are locked individually as needed.
  */
-static struct line serial_lines[NR_PORTS] =
-	{ [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
+static char *conf[NR_PORTS];
+static char *def_conf = CONFIG_SSL_CHAN;
+static struct line serial_lines[NR_PORTS];
 
 static int ssl_config(char *str, char **error_out)
 {
@@ -156,14 +151,14 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&line->lock, flags);
-	console_write_chan(&line->chan_list, string, len);
+	console_write_chan(line->chan_out, string, len);
 	spin_unlock_irqrestore(&line->lock, flags);
 }
 
 static struct tty_driver *ssl_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return ssl_driver;
+	return driver.driver;
 }
 
 static int ssl_console_setup(struct console *co, char *options)
@@ -186,17 +181,30 @@
 static int ssl_init(void)
 {
 	char *new_title;
+	int err;
+	int i;
 
 	printk(KERN_INFO "Initializing software serial port version %d\n",
 	       ssl_version);
-	ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
+
+	err = register_lines(&driver, &ssl_ops, serial_lines,
 				    ARRAY_SIZE(serial_lines));
+	if (err)
+		return err;
 
 	new_title = add_xterm_umid(opts.xterm_title);
 	if (new_title != NULL)
 		opts.xterm_title = new_title;
 
-	lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
+	for (i = 0; i < NR_PORTS; i++) {
+		char *error;
+		char *s = conf[i];
+		if (!s)
+			s = def_conf;
+		if (setup_one_line(serial_lines, i, s, &opts, &error))
+			printk(KERN_ERR "setup_one_line failed for "
+			       "device %d : %s\n", i, error);
+	}
 
 	ssl_init_done = 1;
 	register_console(&ssl_cons);
@@ -214,14 +222,7 @@
 
 static int ssl_chan_setup(char *str)
 {
-	char *error;
-	int ret;
-
-	ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error);
-	if(ret < 0)
-		printk(KERN_ERR "Failed to set up serial line with "
-		       "configuration string \"%s\" : %s\n", str, error);
-
+	line_setup(conf, NR_PORTS, &def_conf, str, "serial line");
 	return 1;
 }
 
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 088776f..7663541 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -27,12 +27,6 @@
 
 #define MAX_TTYS (16)
 
-/* Referenced only by tty_driver below - presumably it's locked correctly
- * by the tty driver.
- */
-
-static struct tty_driver *console_driver;
-
 static void stdio_announce(char *dev_name, int dev)
 {
 	printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev,
@@ -76,9 +70,9 @@
 /* The array is initialized by line_init, at initcall time.  The
  * elements are locked individually as needed.
  */
-static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
-				     [ 1 ... MAX_TTYS - 1 ] =
-				     LINE_INIT(CONFIG_CON_CHAN, &driver) };
+static char *vt_conf[MAX_TTYS];
+static char *def_conf;
+static struct line vts[MAX_TTYS];
 
 static int con_config(char *str, char **error_out)
 {
@@ -130,14 +124,14 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&line->lock, flags);
-	console_write_chan(&line->chan_list, string, len);
+	console_write_chan(line->chan_out, string, len);
 	spin_unlock_irqrestore(&line->lock, flags);
 }
 
 static struct tty_driver *uml_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return console_driver;
+	return driver.driver;
 }
 
 static int uml_console_setup(struct console *co, char *options)
@@ -160,18 +154,31 @@
 static int stdio_init(void)
 {
 	char *new_title;
+	int err;
+	int i;
 
-	console_driver = register_lines(&driver, &console_ops, vts,
+	err = register_lines(&driver, &console_ops, vts,
 					ARRAY_SIZE(vts));
-	if (console_driver == NULL)
-		return -1;
+	if (err)
+		return err;
+
 	printk(KERN_INFO "Initialized stdio console driver\n");
 
 	new_title = add_xterm_umid(opts.xterm_title);
 	if(new_title != NULL)
 		opts.xterm_title = new_title;
 
-	lines_init(vts, ARRAY_SIZE(vts), &opts);
+	for (i = 0; i < MAX_TTYS; i++) {
+		char *error;
+		char *s = vt_conf[i];
+		if (!s)
+			s = def_conf;
+		if (!s)
+			s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN;
+		if (setup_one_line(vts, i, s, &opts, &error))
+			printk(KERN_ERR "setup_one_line failed for "
+			       "device %d : %s\n", i, error);
+	}
 
 	con_init_done = 1;
 	register_console(&stdiocons);
@@ -189,14 +196,7 @@
 
 static int console_chan_setup(char *str)
 {
-	char *error;
-	int ret;
-
-	ret = line_setup(vts, ARRAY_SIZE(vts), str, &error);
-	if(ret < 0)
-		printk(KERN_ERR "Failed to set up console with "
-		       "configuration string \"%s\" : %s\n", str, error);
-
+	line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console");
 	return 1;
 }
 __setup("con", console_chan_setup);
diff --git a/arch/um/drivers/ubd_user.h b/arch/um/drivers/ubd.h
similarity index 100%
rename from arch/um/drivers/ubd_user.h
rename to arch/um/drivers/ubd.h
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 944453a..20505ca 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -19,40 +19,26 @@
 
 #define UBD_SHIFT 4
 
-#include "linux/kernel.h"
-#include "linux/module.h"
-#include "linux/blkdev.h"
-#include "linux/ata.h"
-#include "linux/hdreg.h"
-#include "linux/init.h"
-#include "linux/cdrom.h"
-#include "linux/proc_fs.h"
-#include "linux/seq_file.h"
-#include "linux/ctype.h"
-#include "linux/capability.h"
-#include "linux/mm.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
-#include "linux/mutex.h"
-#include "linux/blkpg.h"
-#include "linux/genhd.h"
-#include "linux/spinlock.h"
-#include "linux/platform_device.h"
-#include "linux/scatterlist.h"
-#include "asm/segment.h"
-#include "asm/uaccess.h"
-#include "asm/irq.h"
-#include "asm/types.h"
-#include "asm/tlbflush.h"
-#include "mem_user.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/ata.h>
+#include <linux/hdreg.h>
+#include <linux/cdrom.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <asm/tlbflush.h>
 #include "kern_util.h"
 #include "mconsole_kern.h"
 #include "init.h"
-#include "irq_user.h"
 #include "irq_kern.h"
-#include "ubd_user.h"
+#include "ubd.h"
 #include "os.h"
-#include "mem.h"
 #include "cow.h"
 
 enum ubd_req { UBD_READ, UBD_WRITE };
@@ -1115,7 +1101,7 @@
 		return 0;
 	}
 	err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
-			     IRQF_DISABLED, "ubd", ubd_devs);
+			     0, "ubd", ubd_devs);
 	if(err != 0)
 		printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
 	return 0;
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 007b94d..ffe02c4 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -15,14 +15,12 @@
 #include <sys/socket.h>
 #include <sys/mman.h>
 #include <sys/param.h>
-#include "asm/types.h"
-#include "ubd_user.h"
-#include "os.h"
-#include "cow.h"
-
 #include <endian.h>
 #include <byteswap.h>
 
+#include "ubd.h"
+#include "os.h"
+
 void ignore_sigwinch_sig(void)
 {
 	signal(SIGWINCH, SIG_IGN);
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index b646bcc..8bd130f 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -50,7 +50,7 @@
 	init_completion(&data->ready);
 
 	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
-			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			     IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 			     "xterm", data);
 	if (err) {
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 451f451..8419f5c 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -1,3 +1,3 @@
 generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
 generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
-generic-y += ftrace.h
+generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h
diff --git a/arch/um/include/asm/asm-offsets.h b/arch/um/include/asm/asm-offsets.h
deleted file mode 100644
index d370ee3..0000000
--- a/arch/um/include/asm/asm-offsets.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <generated/asm-offsets.h>
diff --git a/arch/um/include/asm/auxvec.h b/arch/um/include/asm/auxvec.h
deleted file mode 100644
index 1e5e1c2..0000000
--- a/arch/um/include/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __UM_AUXVEC_H
-#define __UM_AUXVEC_H
-
-#endif
diff --git a/arch/um/include/asm/current.h b/arch/um/include/asm/current.h
deleted file mode 100644
index c2191d9..0000000
--- a/arch/um/include/asm/current.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_CURRENT_H
-#define __UM_CURRENT_H
-
-#include "linux/thread_info.h"
-
-#define current (current_thread_info()->task)
-
-#endif
diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h
deleted file mode 100644
index 8a5576d..0000000
--- a/arch/um/include/asm/delay.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __UM_DELAY_H
-#define __UM_DELAY_H
-
-/* Undefined on purpose */
-extern void __bad_udelay(void);
-extern void __bad_ndelay(void);
-
-extern void __udelay(unsigned long usecs);
-extern void __ndelay(unsigned long usecs);
-extern void __delay(unsigned long loops);
-
-#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
-	__bad_udelay() : __udelay(n))
-
-#define ndelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \
-	__bad_ndelay() : __ndelay(n))
-
-#endif
diff --git a/arch/um/include/asm/io.h b/arch/um/include/asm/io.h
deleted file mode 100644
index 44e8b8c..0000000
--- a/arch/um/include/asm/io.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __UM_IO_H
-#define __UM_IO_H
-
-#include "asm/page.h"
-
-#define IO_SPACE_LIMIT 0xdeadbeef /* Sure hope nothing uses this */
-
-static inline int inb(unsigned long i) { return(0); }
-static inline void outb(char c, unsigned long i) { }
-
-/*
- * Change virtual addresses to physical addresses and vv.
- * These are pretty trivial
- */
-static inline unsigned long virt_to_phys(volatile void * address)
-{
-	return __pa((void *) address);
-}
-
-static inline void * phys_to_virt(unsigned long address)
-{
-	return __va(address);
-}
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)	p
-
-static inline void writeb(unsigned char b, volatile void __iomem *addr)
-{
-	*(volatile unsigned char __force *) addr = b;
-}
-static inline void writew(unsigned short b, volatile void __iomem *addr)
-{
-	*(volatile unsigned short __force *) addr = b;
-}
-static inline void writel(unsigned int b, volatile void __iomem *addr)
-{
-	*(volatile unsigned int __force *) addr = b;
-}
-static inline void writeq(unsigned int b, volatile void __iomem *addr)
-{
-	*(volatile unsigned long long __force *) addr = b;
-}
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-#define __raw_writeq writeq
-
-#endif
diff --git a/arch/um/include/asm/mutex.h b/arch/um/include/asm/mutex.h
deleted file mode 100644
index 458c1f7..0000000
--- a/arch/um/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/um/include/asm/param.h b/arch/um/include/asm/param.h
deleted file mode 100644
index e44f4e6..0000000
--- a/arch/um/include/asm/param.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _UM_PARAM_H
-#define _UM_PARAM_H
-
-#define EXEC_PAGESIZE   4096
-
-#ifndef NOGROUP
-#define NOGROUP         (-1)
-#endif
-
-#define MAXHOSTNAMELEN  64      /* max length of hostname */
-
-#ifdef __KERNEL__
-#define HZ CONFIG_HZ
-#define USER_HZ	100	   /* .. some user interfaces are in "ticks" */
-#define CLOCKS_PER_SEC (USER_HZ)  /* frequency at which times() counts */
-#else
-#define HZ 100
-#endif
-
-#endif
diff --git a/arch/um/include/asm/pci.h b/arch/um/include/asm/pci.h
deleted file mode 100644
index b44cf59..0000000
--- a/arch/um/include/asm/pci.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __UM_PCI_H
-#define __UM_PCI_H
-
-#define PCI_DMA_BUS_IS_PHYS     (1)
-
-#endif
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h
index 32c8ce4..bf90b2a 100644
--- a/arch/um/include/asm/pgalloc.h
+++ b/arch/um/include/asm/pgalloc.h
@@ -8,8 +8,7 @@
 #ifndef __UM_PGALLOC_H
 #define __UM_PGALLOC_H
 
-#include "linux/mm.h"
-#include "asm/fixmap.h"
+#include <linux/mm.h>
 
 #define pmd_populate_kernel(mm, pmd, pte) \
 	set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte)))
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 41474fb..6a3f984 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -69,6 +69,8 @@
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
 #define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC)
 
+#define io_remap_pfn_range	remap_pfn_range
+
 /*
  * The i386 can't do page protection for execute, and considers that the same
  * are read.
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index f605d3c..e786a6a 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -9,7 +9,6 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/ptrace-abi.h>
-#include <asm/user.h>
 #include "sysdep/ptrace.h"
 
 struct pt_regs {
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index d7fe563..40db8f7 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -2,8 +2,6 @@
 
 DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 
-OFFSET(HOST_TASK_PID, task_struct, pid);
-
 DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
 DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
 DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h
index 0f14838..00965d0 100644
--- a/arch/um/include/shared/kern_util.h
+++ b/arch/um/include/shared/kern_util.h
@@ -48,7 +48,7 @@
  * GFP_ATOMIC.
  */
 extern int __cant_sleep(void);
-extern void *get_current(void);
+extern int get_current_pid(void);
 extern int copy_from_user_proc(void *to, void *from, int size);
 extern int cpu(void);
 extern char *uml_strdup(const char *string);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index bc49474..492bc4c 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -3,7 +3,7 @@
 # Licensed under the GPL
 #
 
-CPPFLAGS_vmlinux.lds := -U$(SUBARCH) -DSTART=$(LDS_START) \
+CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
                         -DELF_ARCH=$(LDS_ELF_ARCH)        \
                         -DELF_FORMAT=$(LDS_ELF_FORMAT)
 extra-y := vmlinux.lds
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 69f2490..f386d04 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -126,9 +126,9 @@
 {
 }
 
-void *get_current(void)
+int get_current_pid(void)
 {
-	return current;
+	return task_pid_nr(current);
 }
 
 /*
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 2b272b6..2a16392 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -25,7 +25,7 @@
 	int err;
 
 	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
-			     IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
+			     IRQF_SAMPLE_RANDOM, "write sigio",
 			     NULL);
 	if (err) {
 		printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 82a6e22..d1a23fb 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -82,7 +82,7 @@
 {
 	int err;
 
-	err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL);
+	err = request_irq(TIMER_IRQ, um_timer, 0, "timer", NULL);
 	if (err != 0)
 		printk(KERN_ERR "register_timer : request_irq failed - "
 		       "errno = %d\n", -err);
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index dd76410..08ff509 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -13,8 +13,6 @@
 	main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
 	tty.o umid.o util.o
 
-CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
-
 HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \
 	echo -DHAVE_AIO_ABI )
 CFLAGS_aio.o += $(HAVE_AIO_ABI)
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 45ffe46..73926fa 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -45,7 +45,7 @@
 extern void truncate64(void) __attribute__((weak));
 EXPORT_SYMBOL(truncate64);
 
-#ifdef SUBARCH_i386
+#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
 EXPORT_SYMBOL(vsyscall_ehdr);
 EXPORT_SYMBOL(vsyscall_end);
 #endif
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 2eb2843..d50270d 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -9,8 +9,6 @@
 
 $(USER_OBJS:.o=.%): \
 	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
-$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-	-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
 
 # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
 # using it directly.
@@ -18,8 +16,9 @@
 
 $(UNPROFILE_OBJS:.o=.%): \
 	c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(basetarget).o)
-$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-	-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
+
+$(USER_OBJS) $(UNPROFILE_OBJS): \
+	CHECKFLAGS := $(patsubst $(NOSTDINC_FLAGS),,$(CHECKFLAGS))
 
 # The stubs can't try to call mcount or update basic block data
 define unprofile
diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um
index 36ddec6..4be406a 100644
--- a/arch/x86/Makefile.um
+++ b/arch/x86/Makefile.um
@@ -8,15 +8,11 @@
 ELF_FORMAT 		:= elf32-i386
 CHECKFLAGS	+= -D__i386__
 
-ifeq ("$(origin SUBARCH)", "command line")
-ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
 KBUILD_CFLAGS		+= $(call cc-option,-m32)
 KBUILD_AFLAGS		+= $(call cc-option,-m32)
 LINK-y			+= $(call cc-option,-m32)
 
 export LDFLAGS
-endif
-endif
 
 # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
 include $(srctree)/arch/x86/Makefile_32.cpu
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index b2b54d2..9926e11 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -15,8 +15,8 @@
 	select GENERIC_FIND_FIRST_BIT
 
 config 64BIT
-	bool
-	default SUBARCH = "x86_64"
+	bool "64-bit kernel" if SUBARCH = "x86"
+	default SUBARCH != "i386"
 
 config X86_32
 	def_bool !64BIT
diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h
index 2c32df6..04f82e0 100644
--- a/arch/x86/um/asm/processor.h
+++ b/arch/x86/um/asm/processor.h
@@ -17,6 +17,16 @@
 #define ARCH_IS_STACKGROW(address) \
        (address + 65536 + 32 * sizeof(unsigned long) >= UPT_SP(&current->thread.regs.regs))
 
+#include <asm/user.h>
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	__asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax()	rep_nop()
+
 #include <asm/processor-generic.h>
 
 #endif
diff --git a/arch/x86/um/asm/processor_32.h b/arch/x86/um/asm/processor_32.h
index 018f732..6c6689e 100644
--- a/arch/x86/um/asm/processor_32.h
+++ b/arch/x86/um/asm/processor_32.h
@@ -45,16 +45,6 @@
         memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array));
 }
 
-#include <asm/user.h>
-
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()	rep_nop()
-
 /*
  * Default implementation of macro that returns current
  * instruction pointer ("program counter"). Stolen
diff --git a/arch/x86/um/asm/processor_64.h b/arch/x86/um/asm/processor_64.h
index 61de92d..4b02a84 100644
--- a/arch/x86/um/asm/processor_64.h
+++ b/arch/x86/um/asm/processor_64.h
@@ -14,14 +14,6 @@
         struct faultinfo faultinfo;
 };
 
-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-static inline void rep_nop(void)
-{
-	__asm__ __volatile__("rep;nop": : :"memory");
-}
-
-#define cpu_relax()   rep_nop()
-
 #define INIT_ARCH_THREAD { .debugregs  		= { [ 0 ... 7 ] = 0 }, \
 			   .debugregs_seq	= 0, \
 			   .fs			= 0, \
@@ -37,8 +29,6 @@
 	to->fs = from->fs;
 }
 
-#include <asm/user.h>
-
 #define current_text_addr() \
 	({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; })
 
diff --git a/arch/x86/um/bugs_32.c b/arch/x86/um/bugs_32.c
index a1fba5f..17d88cf 100644
--- a/arch/x86/um/bugs_32.c
+++ b/arch/x86/um/bugs_32.c
@@ -13,8 +13,6 @@
 static int host_has_cmov = 1;
 static jmp_buf cmov_test_return;
 
-#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
-
 static void cmov_sigill_test_handler(int sig)
 {
 	host_has_cmov = 0;
@@ -51,7 +49,7 @@
 	 * This is testing for a cmov (0x0f 0x4x) instruction causing a
 	 * SIGILL in init.
 	 */
-	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+	if ((sig != SIGILL) || (get_current_pid() != 1))
 		return;
 
 	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 1be6218..284cf34 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -1,6 +1,6 @@
 menuconfig MTD
 	tristate "Memory Technology Device (MTD) support"
-	depends on HAS_IOMEM
+	depends on GENERIC_IO
 	help
 	  Memory Technology Devices are flash, RAM and similar chips, often
 	  used for solid state file systems on embedded devices. This option
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 37b05c3..8d3dac4 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -1,5 +1,6 @@
 menu "Self-contained MTD device drivers"
 	depends on MTD!=n
+	depends on HAS_IOMEM
 
 config MTD_PMC551
 	tristate "Ramix PMC551 PCI Mezzanine RAM card support"
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 6c5c431..8af67cf 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -1,5 +1,6 @@
 menu "Mapping drivers for chip access"
 	depends on MTD!=n
+	depends on HAS_IOMEM
 
 config MTD_COMPLEX_MAPPINGS
 	bool "Support non-linear mappings of flash chips"
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 3d8d2d8..a3c4de5 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -246,6 +246,7 @@
 config MTD_NAND_DISKONCHIP
 	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	depends on HAS_IOMEM
 	select REED_SOLOMON
 	select REED_SOLOMON_DEC16
 	help
@@ -431,6 +432,7 @@
 
 config MTD_NAND_PLATFORM
 	tristate "Support for generic platform NAND driver"
+	depends on HAS_IOMEM
 	help
 	  This implements a generic NAND driver for on-SOC platform
 	  devices. You will need to provide platform-specific functions
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 772ad29..91467bb 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -1,6 +1,7 @@
 menuconfig MTD_ONENAND
 	tristate "OneNAND Device Support"
 	depends on MTD
+	depends on HAS_IOMEM
 	help
 	  This enables support for accessing all type of OneNAND flash
 	  devices. For further information see
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index 3cbfa93..1fe7313 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -67,7 +67,8 @@
 extern int open_file(char *path, int r, int w, int append);
 extern void *open_dir(char *path, int *err_out);
 extern char *read_dir(void *stream, unsigned long long *pos,
-		      unsigned long long *ino_out, int *len_out);
+		      unsigned long long *ino_out, int *len_out,
+		      unsigned int *type_out);
 extern void close_file(void *stream);
 extern int replace_file(int oldfd, int fd);
 extern void close_dir(void *stream);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 588d458..07c516b 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -283,6 +283,7 @@
 	char *name;
 	unsigned long long next, ino;
 	int error, len;
+	unsigned int type;
 
 	name = dentry_name(file->f_path.dentry);
 	if (name == NULL)
@@ -292,9 +293,9 @@
 	if (dir == NULL)
 		return -error;
 	next = file->f_pos;
-	while ((name = read_dir(dir, &next, &ino, &len)) != NULL) {
+	while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) {
 		error = (*filldir)(ent, name, len, file->f_pos,
-				   ino, DT_UNKNOWN);
+				   ino, type);
 		if (error) break;
 		file->f_pos = next;
 	}
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index dd7bc38..a74ad0d 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -98,7 +98,8 @@
 }
 
 char *read_dir(void *stream, unsigned long long *pos,
-	       unsigned long long *ino_out, int *len_out)
+	       unsigned long long *ino_out, int *len_out,
+	       unsigned int *type_out)
 {
 	DIR *dir = stream;
 	struct dirent *ent;
@@ -109,6 +110,7 @@
 		return NULL;
 	*len_out = strlen(ent->d_name);
 	*ino_out = ent->d_ino;
+	*type_out = ent->d_type;
 	*pos = telldir(dir);
 	return ent->d_name;
 }
diff --git a/lib/Kconfig b/lib/Kconfig
index 43359bb..a0e5900 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -29,6 +29,10 @@
 	bool
 	select GENERIC_PCI_IOMAP
 
+config GENERIC_IO
+	boolean
+	default n
+
 config CRC_CCITT
 	tristate "CRC-CCITT functions"
 	help
@@ -277,6 +281,7 @@
 config HAS_IOMEM
 	boolean
 	depends on !NO_IOMEM
+	select GENERIC_IO
 	default y
 
 config HAS_IOPORT