From f97666d21c5c841f23fbbe5c3449cc6f879ba404 Mon Sep 17 00:00:00 2001
From: Mika Laitio <lamikr@cc.jyu.fi>
Date: Sun, 21 May 2006 18:59:07 +0000
Subject: gomunicator: h6300 kernel 2.6.16.16, Tux can now call home.

---
 .../linux-h6300-omap1-2.6.16.16/.mtn2git_empty     |    0
 .../linux/linux-h6300-omap1-2.6.16.16/defconfig    | 1558 ++++++
 .../linux-2.6.16.16.patch                          | 5134 ++++++++++++++++++++
 .../linux-h6300-omap2-2.6.16.16.patch              | 3736 ++++++++++++++
 packages/linux/linux-h6300-omap1_2.6.16.16.bb      |   19 +
 5 files changed, 10447 insertions(+)
 create mode 100644 packages/linux/linux-h6300-omap1-2.6.16.16/.mtn2git_empty
 create mode 100644 packages/linux/linux-h6300-omap1-2.6.16.16/defconfig
 create mode 100644 packages/linux/linux-h6300-omap1-2.6.16.16/linux-2.6.16.16.patch
 create mode 100644 packages/linux/linux-h6300-omap1-2.6.16.16/linux-h6300-omap2-2.6.16.16.patch
 create mode 100644 packages/linux/linux-h6300-omap1_2.6.16.16.bb

(limited to 'packages/linux')

diff --git a/packages/linux/linux-h6300-omap1-2.6.16.16/.mtn2git_empty b/packages/linux/linux-h6300-omap1-2.6.16.16/.mtn2git_empty
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/linux/linux-h6300-omap1-2.6.16.16/defconfig b/packages/linux/linux-h6300-omap1-2.6.16.16/defconfig
new file mode 100644
index 0000000000..ddfa1eb8e6
--- /dev/null
+++ b/packages/linux/linux-h6300-omap1-2.6.16.16/defconfig
@@ -0,0 +1,1558 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.16-omap1-h6300
+# Thu May 18 02:10:05 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=m
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# 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_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP1=y
+# CONFIG_ARCH_OMAP2 is not set
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_BOOT_TAG is not set
+CONFIG_OMAP_MUX=y
+# CONFIG_OMAP_MUX_DEBUG is not set
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
+CONFIG_OMAP_LL_DEBUG_UART1=y
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+# CONFIG_OMAP_LL_DEBUG_UART3 is not set
+CONFIG_OMAP_SERIAL_WAKE=y
+
+#
+# OMAP Core Type
+#
+# CONFIG_ARCH_OMAP730 is not set
+CONFIG_ARCH_OMAP15XX=y
+# CONFIG_ARCH_OMAP16XX is not set
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP_INNOVATOR is not set
+CONFIG_MACH_OMAP_H6300=y
+# CONFIG_MACH_VOICEBLUE is not set
+# CONFIG_MACH_OMAP_PALMTE is not set
+# CONFIG_MACH_AMS_DELTA is not set
+# CONFIG_MACH_OMAP_GENERIC is not set
+
+#
+# OMAP CPU Speed
+#
+# CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER is not set
+CONFIG_OMAP_ARM_168MHZ=y
+CONFIG_OMAP_ARM_150MHZ=y
+CONFIG_OMAP_ARM_120MHZ=y
+CONFIG_OMAP_ARM_60MHZ=y
+CONFIG_OMAP_ARM_30MHZ=y
+CONFIG_OMAP_DSP=y
+CONFIG_OMAP_DSP_MBCMD_VERBOSE=y
+CONFIG_OMAP_DSP_TASK_MULTIOPEN=y
+CONFIG_OMAP_DSP_FBEXPORT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM925T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_WRITETHROUGH=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0 root=/dev/nfs nfsroot=192.168.2.1:/opt/h6300/rootfs,rsize=8192,wsize=8192 ip=192.168.2.2:192.168.2.1:192.168.2.1:255.0.0.0:ipaq:"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+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 is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+# CONFIG_BRIDGE_EBT_BROUTE is not set
+# CONFIG_BRIDGE_EBT_T_FILTER is not set
+# CONFIG_BRIDGE_EBT_T_NAT is not set
+# CONFIG_BRIDGE_EBT_802_3 is not set
+# CONFIG_BRIDGE_EBT_AMONG is not set
+# CONFIG_BRIDGE_EBT_ARP is not set
+# CONFIG_BRIDGE_EBT_IP is not set
+# CONFIG_BRIDGE_EBT_LIMIT is not set
+# CONFIG_BRIDGE_EBT_MARK is not set
+# CONFIG_BRIDGE_EBT_PKTTYPE is not set
+# CONFIG_BRIDGE_EBT_STP is not set
+# CONFIG_BRIDGE_EBT_VLAN is not set
+# CONFIG_BRIDGE_EBT_ARPREPLY is not set
+# CONFIG_BRIDGE_EBT_DNAT is not set
+# CONFIG_BRIDGE_EBT_MARK_T is not set
+# CONFIG_BRIDGE_EBT_REDIRECT is not set
+# CONFIG_BRIDGE_EBT_SNAT is not set
+# CONFIG_BRIDGE_EBT_LOG is not set
+# CONFIG_BRIDGE_EBT_ULOG is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+# CONFIG_BT_SCO is not set
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIUSB is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+# CONFIG_BT_HCIBRF6150 is not set
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_H6300=m
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_AMDSTD_RETRY=1
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLKMTD=m
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+CONFIG_MTD_DOCPROBE_HIGH=y
+CONFIG_MTD_DOCPROBE_55AA=y
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_TOTO is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x0
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH is not set
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_ONENAND_SYNC_READ is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# 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_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=y
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+CONFIG_ATMEL=y
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_ATMEL is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=y
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_TSDEV=y
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_OMAP=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_OMAP=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=y
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_NVRAM=y
+# CONFIG_RTC is not set
+CONFIG_OMAP_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_OMAP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+CONFIG_PCA9535=y
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_TLV320AIC23 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C 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_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 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_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_OMAP=y
+# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set
+# CONFIG_FB_OMAP_LCD_LPH8923 is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_FB_OMAP_DMA_TUNE=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# 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=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_LOGO_LINUX_VGA16=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
+
+#
+# Telephony Support
+#
+CONFIG_PHONE=m
+# CONFIG_PHONE_IXJ is not set
+CONFIG_GSM_H6300=m
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_DETECT is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_OMAP_AIC23 is not set
+CONFIG_SND_OMAP_TSC2101=m
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+CONFIG_USB_ACM=y
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=y
+CONFIG_USB_SERIAL_IPAQ=y
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD 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_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+CONFIG_USB_GADGET_OMAP=y
+CONFIG_USB_OMAP=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+# CONFIG_USB_ETH_RNDIS is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BROKEN_RFD=y
+CONFIG_MMC_BULKTRANSFER=y
+CONFIG_MMC_OMAP=y
+
+#
+# Synchronous Serial Interfaces (SSI)
+#
+CONFIG_OMAP_UWIRE=y
+CONFIG_OMAP_TSC2101=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS 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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=4
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_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_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+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=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# 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_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES 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_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
diff --git a/packages/linux/linux-h6300-omap1-2.6.16.16/linux-2.6.16.16.patch b/packages/linux/linux-h6300-omap1-2.6.16.16/linux-2.6.16.16.patch
new file mode 100644
index 0000000000..ff0aaaac27
--- /dev/null
+++ b/packages/linux/linux-h6300-omap1-2.6.16.16/linux-2.6.16.16.patch
@@ -0,0 +1,5134 @@
+diff -Naur linux-2.6.16/arch/alpha/kernel/setup.c linux-2.6.16.16/arch/alpha/kernel/setup.c
+--- linux-2.6.16/arch/alpha/kernel/setup.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/alpha/kernel/setup.c	2006-05-11 04:56:24.000000000 +0300
+@@ -24,6 +24,7 @@
+ #include <linux/config.h>	/* CONFIG_ALPHA_LCA etc */
+ #include <linux/mc146818rtc.h>
+ #include <linux/console.h>
++#include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
+@@ -477,6 +478,22 @@
+ #undef PFN_PHYS
+ #undef PFN_MAX
+ 
++static int __init
++register_cpus(void)
++{
++	int i;
++
++	for_each_possible_cpu(i) {
++		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
++		if (!p)
++			return -ENOMEM;
++		register_cpu(p, i, NULL);
++	}
++	return 0;
++}
++
++arch_initcall(register_cpus);
++
+ void __init
+ setup_arch(char **cmdline_p)
+ {
+diff -Naur linux-2.6.16/arch/alpha/kernel/smp.c linux-2.6.16.16/arch/alpha/kernel/smp.c
+--- linux-2.6.16/arch/alpha/kernel/smp.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/alpha/kernel/smp.c	2006-05-11 04:56:24.000000000 +0300
+@@ -439,7 +439,7 @@
+ 			if ((cpu->flags & 0x1cc) == 0x1cc) {
+ 				smp_num_probed++;
+ 				/* Assume here that "whami" == index */
+-				cpu_set(i, cpu_possible_map);
++				cpu_set(i, cpu_present_mask);
+ 				cpu->pal_revision = boot_cpu_palrev;
+ 			}
+ 
+@@ -450,9 +450,8 @@
+ 		}
+ 	} else {
+ 		smp_num_probed = 1;
+-		cpu_set(boot_cpuid, cpu_possible_map);
++		cpu_set(boot_cpuid, cpu_present_mask);
+ 	}
+-	cpu_present_mask = cpumask_of_cpu(boot_cpuid);
+ 
+ 	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
+ 	       smp_num_probed, cpu_possible_map.bits[0]);
+@@ -488,9 +487,8 @@
+ smp_prepare_boot_cpu(void)
+ {
+ 	/*
+-	 * Mark the boot cpu (current cpu) as both present and online
++	 * Mark the boot cpu (current cpu) as online
+ 	 */ 
+-	cpu_set(smp_processor_id(), cpu_present_mask);
+ 	cpu_set(smp_processor_id(), cpu_online_map);
+ }
+ 
+diff -Naur linux-2.6.16/arch/alpha/lib/strncpy.S linux-2.6.16.16/arch/alpha/lib/strncpy.S
+--- linux-2.6.16/arch/alpha/lib/strncpy.S	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/alpha/lib/strncpy.S	2006-05-11 04:56:24.000000000 +0300
+@@ -43,8 +43,8 @@
+ 
+ 	.align	4
+ $multiword:
+-	subq	$24, 1, $2	# clear the final bits in the prev word
+-	or	$2, $24, $2
++	subq	$27, 1, $2	# clear the final bits in the prev word
++	or	$2, $27, $2
+ 	zapnot	$1, $2, $1
+ 	subq	$18, 1, $18
+ 
+@@ -70,8 +70,8 @@
+ 	bne	$18, 0b
+ 
+ 1:	ldq_u	$1, 0($16)	# clear the leading bits in the final word
+-	subq	$27, 1, $2
+-	or	$2, $27, $2
++	subq	$24, 1, $2
++	or	$2, $24, $2
+ 
+ 	zap	$1, $2, $1
+ 	stq_u	$1, 0($16)
+diff -Naur linux-2.6.16/arch/i386/kernel/apm.c linux-2.6.16.16/arch/i386/kernel/apm.c
+--- linux-2.6.16/arch/i386/kernel/apm.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/apm.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1081,7 +1081,7 @@
+ 			break;
+ 	}
+ 
+-	if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
++	if (error == APM_NOT_ENGAGED) {
+ 		static int tried;
+ 		int eng_error;
+ 		if (tried++ == 0) {
+diff -Naur linux-2.6.16/arch/i386/kernel/cpu/amd.c linux-2.6.16.16/arch/i386/kernel/cpu/amd.c
+--- linux-2.6.16/arch/i386/kernel/cpu/amd.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/cpu/amd.c	2006-05-11 04:56:24.000000000 +0300
+@@ -207,6 +207,8 @@
+ 		set_bit(X86_FEATURE_K7, c->x86_capability); 
+ 		break;
+ 	}
++	if (c->x86 >= 6)
++		set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
+ 
+ 	display_cacheinfo(c);
+ 
+diff -Naur linux-2.6.16/arch/i386/kernel/cpu/cpufreq/Kconfig linux-2.6.16.16/arch/i386/kernel/cpu/cpufreq/Kconfig
+--- linux-2.6.16/arch/i386/kernel/cpu/cpufreq/Kconfig	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/cpu/cpufreq/Kconfig	2006-05-11 04:56:24.000000000 +0300
+@@ -203,6 +203,7 @@
+ config X86_LONGHAUL
+ 	tristate "VIA Cyrix III Longhaul"
+ 	select CPU_FREQ_TABLE
++	depends on BROKEN
+ 	help
+ 	  This adds the CPUFreq driver for VIA Samuel/CyrixIII, 
+ 	  VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T 
+diff -Naur linux-2.6.16/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux-2.6.16.16/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+--- linux-2.6.16/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2006-05-11 04:56:24.000000000 +0300
+@@ -244,7 +244,7 @@
+ 	for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ 		if ((i<2) && (has_N44_O17_errata[policy->cpu]))
+ 			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+-		else if (has_N60_errata[policy->cpu] && p4clockmod_table[i].frequency < 2000000)
++		else if (has_N60_errata[policy->cpu] && ((stock_freq * i)/8) < 2000000)
+ 			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+ 		else
+ 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
+diff -Naur linux-2.6.16/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c linux-2.6.16.16/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+--- linux-2.6.16/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c	2006-05-11 04:56:24.000000000 +0300
+@@ -75,7 +75,9 @@
+ 	__asm__ __volatile__(
+ 		"out %%al, (%%dx)\n"
+ 		: "=D" (result)
+-		: "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic)
++		: "a" (command), "b" (function), "c" (0), "d" (smi_port),
++			"D" (0), "S" (magic)
++		: "memory"
+ 	);
+ 
+ 	dprintk("result is %x\n", result);
+diff -Naur linux-2.6.16/arch/i386/kernel/dmi_scan.c linux-2.6.16.16/arch/i386/kernel/dmi_scan.c
+--- linux-2.6.16/arch/i386/kernel/dmi_scan.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/dmi_scan.c	2006-05-11 04:56:24.000000000 +0300
+@@ -106,7 +106,7 @@
+ 	struct dmi_device *dev;
+ 
+ 	for (i = 0; i < count; i++) {
+-		char *d = ((char *) dm) + (i * 2);
++		char *d = (char *)(dm + 1) + (i * 2);
+ 
+ 		/* Skip disabled device */
+ 		if ((*d & 0x80) == 0)
+diff -Naur linux-2.6.16/arch/i386/kernel/vm86.c linux-2.6.16.16/arch/i386/kernel/vm86.c
+--- linux-2.6.16/arch/i386/kernel/vm86.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/i386/kernel/vm86.c	2006-05-11 04:56:24.000000000 +0300
+@@ -43,6 +43,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/highmem.h>
+ #include <linux/ptrace.h>
++#include <linux/audit.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -252,6 +253,7 @@
+ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
+ {
+ 	struct tss_struct *tss;
++	long eax;
+ /*
+  * make sure the vm86() system call doesn't try to do anything silly
+  */
+@@ -305,13 +307,19 @@
+ 	tsk->thread.screen_bitmap = info->screen_bitmap;
+ 	if (info->flags & VM86_SCREEN_BITMAP)
+ 		mark_screen_rdonly(tsk->mm);
++	__asm__ __volatile__("xorl %eax,%eax; movl %eax,%fs; movl %eax,%gs\n\t");
++	__asm__ __volatile__("movl %%eax, %0\n" :"=r"(eax));
++
++	/*call audit_syscall_exit since we do not exit via the normal paths */
++	if (unlikely(current->audit_context))
++		audit_syscall_exit(current, AUDITSC_RESULT(eax), eax);
++
+ 	__asm__ __volatile__(
+-		"xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs\n\t"
+ 		"movl %0,%%esp\n\t"
+ 		"movl %1,%%ebp\n\t"
+ 		"jmp resume_userspace"
+ 		: /* no outputs */
+-		:"r" (&info->regs), "r" (task_thread_info(tsk)) : "ax");
++		:"r" (&info->regs), "r" (task_thread_info(tsk)));
+ 	/* we never return here */
+ }
+ 
+diff -Naur linux-2.6.16/arch/m32r/kernel/m32r_ksyms.c linux-2.6.16.16/arch/m32r/kernel/m32r_ksyms.c
+--- linux-2.6.16/arch/m32r/kernel/m32r_ksyms.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/m32r/kernel/m32r_ksyms.c	2006-05-11 04:56:24.000000000 +0300
+@@ -38,10 +38,6 @@
+ EXPORT_SYMBOL(__delay);
+ EXPORT_SYMBOL(__const_udelay);
+ 
+-EXPORT_SYMBOL(__get_user_1);
+-EXPORT_SYMBOL(__get_user_2);
+-EXPORT_SYMBOL(__get_user_4);
+-
+ EXPORT_SYMBOL(strpbrk);
+ EXPORT_SYMBOL(strstr);
+ 
+diff -Naur linux-2.6.16/arch/m32r/kernel/setup.c linux-2.6.16.16/arch/m32r/kernel/setup.c
+--- linux-2.6.16/arch/m32r/kernel/setup.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/m32r/kernel/setup.c	2006-05-11 04:56:24.000000000 +0300
+@@ -9,6 +9,7 @@
+ 
+ #include <linux/config.h>
+ #include <linux/init.h>
++#include <linux/kernel.h>
+ #include <linux/stddef.h>
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+@@ -218,8 +219,6 @@
+ extern unsigned long setup_memory(void);
+ #endif	/* CONFIG_DISCONTIGMEM */
+ 
+-#define M32R_PCC_PCATCR	0x00ef7014	/* will move to m32r.h */
+-
+ void __init setup_arch(char **cmdline_p)
+ {
+ 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+@@ -268,15 +267,14 @@
+ 	paging_init();
+ }
+ 
+-static struct cpu cpu[NR_CPUS];
++static struct cpu cpu_devices[NR_CPUS];
+ 
+ static int __init topology_init(void)
+ {
+-	int cpu_id;
++	int i;
+ 
+-	for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+-		if (cpu_possible(cpu_id))
+-			register_cpu(&cpu[cpu_id], cpu_id, NULL);
++	for_each_present_cpu(i)
++		register_cpu(&cpu_devices[i], i, NULL);
+ 
+ 	return 0;
+ }
+diff -Naur linux-2.6.16/arch/m32r/kernel/smpboot.c linux-2.6.16.16/arch/m32r/kernel/smpboot.c
+--- linux-2.6.16/arch/m32r/kernel/smpboot.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/m32r/kernel/smpboot.c	2006-05-11 04:56:24.000000000 +0300
+@@ -39,8 +39,10 @@
+  *		Martin J. Bligh	: 	Added support for multi-quad systems
+  */
+ 
++#include <linux/module.h>
+ #include <linux/config.h>
+ #include <linux/init.h>
++#include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/smp_lock.h>
+ #include <linux/irq.h>
+@@ -72,11 +74,15 @@
+ 
+ /* Bitmask of currently online CPUs */
+ cpumask_t cpu_online_map;
++EXPORT_SYMBOL(cpu_online_map);
+ 
+ cpumask_t cpu_bootout_map;
+ cpumask_t cpu_bootin_map;
+-cpumask_t cpu_callout_map;
+ static cpumask_t cpu_callin_map;
++cpumask_t cpu_callout_map;
++EXPORT_SYMBOL(cpu_callout_map);
++cpumask_t cpu_possible_map = CPU_MASK_ALL;
++EXPORT_SYMBOL(cpu_possible_map);
+ 
+ /* Per CPU bogomips and other parameters */
+ struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
+@@ -110,7 +116,6 @@
+ 
+ void smp_prepare_boot_cpu(void);
+ void smp_prepare_cpus(unsigned int);
+-static void smp_tune_scheduling(void);
+ static void init_ipi_lock(void);
+ static void do_boot_cpu(int);
+ int __cpu_up(unsigned int);
+@@ -177,6 +182,9 @@
+ 	}
+ 	for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
+ 		physid_set(phys_id, phys_cpu_present_map);
++#ifndef CONFIG_HOTPLUG_CPU
++	cpu_present_map = cpu_possible_map;
++#endif
+ 
+ 	show_mp_info(nr_cpu);
+ 
+@@ -186,7 +194,6 @@
+ 	 * Setup boot CPU information
+ 	 */
+ 	smp_store_cpu_info(0); /* Final full version of the data */
+-	smp_tune_scheduling();
+ 
+ 	/*
+ 	 * If SMP should be disabled, then really disable it!
+@@ -230,11 +237,6 @@
+ 	Dprintk("Boot done.\n");
+ }
+ 
+-static void __init smp_tune_scheduling(void)
+-{
+-	/* Nothing to do. */
+-}
+-
+ /*
+  * init_ipi_lock : Initialize IPI locks.
+  */
+@@ -629,4 +631,3 @@
+ 	physid_2_cpu[phys_id] = -1;
+ 	cpu_2_physid[cpu_id] = -1;
+ }
+-
+diff -Naur linux-2.6.16/arch/m32r/lib/getuser.S linux-2.6.16.16/arch/m32r/lib/getuser.S
+--- linux-2.6.16/arch/m32r/lib/getuser.S	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/m32r/lib/getuser.S	1970-01-01 02:00:00.000000000 +0200
+@@ -1,88 +0,0 @@
+-/*
+- * __get_user functions.
+- *
+- * (C) Copyright 2001 Hirokazu Takata
+- *
+- * These functions have a non-standard call interface
+- * to make them more efficient, especially as they
+- * return an error value in addition to the "real"
+- * return value.
+- */
+-
+-#include <linux/config.h>
+-
+-/*
+- * __get_user_X
+- *
+- * Inputs:	r0 contains the address
+- *
+- * Outputs:	r0 is error code (0 or -EFAULT)
+- *		r1 contains zero-extended value
+- *
+- * These functions should not modify any other registers,
+- * as they get called from within inline assembly.
+- */
+-
+-#ifdef CONFIG_ISA_DUAL_ISSUE
+-
+-	.text
+-	.balign 4
+-	.globl __get_user_1
+-__get_user_1:
+-1:	ldub	r1, @r0		    ||	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __get_user_2
+-__get_user_2:
+-2:	lduh	r1, @r0		    ||	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __get_user_4
+-__get_user_4:
+-3:	ld	r1, @r0		    ||	ldi	r0, #0
+-	jmp	r14
+-
+-bad_get_user:
+-	ldi	r1, #0		    ||	ldi	r0, #-14
+-	jmp	r14
+-
+-#else /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-	.text
+-	.balign 4
+-	.globl __get_user_1
+-__get_user_1:
+-1:	ldub	r1, @r0
+-	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __get_user_2
+-__get_user_2:
+-2:	lduh	r1, @r0
+-	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __get_user_4
+-__get_user_4:
+-3:	ld	r1, @r0
+-	ldi	r0, #0
+-	jmp	r14
+-
+-bad_get_user:
+-	ldi	r1, #0
+-	ldi	r0, #-14
+-	jmp	r14
+-
+-#endif /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-.section __ex_table,"a"
+-	.long 1b,bad_get_user
+-	.long 2b,bad_get_user
+-	.long 3b,bad_get_user
+-.previous
+-
+-	.end
+diff -Naur linux-2.6.16/arch/m32r/lib/Makefile linux-2.6.16.16/arch/m32r/lib/Makefile
+--- linux-2.6.16/arch/m32r/lib/Makefile	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/m32r/lib/Makefile	2006-05-11 04:56:24.000000000 +0300
+@@ -2,6 +2,6 @@
+ # Makefile for M32R-specific library files..
+ #
+ 
+-lib-y  := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
+-	  putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
++lib-y  := checksum.o ashxdi3.o memset.o memcpy.o \
++	  delay.o strlen.o usercopy.o csum_partial_copy.o
+ 
+diff -Naur linux-2.6.16/arch/m32r/lib/putuser.S linux-2.6.16.16/arch/m32r/lib/putuser.S
+--- linux-2.6.16/arch/m32r/lib/putuser.S	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/m32r/lib/putuser.S	1970-01-01 02:00:00.000000000 +0200
+@@ -1,84 +0,0 @@
+-/*
+- * __put_user functions.
+- *
+- * (C) Copyright 1998 Linus Torvalds
+- * (C) Copyright 2001 Hirokazu Takata
+- *
+- * These functions have a non-standard call interface
+- * to make them more efficient.
+- */
+-
+-#include <linux/config.h>
+-
+-/*
+- * __put_user_X
+- *
+- * Inputs:	r0 contains the address
+- *		r1 contains the value
+- *
+- * Outputs:	r0 is error code (0 or -EFAULT)
+- *		r1 is corrupted (will contain "current_task").
+- *
+- * These functions should not modify any other registers,
+- * as they get called from within inline assembly.
+- */
+-
+-#ifdef CONFIG_ISA_DUAL_ISSUE
+-
+-	.text
+-	.balign 4
+-	.globl __put_user_1
+-__put_user_1:
+-1:	stb	r1, @r0		    ||	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __put_user_2
+-__put_user_2:
+-2:	sth	r1, @r0		    ||	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __put_user_4
+-__put_user_4:
+-3:	st	r1, @r0		    ||	ldi	r0, #0
+-	jmp	r14
+-
+-bad_put_user:
+-	ldi	r0, #-14	    ||	jmp	r14
+-
+-#else /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-	.text
+-	.balign 4
+-	.globl __put_user_1
+-__put_user_1:
+-1:	stb	r1, @r0
+-	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __put_user_2
+-__put_user_2:
+-2:	sth	r1, @r0
+-	ldi	r0, #0
+-	jmp	r14
+-
+-	.balign 4
+-	.globl __put_user_4
+-__put_user_4:
+-3:	st	r1, @r0
+-	ldi	r0, #0
+-	jmp	r14
+-
+-bad_put_user:
+-	ldi	r0, #-14
+-	jmp	r14
+-
+-#endif /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-.section __ex_table,"a"
+-	.long 1b,bad_put_user
+-	.long 2b,bad_put_user
+-	.long 3b,bad_put_user
+-.previous
+diff -Naur linux-2.6.16/arch/mips/kernel/branch.c linux-2.6.16.16/arch/mips/kernel/branch.c
+--- linux-2.6.16/arch/mips/kernel/branch.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/mips/kernel/branch.c	2006-05-11 04:56:24.000000000 +0300
+@@ -184,7 +184,7 @@
+ 		bit = (insn.i_format.rt >> 2);
+ 		bit += (bit != 0);
+ 		bit += 23;
+-		switch (insn.i_format.rt) {
++		switch (insn.i_format.rt & 3) {
+ 		case 0:	/* bc1f */
+ 		case 2:	/* bc1fl */
+ 			if (~fcr31 & (1 << bit))
+diff -Naur linux-2.6.16/arch/mips/mm/c-r4k.c linux-2.6.16.16/arch/mips/mm/c-r4k.c
+--- linux-2.6.16/arch/mips/mm/c-r4k.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/mips/mm/c-r4k.c	2006-05-11 04:56:24.000000000 +0300
+@@ -154,7 +154,8 @@
+ 
+ static inline void tx49_blast_icache32_page_indexed(unsigned long page)
+ {
+-	unsigned long start = page;
++	unsigned long indexmask = current_cpu_data.icache.waysize - 1;
++	unsigned long start = INDEX_BASE + (page & indexmask);
+ 	unsigned long end = start + PAGE_SIZE;
+ 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+ 	unsigned long ws_end = current_cpu_data.icache.ways <<
+diff -Naur linux-2.6.16/arch/powerpc/kernel/pci_64.c linux-2.6.16.16/arch/powerpc/kernel/pci_64.c
+--- linux-2.6.16/arch/powerpc/kernel/pci_64.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/powerpc/kernel/pci_64.c	2006-05-11 04:56:24.000000000 +0300
+@@ -78,6 +78,7 @@
+ 
+ /* Cached ISA bridge dev. */
+ struct pci_dev *ppc64_isabridge_dev = NULL;
++EXPORT_SYMBOL_GPL(ppc64_isabridge_dev);
+ 
+ static void fixup_broken_pcnet32(struct pci_dev* dev)
+ {
+diff -Naur linux-2.6.16/arch/powerpc/kernel/setup_64.c linux-2.6.16.16/arch/powerpc/kernel/setup_64.c
+--- linux-2.6.16/arch/powerpc/kernel/setup_64.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/powerpc/kernel/setup_64.c	2006-05-11 04:56:24.000000000 +0300
+@@ -256,12 +256,10 @@
+ 	/*
+ 	 * Initialize stab / SLB management except on iSeries
+ 	 */
+-	if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
+-		if (cpu_has_feature(CPU_FTR_SLB))
+-			slb_initialize();
+-		else
+-			stab_initialize(lpaca->stab_real);
+-	}
++	if (cpu_has_feature(CPU_FTR_SLB))
++		slb_initialize();
++	else if (!firmware_has_feature(FW_FEATURE_ISERIES))
++		stab_initialize(lpaca->stab_real);
+ 
+ 	DBG(" <- early_setup()\n");
+ }
+diff -Naur linux-2.6.16/arch/powerpc/kernel/signal_64.c linux-2.6.16.16/arch/powerpc/kernel/signal_64.c
+--- linux-2.6.16/arch/powerpc/kernel/signal_64.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/powerpc/kernel/signal_64.c	2006-05-11 04:56:24.000000000 +0300
+@@ -213,7 +213,7 @@
+         /* Default to using normal stack */
+         newsp = regs->gpr[1];
+ 
+-	if (ka->sa.sa_flags & SA_ONSTACK) {
++	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
+ 		if (! on_sig_stack(regs->gpr[1]))
+ 			newsp = (current->sas_ss_sp + current->sas_ss_size);
+ 	}
+diff -Naur linux-2.6.16/arch/x86_64/ia32/Makefile linux-2.6.16.16/arch/x86_64/ia32/Makefile
+--- linux-2.6.16/arch/x86_64/ia32/Makefile	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/x86_64/ia32/Makefile	2006-05-11 04:56:24.000000000 +0300
+@@ -27,5 +27,5 @@
+ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+ 	$(call if_changed,syscall)
+ 
+-AFLAGS_vsyscall-sysenter.o = -m32
+-AFLAGS_vsyscall-syscall.o = -m32
++AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
++AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
+diff -Naur linux-2.6.16/arch/x86_64/kernel/entry.S linux-2.6.16.16/arch/x86_64/kernel/entry.S
+--- linux-2.6.16/arch/x86_64/kernel/entry.S	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/x86_64/kernel/entry.S	2006-05-11 04:56:24.000000000 +0300
+@@ -180,6 +180,10 @@
+  *
+  * XXX	if we had a free scratch register we could save the RSP into the stack frame
+  *      and report it properly in ps. Unfortunately we haven't.
++ *
++ * When user can change the frames always force IRET. That is because
++ * it deals with uncanonical addresses better. SYSRET has trouble
++ * with them due to bugs in both AMD and Intel CPUs.
+  */ 			 		
+ 
+ ENTRY(system_call)
+@@ -254,7 +258,10 @@
+ 	xorl %esi,%esi # oldset -> arg2
+ 	call ptregscall_common
+ 1:	movl $_TIF_NEED_RESCHED,%edi
+-	jmp sysret_check
++	/* Use IRET because user could have changed frame. This
++	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
++	cli
++	jmp int_with_check
+ 	
+ badsys:
+ 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+@@ -280,7 +287,8 @@
+ 	call syscall_trace_leave
+ 	RESTORE_TOP_OF_STACK %rbx
+ 	RESTORE_REST
+-	jmp ret_from_sys_call
++	/* Use IRET because user could have changed frame */
++	jmp int_ret_from_sys_call
+ 	CFI_ENDPROC
+ 		
+ /* 
+@@ -408,25 +416,9 @@
+ 	CFI_ADJUST_CFA_OFFSET -8
+ 	CFI_REGISTER rip, r11
+ 	SAVE_REST
+-	movq %r11, %r15
+-	CFI_REGISTER rip, r15
+ 	FIXUP_TOP_OF_STACK %r11
+ 	call sys_execve
+-	GET_THREAD_INFO(%rcx)
+-	bt $TIF_IA32,threadinfo_flags(%rcx)
+-	CFI_REMEMBER_STATE
+-	jc exec_32bit
+ 	RESTORE_TOP_OF_STACK %r11
+-	movq %r15, %r11
+-	CFI_REGISTER rip, r11
+-	RESTORE_REST
+-	pushq %r11
+-	CFI_ADJUST_CFA_OFFSET 8
+-	CFI_REL_OFFSET rip, 0
+-	ret
+-
+-exec_32bit:
+-	CFI_RESTORE_STATE
+ 	movq %rax,RAX(%rsp)
+ 	RESTORE_REST
+ 	jmp int_ret_from_sys_call
+diff -Naur linux-2.6.16/arch/x86_64/kernel/pci-gart.c linux-2.6.16.16/arch/x86_64/kernel/pci-gart.c
+--- linux-2.6.16/arch/x86_64/kernel/pci-gart.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/x86_64/kernel/pci-gart.c	2006-05-11 04:56:24.000000000 +0300
+@@ -114,10 +114,6 @@
+ static void free_iommu(unsigned long offset, int size)
+ { 
+ 	unsigned long flags;
+-	if (size == 1) { 
+-		clear_bit(offset, iommu_gart_bitmap); 
+-		return;
+-	}
+ 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
+ 	__clear_bit_string(iommu_gart_bitmap, offset, size);
+ 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
+diff -Naur linux-2.6.16/arch/x86_64/kernel/process.c linux-2.6.16.16/arch/x86_64/kernel/process.c
+--- linux-2.6.16/arch/x86_64/kernel/process.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/x86_64/kernel/process.c	2006-05-11 04:56:24.000000000 +0300
+@@ -527,8 +527,6 @@
+ 	int cpu = smp_processor_id();  
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ 
+-	unlazy_fpu(prev_p);
+-
+ 	/*
+ 	 * Reload esp0, LDT and the page table pointer:
+ 	 */
+@@ -591,6 +589,12 @@
+ 	prev->userrsp = read_pda(oldrsp); 
+ 	write_pda(oldrsp, next->userrsp); 
+ 	write_pda(pcurrent, next_p); 
++
++ 	/* This must be here to ensure both math_state_restore() and
++	   kernel_fpu_begin() work consistently.
++	   And the AMD workaround requires it to be after DS reload. */
++	unlazy_fpu(prev_p);
++
+ 	write_pda(kernelstack,
+ 		  task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
+ 
+diff -Naur linux-2.6.16/arch/x86_64/kernel/setup.c linux-2.6.16.16/arch/x86_64/kernel/setup.c
+--- linux-2.6.16/arch/x86_64/kernel/setup.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/arch/x86_64/kernel/setup.c	2006-05-11 04:56:24.000000000 +0300
+@@ -909,6 +909,10 @@
+ 	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
+ 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+ 
++	/* Enable workaround for FXSAVE leak */
++	if (c->x86 >= 6)
++		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
++
+ 	r = get_model_name(c);
+ 	if (!r) { 
+ 		switch (c->x86) { 
+diff -Naur linux-2.6.16/block/genhd.c linux-2.6.16.16/block/genhd.c
+--- linux-2.6.16/block/genhd.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/block/genhd.c	2006-05-11 04:56:24.000000000 +0300
+@@ -16,8 +16,6 @@
+ #include <linux/kobj_map.h>
+ #include <linux/buffer_head.h>
+ 
+-#define MAX_PROBE_HASH 255	/* random */
+-
+ static struct subsystem block_subsys;
+ 
+ static DECLARE_MUTEX(block_subsys_sem);
+@@ -30,108 +28,29 @@
+ 	struct blk_major_name *next;
+ 	int major;
+ 	char name[16];
+-} *major_names[MAX_PROBE_HASH];
++} *major_names[BLKDEV_MAJOR_HASH_SIZE];
+ 
+ /* index in the above - for now: assume no multimajor ranges */
+ static inline int major_to_index(int major)
+ {
+-	return major % MAX_PROBE_HASH;
+-}
+-
+-struct blkdev_info {
+-        int index;
+-        struct blk_major_name *bd;
+-};
+-
+-/*
+- * iterate over a list of blkdev_info structures.  allows
+- * the major_names array to be iterated over from outside this file
+- * must be called with the block_subsys_sem held
+- */
+-void *get_next_blkdev(void *dev)
+-{
+-        struct blkdev_info *info;
+-
+-        if (dev == NULL) {
+-                info = kmalloc(sizeof(*info), GFP_KERNEL);
+-                if (!info)
+-                        goto out;
+-                info->index=0;
+-                info->bd = major_names[info->index];
+-                if (info->bd)
+-                        goto out;
+-        } else {
+-                info = dev;
+-        }
+-
+-        while (info->index < ARRAY_SIZE(major_names)) {
+-                if (info->bd)
+-                        info->bd = info->bd->next;
+-                if (info->bd)
+-                        goto out;
+-                /*
+-                 * No devices on this chain, move to the next
+-                 */
+-                info->index++;
+-                info->bd = (info->index < ARRAY_SIZE(major_names)) ?
+-			major_names[info->index] : NULL;
+-                if (info->bd)
+-                        goto out;
+-        }
+-
+-out:
+-        return info;
+-}
+-
+-void *acquire_blkdev_list(void)
+-{
+-        down(&block_subsys_sem);
+-        return get_next_blkdev(NULL);
+-}
+-
+-void release_blkdev_list(void *dev)
+-{
+-        up(&block_subsys_sem);
+-        kfree(dev);
++	return major % BLKDEV_MAJOR_HASH_SIZE;
+ }
+ 
++#ifdef CONFIG_PROC_FS
+ 
+-/*
+- * Count the number of records in the blkdev_list.
+- * must be called with the block_subsys_sem held
+- */
+-int count_blkdev_list(void)
++void blkdev_show(struct seq_file *f, off_t offset)
+ {
+-	struct blk_major_name *n;
+-	int i, count;
+-
+-	count = 0;
++	struct blk_major_name *dp;
+ 
+-	for (i = 0; i < ARRAY_SIZE(major_names); i++) {
+-		for (n = major_names[i]; n; n = n->next)
+-				count++;
++	if (offset < BLKDEV_MAJOR_HASH_SIZE) {
++		down(&block_subsys_sem);
++		for (dp = major_names[offset]; dp; dp = dp->next)
++			seq_printf(f, "%3d %s\n", dp->major, dp->name);
++		up(&block_subsys_sem);
+ 	}
+-
+-	return count;
+-}
+-
+-/*
+- * extract the major and name values from a blkdev_info struct
+- * passed in as a void to *dev.  Must be called with
+- * block_subsys_sem held
+- */
+-int get_blkdev_info(void *dev, int *major, char **name)
+-{
+-        struct blkdev_info *info = dev;
+-
+-        if (info->bd == NULL)
+-                return 1;
+-
+-        *major = info->bd->major;
+-        *name = info->bd->name;
+-        return 0;
+ }
+ 
++#endif /* CONFIG_PROC_FS */
+ 
+ int register_blkdev(unsigned int major, const char *name)
+ {
+diff -Naur linux-2.6.16/Documentation/dvb/get_dvb_firmware linux-2.6.16.16/Documentation/dvb/get_dvb_firmware
+--- linux-2.6.16/Documentation/dvb/get_dvb_firmware	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/Documentation/dvb/get_dvb_firmware	2006-05-11 04:56:24.000000000 +0300
+@@ -240,9 +240,9 @@
+ }
+ 
+ sub nxt2002 {
+-    my $sourcefile = "Broadband4PC_4_2_11.zip";
++    my $sourcefile = "Technisat_DVB-PC_4_4_COMPACT.zip";
+     my $url = "http://www.bbti.us/download/windows/$sourcefile";
+-    my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a";
++    my $hash = "476befae8c7c1bb9648954060b1eec1f";
+     my $outfile = "dvb-fe-nxt2002.fw";
+     my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+ 
+@@ -250,8 +250,8 @@
+ 
+     wgetfile($sourcefile, $url);
+     unzip($sourcefile, $tmpdir);
+-    verify("$tmpdir/SkyNETU.sys", $hash);
+-    extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile);
++    verify("$tmpdir/SkyNET.sys", $hash);
++    extract("$tmpdir/SkyNET.sys", 331624, 5908, $outfile);
+ 
+     $outfile;
+ }
+diff -Naur linux-2.6.16/drivers/base/cpu.c linux-2.6.16.16/drivers/base/cpu.c
+--- linux-2.6.16/drivers/base/cpu.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/base/cpu.c	2006-05-11 04:56:24.000000000 +0300
+@@ -141,7 +141,7 @@
+ 	return error;
+ }
+ 
+-struct sys_device *get_cpu_sysdev(int cpu)
++struct sys_device *get_cpu_sysdev(unsigned cpu)
+ {
+ 	if (cpu < NR_CPUS)
+ 		return cpu_sys_devices[cpu];
+diff -Naur linux-2.6.16/drivers/base/firmware_class.c linux-2.6.16.16/drivers/base/firmware_class.c
+--- linux-2.6.16/drivers/base/firmware_class.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/base/firmware_class.c	2006-05-11 04:56:24.000000000 +0300
+@@ -211,18 +211,20 @@
+ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
+ {
+ 	u8 *new_data;
++	int new_size = fw_priv->alloc_size;
+ 
+ 	if (min_size <= fw_priv->alloc_size)
+ 		return 0;
+ 
+-	new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE);
++	new_size = ALIGN(min_size, PAGE_SIZE);
++	new_data = vmalloc(new_size);
+ 	if (!new_data) {
+ 		printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
+ 		/* Make sure that we don't keep incomplete data */
+ 		fw_load_abort(fw_priv);
+ 		return -ENOMEM;
+ 	}
+-	fw_priv->alloc_size += PAGE_SIZE;
++	fw_priv->alloc_size = new_size;
+ 	if (fw_priv->fw->data) {
+ 		memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size);
+ 		vfree(fw_priv->fw->data);
+diff -Naur linux-2.6.16/drivers/base/node.c linux-2.6.16.16/drivers/base/node.c
+--- linux-2.6.16/drivers/base/node.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/base/node.c	2006-05-11 04:56:24.000000000 +0300
+@@ -106,7 +106,7 @@
+ 	other_node = 0;
+ 	for (i = 0; i < MAX_NR_ZONES; i++) {
+ 		struct zone *z = &pg->node_zones[i];
+-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
++		for_each_online_cpu(cpu) {
+ 			struct per_cpu_pageset *ps = zone_pcp(z,cpu);
+ 			numa_hit += ps->numa_hit;
+ 			numa_miss += ps->numa_miss;
+diff -Naur linux-2.6.16/drivers/block/cciss.c linux-2.6.16.16/drivers/block/cciss.c
+--- linux-2.6.16/drivers/block/cciss.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/block/cciss.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1181,6 +1181,53 @@
+         return 0;
+ }
+ 
++static inline void complete_buffers(struct bio *bio, int status)
++{
++	while (bio) {
++		struct bio *xbh = bio->bi_next;
++		int nr_sectors = bio_sectors(bio);
++
++		bio->bi_next = NULL;
++		blk_finished_io(len);
++		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
++		bio = xbh;
++	}
++
++}
++
++static void cciss_softirq_done(struct request *rq)
++{
++	CommandList_struct *cmd = rq->completion_data;
++	ctlr_info_t *h = hba[cmd->ctlr];
++	unsigned long flags;
++	u64bit temp64;
++	int i, ddir;
++
++	if (cmd->Request.Type.Direction == XFER_READ)
++		ddir = PCI_DMA_FROMDEVICE;
++	else
++		ddir = PCI_DMA_TODEVICE;
++
++	/* command did not need to be retried */
++	/* unmap the DMA mapping for all the scatter gather elements */
++	for(i=0; i<cmd->Header.SGList; i++) {
++		temp64.val32.lower = cmd->SG[i].Addr.lower;
++		temp64.val32.upper = cmd->SG[i].Addr.upper;
++		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
++	}
++
++	complete_buffers(rq->bio, rq->errors);
++
++#ifdef CCISS_DEBUG
++	printk("Done with %p\n", rq);
++#endif /* CCISS_DEBUG */
++
++	spin_lock_irqsave(&h->lock, flags);
++	end_that_request_last(rq, rq->errors);
++	cmd_free(h, cmd,1);
++	spin_unlock_irqrestore(&h->lock, flags);
++}
++
+ /* This function will check the usage_count of the drive to be updated/added.
+  * If the usage_count is zero then the drive information will be updated and
+  * the disk will be re-registered with the kernel.  If not then it will be
+@@ -1249,6 +1296,8 @@
+ 
+ 		blk_queue_max_sectors(disk->queue, 512);
+ 
++		blk_queue_softirq_done(disk->queue, cciss_softirq_done);
++
+ 		disk->queue->queuedata = hba[ctlr];
+ 
+ 		blk_queue_hardsect_size(disk->queue,
+@@ -2148,20 +2197,6 @@
+ 		addQ (&(h->cmpQ), c); 
+ 	}
+ }
+-
+-static inline void complete_buffers(struct bio *bio, int status)
+-{
+-	while (bio) {
+-		struct bio *xbh = bio->bi_next; 
+-		int nr_sectors = bio_sectors(bio);
+-
+-		bio->bi_next = NULL; 
+-		blk_finished_io(len);
+-		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+-		bio = xbh;
+-	}
+-
+-} 
+ /* Assumes that CCISS_LOCK(h->ctlr) is held. */
+ /* Zeros out the error record and then resends the command back */
+ /* to the controller */
+@@ -2179,39 +2214,6 @@
+ 	start_io(h);
+ }
+ 
+-static void cciss_softirq_done(struct request *rq)
+-{
+-	CommandList_struct *cmd = rq->completion_data;
+-	ctlr_info_t *h = hba[cmd->ctlr];
+-	unsigned long flags;
+-	u64bit temp64;
+-	int i, ddir;
+-
+-	if (cmd->Request.Type.Direction == XFER_READ)
+-		ddir = PCI_DMA_FROMDEVICE;
+-	else
+-		ddir = PCI_DMA_TODEVICE;
+-
+-	/* command did not need to be retried */
+-	/* unmap the DMA mapping for all the scatter gather elements */
+-	for(i=0; i<cmd->Header.SGList; i++) {
+-		temp64.val32.lower = cmd->SG[i].Addr.lower;
+-		temp64.val32.upper = cmd->SG[i].Addr.upper;
+-		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+-	}
+-
+-	complete_buffers(rq->bio, rq->errors);
+-
+-#ifdef CCISS_DEBUG
+-	printk("Done with %p\n", rq);
+-#endif /* CCISS_DEBUG */ 
+-
+-	spin_lock_irqsave(&h->lock, flags);
+-	end_that_request_last(rq, rq->errors);
+-	cmd_free(h, cmd,1);
+-	spin_unlock_irqrestore(&h->lock, flags);
+-}
+-
+ /* checks the status of the job and calls complete buffers to mark all 
+  * buffers for the completed job. Note that this function does not need
+  * to hold the hba/queue lock.
+@@ -3269,8 +3271,8 @@
+ 	unregister_blkdev(hba[i]->major, hba[i]->devname);
+ clean1:
+ 	release_io_mem(hba[i]);
+-	free_hba(i);
+ 	hba[i]->busy_initializing = 0;
++	free_hba(i);
+ 	return(-1);
+ }
+ 
+diff -Naur linux-2.6.16/drivers/char/agp/efficeon-agp.c linux-2.6.16.16/drivers/char/agp/efficeon-agp.c
+--- linux-2.6.16/drivers/char/agp/efficeon-agp.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/agp/efficeon-agp.c	2006-05-11 04:56:24.000000000 +0300
+@@ -64,6 +64,12 @@
+ 	{.mask = 0x00000001, .type = 0}
+ };
+ 
++/* This function does the same thing as mask_memory() for this chipset... */
++static inline unsigned long efficeon_mask_memory(unsigned long addr)
++{
++	return addr | 0x00000001;
++}
++
+ static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
+ {
+ 	{256, 65536, 0},
+@@ -251,7 +257,7 @@
+ 	last_page = NULL;
+ 	for (i = 0; i < count; i++) {
+ 		int index = pg_start + i;
+-		unsigned long insert = mem->memory[i];
++		unsigned long insert = efficeon_mask_memory(mem->memory[i]);
+ 
+ 		page = (unsigned int *) efficeon_private.l1_table[index >> 10];
+ 
+diff -Naur linux-2.6.16/drivers/char/cs5535_gpio.c linux-2.6.16.16/drivers/char/cs5535_gpio.c
+--- linux-2.6.16/drivers/char/cs5535_gpio.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/cs5535_gpio.c	2006-05-11 04:56:24.000000000 +0300
+@@ -241,9 +241,10 @@
+ static void __exit cs5535_gpio_cleanup(void)
+ {
+ 	dev_t dev_id = MKDEV(major, 0);
++
++	cdev_del(&cs5535_gpio_cdev);
+ 	unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
+-	if (gpio_base != 0)
+-		release_region(gpio_base, CS5535_GPIO_SIZE);
++	release_region(gpio_base, CS5535_GPIO_SIZE);
+ }
+ 
+ module_init(cs5535_gpio_init);
+diff -Naur linux-2.6.16/drivers/char/ipmi/ipmi_bt_sm.c linux-2.6.16.16/drivers/char/ipmi/ipmi_bt_sm.c
+--- linux-2.6.16/drivers/char/ipmi/ipmi_bt_sm.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/ipmi/ipmi_bt_sm.c	2006-05-11 04:56:24.000000000 +0300
+@@ -165,7 +165,7 @@
+ {
+ 	unsigned int i;
+ 
+-	if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
++	if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
+ 	       return -1;
+ 
+ 	if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
+diff -Naur linux-2.6.16/drivers/char/Kconfig linux-2.6.16.16/drivers/char/Kconfig
+--- linux-2.6.16/drivers/char/Kconfig	2006-05-18 01:12:22.000000000 +0300
++++ linux-2.6.16.16/drivers/char/Kconfig	2006-05-17 21:41:29.000000000 +0300
+@@ -187,6 +187,7 @@
+ config ISI
+ 	tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
+ 	depends on SERIAL_NONSTANDARD
++	select FW_LOADER
+ 	help
+ 	  This is a driver for the Multi-Tech cards which provide several
+ 	  serial ports.  The driver is experimental and can currently only be
+diff -Naur linux-2.6.16/drivers/char/snsc.c linux-2.6.16.16/drivers/char/snsc.c
+--- linux-2.6.16/drivers/char/snsc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/snsc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -391,7 +391,8 @@
+ 			format_module_id(devnamep, geo_module(geoid),
+ 					 MODULE_FORMAT_BRIEF);
+ 			devnamep = devname + strlen(devname);
+-			sprintf(devnamep, "#%d", geo_slab(geoid));
++			sprintf(devnamep, "^%d#%d", geo_slot(geoid),
++				geo_slab(geoid));
+ 
+ 			/* allocate sysctl device data */
+ 			scd = kmalloc(sizeof (struct sysctl_data_s),
+diff -Naur linux-2.6.16/drivers/char/sonypi.c linux-2.6.16.16/drivers/char/sonypi.c
+--- linux-2.6.16/drivers/char/sonypi.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/sonypi.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1341,6 +1341,9 @@
+ 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ 					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
+ 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
++	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
++					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
++		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+ 	else
+ 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
+ 
+diff -Naur linux-2.6.16/drivers/char/tipar.c linux-2.6.16.16/drivers/char/tipar.c
+--- linux-2.6.16/drivers/char/tipar.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/tipar.c	2006-05-11 04:56:24.000000000 +0300
+@@ -515,7 +515,7 @@
+ 		err = PTR_ERR(tipar_class);
+ 		goto out_chrdev;
+ 	}
+-	if (parport_register_driver(&tipar_driver) || tp_count == 0) {
++	if (parport_register_driver(&tipar_driver)) {
+ 		printk(KERN_ERR "tipar: unable to register with parport\n");
+ 		err = -EIO;
+ 		goto out_class;
+diff -Naur linux-2.6.16/drivers/char/tlclk.c linux-2.6.16.16/drivers/char/tlclk.c
+--- linux-2.6.16/drivers/char/tlclk.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/tlclk.c	2006-05-11 04:56:24.000000000 +0300
+@@ -327,7 +327,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
++static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
+ 		store_received_ref_clk3a);
+ 
+ 
+@@ -349,7 +349,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
++static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
+ 		store_received_ref_clk3b);
+ 
+ 
+@@ -371,7 +371,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL,
++static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
+ 		store_enable_clk3b_output);
+ 
+ static ssize_t store_enable_clk3a_output(struct device *d,
+@@ -392,7 +392,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL,
++static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
+ 		store_enable_clk3a_output);
+ 
+ static ssize_t store_enable_clkb1_output(struct device *d,
+@@ -413,7 +413,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL,
++static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
+ 		store_enable_clkb1_output);
+ 
+ 
+@@ -435,7 +435,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL,
++static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
+ 		store_enable_clka1_output);
+ 
+ static ssize_t store_enable_clkb0_output(struct device *d,
+@@ -456,7 +456,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL,
++static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
+ 		store_enable_clkb0_output);
+ 
+ static ssize_t store_enable_clka0_output(struct device *d,
+@@ -477,7 +477,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
++static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
+ 		store_enable_clka0_output);
+ 
+ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
+@@ -519,7 +519,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL,
++static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
+ 	store_select_amcb2_transmit_clock);
+ 
+ static ssize_t store_select_amcb1_transmit_clock(struct device *d,
+@@ -560,7 +560,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL,
++static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
+ 		store_select_amcb1_transmit_clock);
+ 
+ static ssize_t store_select_redundant_clock(struct device *d,
+@@ -581,7 +581,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL,
++static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
+ 		store_select_redundant_clock);
+ 
+ static ssize_t store_select_ref_frequency(struct device *d,
+@@ -602,7 +602,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL,
++static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
+ 		store_select_ref_frequency);
+ 
+ static ssize_t store_filter_select(struct device *d,
+@@ -623,7 +623,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select);
++static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
+ 
+ static ssize_t store_hardware_switching_mode(struct device *d,
+ 		 struct device_attribute *attr, const char *buf, size_t count)
+@@ -643,7 +643,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL,
++static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
+ 		store_hardware_switching_mode);
+ 
+ static ssize_t store_hardware_switching(struct device *d,
+@@ -664,7 +664,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL,
++static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
+ 		store_hardware_switching);
+ 
+ static ssize_t store_refalign (struct device *d,
+@@ -684,7 +684,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign);
++static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
+ 
+ static ssize_t store_mode_select (struct device *d,
+ 		 struct device_attribute *attr, const char *buf, size_t count)
+@@ -704,7 +704,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select);
++static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
+ 
+ static ssize_t store_reset (struct device *d,
+ 		 struct device_attribute *attr, const char *buf, size_t count)
+@@ -724,7 +724,7 @@
+ 	return strnlen(buf, count);
+ }
+ 
+-static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
++static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
+ 
+ static struct attribute *tlclk_sysfs_entries[] = {
+ 	&dev_attr_current_ref.attr,
+@@ -767,6 +767,7 @@
+ 		printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
+ 		return ret;
+ 	}
++	tlclk_major = ret;
+ 	alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
+ 	if (!alarm_events)
+ 		goto out1;
+diff -Naur linux-2.6.16/drivers/char/tty_io.c linux-2.6.16.16/drivers/char/tty_io.c
+--- linux-2.6.16/drivers/char/tty_io.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/char/tty_io.c	2006-05-11 04:56:24.000000000 +0300
+@@ -2706,7 +2706,11 @@
+ 		}
+ 		task_lock(p);
+ 		if (p->files) {
+-			rcu_read_lock();
++			/*
++			 * We don't take a ref to the file, so we must
++			 * hold ->file_lock instead.
++			 */
++			spin_lock(&p->files->file_lock);
+ 			fdt = files_fdtable(p->files);
+ 			for (i=0; i < fdt->max_fds; i++) {
+ 				filp = fcheck_files(p->files, i);
+@@ -2721,7 +2725,7 @@
+ 					break;
+ 				}
+ 			}
+-			rcu_read_unlock();
++			spin_unlock(&p->files->file_lock);
+ 		}
+ 		task_unlock(p);
+ 	} while_each_task_pid(session, PIDTYPE_SID, p);
+diff -Naur linux-2.6.16/drivers/edac/Kconfig linux-2.6.16.16/drivers/edac/Kconfig
+--- linux-2.6.16/drivers/edac/Kconfig	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/edac/Kconfig	2006-05-11 04:56:24.000000000 +0300
+@@ -71,7 +71,7 @@
+ 
+ config EDAC_E752X
+ 	tristate "Intel e752x (e7520, e7525, e7320)"
+-	depends on EDAC_MM_EDAC && PCI
++	depends on EDAC_MM_EDAC && PCI && HOTPLUG
+ 	help
+ 	  Support for error detection and correction on the Intel
+ 	  E7520, E7525, E7320 server chipsets.
+diff -Naur linux-2.6.16/drivers/i2c/busses/i2c-i801.c linux-2.6.16.16/drivers/i2c/busses/i2c-i801.c
+--- linux-2.6.16/drivers/i2c/busses/i2c-i801.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/i2c/busses/i2c-i801.c	2006-05-11 04:56:24.000000000 +0300
+@@ -478,6 +478,11 @@
+ 		ret = i801_transaction();
+ 	}
+ 
++	/* Some BIOSes don't like it when PEC is enabled at reboot or resume
++	   time, so we forcibly disable it after every transaction. */
++	if (hwpec)
++		outb_p(0, SMBAUXCTL);
++
+ 	if(block)
+ 		return ret;
+ 	if(ret)
+diff -Naur linux-2.6.16/drivers/i2c/chips/m41t00.c linux-2.6.16.16/drivers/i2c/chips/m41t00.c
+--- linux-2.6.16/drivers/i2c/chips/m41t00.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/i2c/chips/m41t00.c	2006-05-11 04:56:24.000000000 +0300
+@@ -129,13 +129,13 @@
+ 	if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
+ 		|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
+ 			< 0)
+-		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
++		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
+ 			< 0)
+-		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
++		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
+ 			< 0)
+-		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
++		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
+ 			< 0)
+-		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
++		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
+ 			< 0))
+ 
+ 		dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
+diff -Naur linux-2.6.16/drivers/ide/pci/alim15x3.c linux-2.6.16.16/drivers/ide/pci/alim15x3.c
+--- linux-2.6.16/drivers/ide/pci/alim15x3.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/ide/pci/alim15x3.c	2006-05-11 04:56:24.000000000 +0300
+@@ -731,6 +731,8 @@
+ 	
+ 	if(m5229_revision <= 0x20)
+ 		tmpbyte = (tmpbyte & (~0x02)) | 0x01;
++	else if (m5229_revision == 0xc7)
++		tmpbyte |= 0x03;
+ 	else
+ 		tmpbyte |= 0x01;
+ 
+diff -Naur linux-2.6.16/drivers/ieee1394/sbp2.c linux-2.6.16.16/drivers/ieee1394/sbp2.c
+--- linux-2.6.16/drivers/ieee1394/sbp2.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/ieee1394/sbp2.c	2006-05-11 04:56:24.000000000 +0300
+@@ -495,22 +495,17 @@
+ /*
+  * This function finds the sbp2_command for a given outstanding SCpnt.
+  * Only looks at the inuse list.
++ * Must be called with scsi_id->sbp2_command_orb_lock held.
+  */
+-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
++static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
++		struct scsi_id_instance_data *scsi_id, void *SCpnt)
+ {
+ 	struct sbp2_command_info *command;
+-	unsigned long flags;
+ 
+-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+-	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
+-		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
+-			if (command->Current_SCpnt == SCpnt) {
+-				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
++	if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
++		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
++			if (command->Current_SCpnt == SCpnt)
+ 				return command;
+-			}
+-		}
+-	}
+-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+ 	return NULL;
+ }
+ 
+@@ -579,17 +574,15 @@
+ 
+ /*
+  * This function moves a command to the completed orb list.
++ * Must be called with scsi_id->sbp2_command_orb_lock held.
+  */
+-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
+-					    struct sbp2_command_info *command)
++static void sbp2util_mark_command_completed(
++		struct scsi_id_instance_data *scsi_id,
++		struct sbp2_command_info *command)
+ {
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+ 	list_del(&command->list);
+ 	sbp2util_free_command_dma(command);
+ 	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
+-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+ }
+ 
+ /*
+@@ -2177,7 +2170,9 @@
+ 		 * Matched status with command, now grab scsi command pointers and check status
+ 		 */
+ 		SCpnt = command->Current_SCpnt;
++		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+ 		sbp2util_mark_command_completed(scsi_id, command);
++		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+ 
+ 		if (SCpnt) {
+ 
+@@ -2513,6 +2508,7 @@
+ 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
+ 	struct sbp2scsi_host_info *hi = scsi_id->hi;
+ 	struct sbp2_command_info *command;
++	unsigned long flags;
+ 
+ 	SBP2_ERR("aborting sbp2 command");
+ 	scsi_print_command(SCpnt);
+@@ -2523,6 +2519,7 @@
+ 		 * Right now, just return any matching command structures
+ 		 * to the free pool.
+ 		 */
++		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
+ 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
+ 		if (command) {
+ 			SBP2_DEBUG("Found command to abort");
+@@ -2540,6 +2537,7 @@
+ 				command->Current_done(command->Current_SCpnt);
+ 			}
+ 		}
++		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+ 
+ 		/*
+ 		 * Initiate a fetch agent reset.
+diff -Naur linux-2.6.16/drivers/macintosh/therm_adt746x.c linux-2.6.16.16/drivers/macintosh/therm_adt746x.c
+--- linux-2.6.16/drivers/macintosh/therm_adt746x.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/macintosh/therm_adt746x.c	2006-05-11 04:56:24.000000000 +0300
+@@ -627,8 +627,8 @@
+ 	if(therm_type == ADT7460)
+ 		device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
+ 
+-#ifndef CONFIG_I2C_KEYWEST
+-	request_module("i2c-keywest");
++#ifndef CONFIG_I2C_POWERMAC
++	request_module("i2c-powermac");
+ #endif
+ 
+ 	return i2c_add_driver(&thermostat_driver);
+diff -Naur linux-2.6.16/drivers/md/dm.c linux-2.6.16.16/drivers/md/dm.c
+--- linux-2.6.16/drivers/md/dm.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/md/dm.c	2006-05-11 04:56:24.000000000 +0300
+@@ -533,30 +533,35 @@
+ 
+ 	} else {
+ 		/*
+-		 * Create two copy bios to deal with io that has
+-		 * been split across a target.
++		 * Handle a bvec that must be split between two or more targets.
+ 		 */
+ 		struct bio_vec *bv = bio->bi_io_vec + ci->idx;
++		sector_t remaining = to_sector(bv->bv_len);
++		unsigned int offset = 0;
+ 
+-		clone = split_bvec(bio, ci->sector, ci->idx,
+-				   bv->bv_offset, max);
+-		__map_bio(ti, clone, tio);
+-
+-		ci->sector += max;
+-		ci->sector_count -= max;
+-		ti = dm_table_find_target(ci->map, ci->sector);
+-
+-		len = to_sector(bv->bv_len) - max;
+-		clone = split_bvec(bio, ci->sector, ci->idx,
+-				   bv->bv_offset + to_bytes(max), len);
+-		tio = alloc_tio(ci->md);
+-		tio->io = ci->io;
+-		tio->ti = ti;
+-		memset(&tio->info, 0, sizeof(tio->info));
+-		__map_bio(ti, clone, tio);
++		do {
++			if (offset) {
++				ti = dm_table_find_target(ci->map, ci->sector);
++				max = max_io_len(ci->md, ci->sector, ti);
++
++				tio = alloc_tio(ci->md);
++				tio->io = ci->io;
++				tio->ti = ti;
++				memset(&tio->info, 0, sizeof(tio->info));
++			}
++
++			len = min(remaining, max);
++
++			clone = split_bvec(bio, ci->sector, ci->idx,
++					   bv->bv_offset + offset, len);
++
++			__map_bio(ti, clone, tio);
++
++			ci->sector += len;
++			ci->sector_count -= len;
++			offset += to_bytes(len);
++		} while (remaining -= len);
+ 
+-		ci->sector += len;
+-		ci->sector_count -= len;
+ 		ci->idx++;
+ 	}
+ }
+@@ -1093,6 +1098,7 @@
+ {
+ 	struct dm_table *map = NULL;
+ 	DECLARE_WAITQUEUE(wait, current);
++	struct bio *def;
+ 	int r = -EINVAL;
+ 
+ 	down(&md->suspend_lock);
+@@ -1152,9 +1158,11 @@
+ 	/* were we interrupted ? */
+ 	r = -EINTR;
+ 	if (atomic_read(&md->pending)) {
++		clear_bit(DMF_BLOCK_IO, &md->flags);
++		def = bio_list_get(&md->deferred);
++		__flush_deferred_io(md, def);
+ 		up_write(&md->io_lock);
+ 		unlock_fs(md);
+-		clear_bit(DMF_BLOCK_IO, &md->flags);
+ 		goto out;
+ 	}
+ 	up_write(&md->io_lock);
+diff -Naur linux-2.6.16/drivers/md/dm-snap.c linux-2.6.16.16/drivers/md/dm-snap.c
+--- linux-2.6.16/drivers/md/dm-snap.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/md/dm-snap.c	2006-05-11 04:56:24.000000000 +0300
+@@ -542,8 +542,12 @@
+ {
+ 	struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ 
++	/* Prevent further origin writes from using this snapshot. */
++	/* After this returns there can be no new kcopyd jobs. */
+ 	unregister_snapshot(s);
+ 
++	kcopyd_client_destroy(s->kcopyd_client);
++
+ 	exit_exception_table(&s->pending, pending_cache);
+ 	exit_exception_table(&s->complete, exception_cache);
+ 
+@@ -552,7 +556,7 @@
+ 
+ 	dm_put_device(ti, s->origin);
+ 	dm_put_device(ti, s->cow);
+-	kcopyd_client_destroy(s->kcopyd_client);
++
+ 	kfree(s);
+ }
+ 
+diff -Naur linux-2.6.16/drivers/md/kcopyd.c linux-2.6.16.16/drivers/md/kcopyd.c
+--- linux-2.6.16/drivers/md/kcopyd.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/md/kcopyd.c	2006-05-11 04:56:24.000000000 +0300
+@@ -44,6 +44,9 @@
+ 	struct page_list *pages;
+ 	unsigned int nr_pages;
+ 	unsigned int nr_free_pages;
++
++	wait_queue_head_t destroyq;
++	atomic_t nr_jobs;
+ };
+ 
+ static struct page_list *alloc_pl(void)
+@@ -293,10 +296,15 @@
+ 	int read_err = job->read_err;
+ 	unsigned int write_err = job->write_err;
+ 	kcopyd_notify_fn fn = job->fn;
++	struct kcopyd_client *kc = job->kc;
+ 
+-	kcopyd_put_pages(job->kc, job->pages);
++	kcopyd_put_pages(kc, job->pages);
+ 	mempool_free(job, _job_pool);
+ 	fn(read_err, write_err, context);
++
++	if (atomic_dec_and_test(&kc->nr_jobs))
++		wake_up(&kc->destroyq);
++
+ 	return 0;
+ }
+ 
+@@ -431,6 +439,7 @@
+  */
+ static void dispatch_job(struct kcopyd_job *job)
+ {
++	atomic_inc(&job->kc->nr_jobs);
+ 	push(&_pages_jobs, job);
+ 	wake();
+ }
+@@ -670,6 +679,9 @@
+ 		return r;
+ 	}
+ 
++	init_waitqueue_head(&kc->destroyq);
++	atomic_set(&kc->nr_jobs, 0);
++
+ 	client_add(kc);
+ 	*result = kc;
+ 	return 0;
+@@ -677,6 +689,9 @@
+ 
+ void kcopyd_client_destroy(struct kcopyd_client *kc)
+ {
++	/* Wait for completion of all jobs submitted by this client. */
++	wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs));
++
+ 	dm_io_put(kc->nr_pages);
+ 	client_free_pages(kc);
+ 	client_del(kc);
+diff -Naur linux-2.6.16/drivers/media/dvb/dvb-usb/cxusb.c linux-2.6.16.16/drivers/media/dvb/dvb-usb/cxusb.c
+--- linux-2.6.16/drivers/media/dvb/dvb-usb/cxusb.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/media/dvb/dvb-usb/cxusb.c	2006-05-11 04:56:24.000000000 +0300
+@@ -149,6 +149,15 @@
+ 		return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
+ }
+ 
++static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
++{
++	u8 b = 0;
++	if (onoff)
++		return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
++	else
++		return 0;
++}
++
+ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+ {
+ 	u8 buf[2] = { 0x03, 0x00 };
+@@ -505,7 +514,7 @@
+ 	.size_of_priv     = sizeof(struct cxusb_state),
+ 
+ 	.streaming_ctrl   = cxusb_streaming_ctrl,
+-	.power_ctrl       = cxusb_power_ctrl,
++	.power_ctrl       = cxusb_bluebird_power_ctrl,
+ 	.frontend_attach  = cxusb_lgdt3303_frontend_attach,
+ 	.tuner_attach     = cxusb_lgh064f_tuner_attach,
+ 
+@@ -545,7 +554,7 @@
+ 	.size_of_priv     = sizeof(struct cxusb_state),
+ 
+ 	.streaming_ctrl   = cxusb_streaming_ctrl,
+-	.power_ctrl       = cxusb_power_ctrl,
++	.power_ctrl       = cxusb_bluebird_power_ctrl,
+ 	.frontend_attach  = cxusb_dee1601_frontend_attach,
+ 	.tuner_attach     = cxusb_dee1601_tuner_attach,
+ 
+@@ -594,7 +603,7 @@
+ 	.size_of_priv     = sizeof(struct cxusb_state),
+ 
+ 	.streaming_ctrl   = cxusb_streaming_ctrl,
+-	.power_ctrl       = cxusb_power_ctrl,
++	.power_ctrl       = cxusb_bluebird_power_ctrl,
+ 	.frontend_attach  = cxusb_mt352_frontend_attach,
+ 	.tuner_attach     = cxusb_lgz201_tuner_attach,
+ 
+@@ -634,7 +643,7 @@
+ 	.size_of_priv     = sizeof(struct cxusb_state),
+ 
+ 	.streaming_ctrl   = cxusb_streaming_ctrl,
+-	.power_ctrl       = cxusb_power_ctrl,
++	.power_ctrl       = cxusb_bluebird_power_ctrl,
+ 	.frontend_attach  = cxusb_mt352_frontend_attach,
+ 	.tuner_attach     = cxusb_dtt7579_tuner_attach,
+ 
+diff -Naur linux-2.6.16/drivers/media/video/Kconfig linux-2.6.16.16/drivers/media/video/Kconfig
+--- linux-2.6.16/drivers/media/video/Kconfig	2006-05-18 01:12:22.000000000 +0300
++++ linux-2.6.16.16/drivers/media/video/Kconfig	2006-05-17 21:41:30.000000000 +0300
+@@ -349,6 +349,7 @@
+ config VIDEO_DECODER
+ 	tristate "Add support for additional video chipsets"
+ 	depends on VIDEO_DEV && I2C && EXPERIMENTAL
++	select FW_LOADER
+ 	---help---
+ 	  Say Y here to compile drivers for SAA7115, SAA7127 and CX25840
+ 	  video decoders.
+diff -Naur linux-2.6.16/drivers/media/video/saa7127.c linux-2.6.16.16/drivers/media/video/saa7127.c
+--- linux-2.6.16/drivers/media/video/saa7127.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/media/video/saa7127.c	2006-05-11 04:56:24.000000000 +0300
+@@ -141,6 +141,7 @@
+ static const struct i2c_reg_value saa7129_init_config_extra[] = {
+ 	{ SAA7127_REG_OUTPUT_PORT_CONTROL, 		0x38 },
+ 	{ SAA7127_REG_VTRIG, 				0xfa },
++	{ 0, 0 }
+ };
+ 
+ static const struct i2c_reg_value saa7127_init_config_common[] = {
+diff -Naur linux-2.6.16/drivers/media/video/tuner-types.c linux-2.6.16.16/drivers/media/video/tuner-types.c
+--- linux-2.6.16/drivers/media/video/tuner-types.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/media/video/tuner-types.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1087,8 +1087,8 @@
+ /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+ 
+ static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
+-	{ 16 * 175.75 /*MHz*/, 0x01, },
+-	{ 16 * 410.25 /*MHz*/, 0x02, },
++	{ 16 * 130.00 /*MHz*/, 0x01, },
++	{ 16 * 364.50 /*MHz*/, 0x02, },
+ 	{ 16 * 999.99        , 0x08, },
+ };
+ 
+diff -Naur linux-2.6.16/drivers/mtd/nand/Kconfig linux-2.6.16.16/drivers/mtd/nand/Kconfig
+--- linux-2.6.16/drivers/mtd/nand/Kconfig	2006-05-18 01:12:23.000000000 +0300
++++ linux-2.6.16.16/drivers/mtd/nand/Kconfig	2006-05-17 22:32:57.000000000 +0300
+@@ -184,15 +184,14 @@
+ 	  Even if you leave this disabled, you can enable BBT writes at module
+ 	  load time (assuming you build diskonchip as a module) with the module
+ 	  parameter "inftl_bbt_write=1".
+-	  
+- config MTD_NAND_SHARPSL
+- 	bool "Support for NAND Flash on Sharp SL Series (C7xx + others)"
+- 	depends on MTD_NAND && ARCH_PXA
+- 
+- config MTD_NAND_NANDSIM
+- 	bool "Support for NAND Flash Simulator"
+- 	depends on MTD_NAND && MTD_PARTITIONS
+ 
++config MTD_NAND_SHARPSL
++	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
++	depends on MTD_NAND && ARCH_PXA
++
++config MTD_NAND_NANDSIM
++	tristate "Support for NAND Flash Simulator"
++	depends on MTD_NAND && MTD_PARTITIONS
+ 	help
+ 	  The simulator may simulate verious NAND flash chips for the
+ 	  MTD nand layer.
+@@ -200,7 +199,6 @@
+ config MTD_NAND_OMAP_HW
+ 	bool "OMAP HW NAND Flash controller support"
+         depends on ARM && ARCH_OMAP16XX && MTD_NAND
+-
+ 	help
+ 	  Driver for TI OMAP16xx hardware NAND flash controller.
+ 
+diff -Naur linux-2.6.16/drivers/net/e1000/e1000_main.c linux-2.6.16.16/drivers/net/e1000/e1000_main.c
+--- linux-2.6.16/drivers/net/e1000/e1000_main.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/e1000/e1000_main.c	2006-05-11 04:56:24.000000000 +0300
+@@ -3851,6 +3851,7 @@
+ 			skb_shinfo(skb)->nr_frags++;
+ 			skb->len += length;
+ 			skb->data_len += length;
++			skb->truesize += length;
+ 		}
+ 
+ 		e1000_rx_checksum(adapter, staterr,
+diff -Naur linux-2.6.16/drivers/net/irda/irda-usb.c linux-2.6.16.16/drivers/net/irda/irda-usb.c
+--- linux-2.6.16/drivers/net/irda/irda-usb.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/irda/irda-usb.c	2006-05-11 04:56:24.000000000 +0300
+@@ -740,7 +740,7 @@
+ 	struct sk_buff *newskb;
+ 	struct sk_buff *dataskb;
+ 	struct urb *next_urb;
+-	int		docopy;
++	unsigned int len, docopy;
+ 
+ 	IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
+ 	
+@@ -851,10 +851,11 @@
+ 	dataskb->dev = self->netdev;
+ 	dataskb->mac.raw  = dataskb->data;
+ 	dataskb->protocol = htons(ETH_P_IRDA);
++	len = dataskb->len;
+ 	netif_rx(dataskb);
+ 
+ 	/* Keep stats up to date */
+-	self->stats.rx_bytes += dataskb->len;
++	self->stats.rx_bytes += len;
+ 	self->stats.rx_packets++;
+ 	self->netdev->last_rx = jiffies;
+ 
+diff -Naur linux-2.6.16/drivers/net/sky2.c linux-2.6.16.16/drivers/net/sky2.c
+--- linux-2.6.16/drivers/net/sky2.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/sky2.c	2006-05-11 04:56:24.000000000 +0300
+@@ -579,8 +579,8 @@
+ 	reg = gma_read16(hw, port, GM_PHY_ADDR);
+ 	gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+ 
+-	for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+-		gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
++	for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
++		gma_read16(hw, port, i);
+ 	gma_write16(hw, port, GM_PHY_ADDR, reg);
+ 
+ 	/* transmit control */
+diff -Naur linux-2.6.16/drivers/net/sky2.h linux-2.6.16.16/drivers/net/sky2.h
+--- linux-2.6.16/drivers/net/sky2.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/sky2.h	2006-05-11 04:56:24.000000000 +0300
+@@ -1380,6 +1380,7 @@
+ /* MIB Counters */
+ #define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
+ #define GM_MIB_CNT_SIZE	44		/* Number of MIB Counters */
++#define GM_MIB_CNT_END	0x025C		/* Last MIB counter */
+ 
+ /*
+  * MIB Counters base address definitions (low word) -
+diff -Naur linux-2.6.16/drivers/net/wireless/hostap/hostap_80211_tx.c linux-2.6.16.16/drivers/net/wireless/hostap/hostap_80211_tx.c
+--- linux-2.6.16/drivers/net/wireless/hostap/hostap_80211_tx.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/wireless/hostap/hostap_80211_tx.c	2006-05-11 04:56:24.000000000 +0300
+@@ -469,7 +469,7 @@
+ 	}
+ 
+ 	if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt &&
+-	    !(fc & IEEE80211_FCTL_VERS)) {
++	    !(fc & IEEE80211_FCTL_PROTECTED)) {
+ 		no_encrypt = 1;
+ 		PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing "
+ 		       "unencrypted EAPOL frame\n", dev->name);
+diff -Naur linux-2.6.16/drivers/net/wireless/ipw2200.c linux-2.6.16.16/drivers/net/wireless/ipw2200.c
+--- linux-2.6.16/drivers/net/wireless/ipw2200.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/wireless/ipw2200.c	2006-05-11 04:56:24.000000000 +0300
+@@ -9956,9 +9956,8 @@
+ 		return -EINVAL;
+ 	down(&p->sem);
+ 	memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len);
+-	for (i = IPW_EEPROM_DATA;
+-	     i < IPW_EEPROM_DATA + IPW_EEPROM_IMAGE_SIZE; i++)
+-		ipw_write8(p, i, p->eeprom[i]);
++	for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++)
++		ipw_write8(p, i + IPW_EEPROM_DATA, p->eeprom[i]);
+ 	up(&p->sem);
+ 	return 0;
+ }
+diff -Naur linux-2.6.16/drivers/net/wireless/Kconfig linux-2.6.16.16/drivers/net/wireless/Kconfig
+--- linux-2.6.16/drivers/net/wireless/Kconfig	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/net/wireless/Kconfig	2006-05-11 04:56:24.000000000 +0300
+@@ -239,7 +239,8 @@
+ 
+ config AIRO
+ 	tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
+-	depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN)
++ 	depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
++	select CRYPTO
+ 	---help---
+ 	  This is the standard Linux driver to support Cisco/Aironet ISA and
+ 	  PCI 802.11 wireless cards.
+@@ -374,6 +375,7 @@
+ config PCMCIA_SPECTRUM
+ 	tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+ 	depends on NET_RADIO && PCMCIA && HERMES
++	select FW_LOADER
+ 	---help---
+ 
+ 	  This is a driver for 802.11b cards using RAM-loadable Symbol
+@@ -387,6 +389,7 @@
+ config AIRO_CS
+ 	tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
+ 	depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
++	select CRYPTO
+ 	---help---
+ 	  This is the standard Linux driver to support Cisco/Aironet PCMCIA
+ 	  802.11 wireless cards.  This driver is the same as the Aironet
+diff -Naur linux-2.6.16/drivers/pcmcia/ds.c linux-2.6.16.16/drivers/pcmcia/ds.c
+--- linux-2.6.16/drivers/pcmcia/ds.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/pcmcia/ds.c	2006-05-11 04:56:24.000000000 +0300
+@@ -546,7 +546,7 @@
+ 			tmp = vers1->str + vers1->ofs[i];
+ 
+ 			length = strlen(tmp) + 1;
+-			if ((length < 3) || (length > 255))
++			if ((length < 2) || (length > 255))
+ 				continue;
+ 
+ 			p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
+diff -Naur linux-2.6.16/drivers/scsi/3w-9xxx.c linux-2.6.16.16/drivers/scsi/3w-9xxx.c
+--- linux-2.6.16/drivers/scsi/3w-9xxx.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/scsi/3w-9xxx.c	2006-05-11 04:56:24.000000000 +0300
+@@ -85,7 +85,7 @@
+ #include "3w-9xxx.h"
+ 
+ /* Globals */
+-#define TW_DRIVER_VERSION "2.26.02.005"
++#define TW_DRIVER_VERSION "2.26.02.007"
+ static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
+ static unsigned int twa_device_extension_count;
+ static int twa_major = -1;
+@@ -1944,9 +1944,13 @@
+ 		}
+ 		if (tw_dev->srb[request_id]->use_sg == 1) {
+ 			struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+-			char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
++			char *buf;
++			unsigned long flags = 0;
++			local_irq_save(flags);
++			buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ 			memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
+ 			kunmap_atomic(buf - sg->offset, KM_IRQ0);
++			local_irq_restore(flags);
+ 		}
+ 	}
+ } /* End twa_scsiop_execute_scsi_complete() */
+diff -Naur linux-2.6.16/drivers/scsi/3w-xxxx.c linux-2.6.16.16/drivers/scsi/3w-xxxx.c
+--- linux-2.6.16/drivers/scsi/3w-xxxx.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/scsi/3w-xxxx.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1508,10 +1508,12 @@
+ 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
+ 	void *buf;
+ 	unsigned int transfer_len;
++	unsigned long flags = 0;
+ 
+ 	if (cmd->use_sg) {
+ 		struct scatterlist *sg =
+ 			(struct scatterlist *)cmd->request_buffer;
++		local_irq_save(flags);
+ 		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+ 		transfer_len = min(sg->length, len);
+ 	} else {
+@@ -1526,6 +1528,7 @@
+ 
+ 		sg = (struct scatterlist *)cmd->request_buffer;
+ 		kunmap_atomic(buf - sg->offset, KM_IRQ0);
++		local_irq_restore(flags);
+ 	}
+ }
+ 
+diff -Naur linux-2.6.16/drivers/scsi/sata_mv.c linux-2.6.16.16/drivers/scsi/sata_mv.c
+--- linux-2.6.16/drivers/scsi/sata_mv.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/scsi/sata_mv.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1102,6 +1102,7 @@
+ 	void __iomem *port_mmio = mv_ap_base(ap);
+ 	struct mv_port_priv *pp = ap->private_data;
+ 	u32 out_ptr;
++	u8 ata_status;
+ 
+ 	out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ 
+@@ -1109,6 +1110,8 @@
+ 	assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+ 	       pp->rsp_consumer);
+ 
++	ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT;
++
+ 	/* increment our consumer index... */
+ 	pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+ 
+@@ -1123,7 +1126,7 @@
+ 	writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ 
+ 	/* Return ATA status register for completed CRPB */
+-	return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT);
++	return ata_status;
+ }
+ 
+ /**
+@@ -1192,7 +1195,6 @@
+ 	u32 hc_irq_cause;
+ 	int shift, port, port0, hard_port, handled;
+ 	unsigned int err_mask;
+-	u8 ata_status = 0;
+ 
+ 	if (hc == 0) {
+ 		port0 = 0;
+@@ -1210,6 +1212,7 @@
+ 		hc,relevant,hc_irq_cause);
+ 
+ 	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
++		u8 ata_status = 0;
+ 		ap = host_set->ports[port];
+ 		hard_port = port & MV_PORT_MASK;	/* range 0-3 */
+ 		handled = 0;	/* ensure ata_status is set if handled++ */
+diff -Naur linux-2.6.16/drivers/usb/core/message.c linux-2.6.16.16/drivers/usb/core/message.c
+--- linux-2.6.16/drivers/usb/core/message.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/usb/core/message.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1388,11 +1388,13 @@
+ 	if (dev->state != USB_STATE_ADDRESS)
+ 		usb_disable_device (dev, 1);	// Skip ep0
+ 
+-	i = dev->bus_mA - cp->desc.bMaxPower * 2;
+-	if (i < 0)
+-		dev_warn(&dev->dev, "new config #%d exceeds power "
+-				"limit by %dmA\n",
+-				configuration, -i);
++	if (cp) {
++		i = dev->bus_mA - cp->desc.bMaxPower * 2;
++		if (i < 0)
++			dev_warn(&dev->dev, "new config #%d exceeds power "
++					"limit by %dmA\n",
++					configuration, -i);
++	}
+ 
+ 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+diff -Naur linux-2.6.16/drivers/usb/host/ehci-sched.c linux-2.6.16.16/drivers/usb/host/ehci-sched.c
+--- linux-2.6.16/drivers/usb/host/ehci-sched.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/usb/host/ehci-sched.c	2006-05-11 04:56:24.000000000 +0300
+@@ -707,6 +707,7 @@
+ 	} else {
+ 		u32		addr;
+ 		int		think_time;
++		int		hs_transfers;
+ 
+ 		addr = dev->ttport << 24;
+ 		if (!ehci_is_TDI(ehci)
+@@ -719,6 +720,7 @@
+ 		think_time = dev->tt ? dev->tt->think_time : 0;
+ 		stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time (
+ 				dev->speed, is_input, 1, maxp));
++		hs_transfers = max (1u, (maxp + 187) / 188);
+ 		if (is_input) {
+ 			u32	tmp;
+ 
+@@ -727,12 +729,11 @@
+ 			stream->usecs = HS_USECS_ISO (1);
+ 			stream->raw_mask = 1;
+ 
+-			/* pessimistic c-mask */
+-			tmp = usb_calc_bus_time (USB_SPEED_FULL, 1, 0, maxp)
+-					/ (125 * 1000);
+-			stream->raw_mask |= 3 << (tmp + 9);
++			/* c-mask as specified in USB 2.0 11.18.4 3.c */
++			tmp = (1 << (hs_transfers + 2)) - 1;
++			stream->raw_mask |= tmp << (8 + 2);
+ 		} else
+-			stream->raw_mask = smask_out [maxp / 188];
++			stream->raw_mask = smask_out [hs_transfers - 1];
+ 		bandwidth = stream->usecs + stream->c_usecs;
+ 		bandwidth /= 1 << (interval + 2);
+ 
+diff -Naur linux-2.6.16/drivers/usb/serial/console.c linux-2.6.16.16/drivers/usb/serial/console.c
+--- linux-2.6.16/drivers/usb/serial/console.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/usb/serial/console.c	2006-05-11 04:56:24.000000000 +0300
+@@ -54,7 +54,7 @@
+  * serial.c code, except that the specifier is "ttyUSB" instead
+  * of "ttyS".
+  */
+-static int __init usb_console_setup(struct console *co, char *options)
++static int usb_console_setup(struct console *co, char *options)
+ {
+ 	struct usbcons_info *info = &usbcons_info;
+ 	int baud = 9600;
+diff -Naur linux-2.6.16/drivers/usb/serial/option.c linux-2.6.16.16/drivers/usb/serial/option.c
+--- linux-2.6.16/drivers/usb/serial/option.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/usb/serial/option.c	2006-05-11 04:56:24.000000000 +0300
+@@ -582,14 +582,14 @@
+ 	portdata = usb_get_serial_port_data(port);
+ 
+ 	/* Do indat endpoints first */
+-	for (j = 0; j <= N_IN_URB; ++j) {
++	for (j = 0; j < N_IN_URB; ++j) {
+ 		portdata->in_urbs[j] = option_setup_urb (serial,
+                   port->bulk_in_endpointAddress, USB_DIR_IN, port,
+                   portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
+ 	}
+ 
+ 	/* outdat endpoints */
+-	for (j = 0; j <= N_OUT_URB; ++j) {
++	for (j = 0; j < N_OUT_URB; ++j) {
+ 		portdata->out_urbs[j] = option_setup_urb (serial,
+                   port->bulk_out_endpointAddress, USB_DIR_OUT, port,
+                   portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+diff -Naur linux-2.6.16/drivers/usb/storage/Kconfig linux-2.6.16.16/drivers/usb/storage/Kconfig
+--- linux-2.6.16/drivers/usb/storage/Kconfig	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/usb/storage/Kconfig	2006-05-11 04:56:24.000000000 +0300
+@@ -48,7 +48,8 @@
+ 
+ config USB_STORAGE_ISD200
+ 	bool "ISD-200 USB/ATA Bridge support"
+-	depends on USB_STORAGE && BLK_DEV_IDE
++	depends on USB_STORAGE
++	depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE
+ 	---help---
+ 	  Say Y here if you want to use USB Mass Store devices based
+ 	  on the In-Systems Design ISD-200 USB/ATA bridge.
+diff -Naur linux-2.6.16/drivers/video/cfbimgblt.c linux-2.6.16.16/drivers/video/cfbimgblt.c
+--- linux-2.6.16/drivers/video/cfbimgblt.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/video/cfbimgblt.c	2006-05-11 04:56:24.000000000 +0300
+@@ -169,7 +169,7 @@
+ 
+ 		while (j--) {
+ 			l--;
+-			color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor;
++			color = (*s & (1 << l)) ? fgcolor : bgcolor;
+ 			val |= FB_SHIFT_HIGH(color, shift);
+ 			
+ 			/* Did the bitshift spill bits to the next long? */
+diff -Naur linux-2.6.16/drivers/video/fbmem.c linux-2.6.16.16/drivers/video/fbmem.c
+--- linux-2.6.16/drivers/video/fbmem.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/video/fbmem.c	2006-05-11 04:56:24.000000000 +0300
+@@ -669,13 +669,19 @@
+ 		total_size = info->fix.smem_len;
+ 
+ 	if (p > total_size)
+-		return 0;
++		return -EFBIG;
+ 
+-	if (count >= total_size)
++	if (count > total_size) {
++		err = -EFBIG;
+ 		count = total_size;
++	}
++
++	if (count + p > total_size) {
++		if (!err)
++			err = -ENOSPC;
+ 
+-	if (count + p > total_size)
+ 		count = total_size - p;
++	}
+ 
+ 	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+ 			 GFP_KERNEL);
+@@ -717,7 +723,7 @@
+ 
+ 	kfree(buffer);
+ 
+-	return (err) ? err : cnt;
++	return (cnt) ? cnt : err;
+ }
+ 
+ #ifdef CONFIG_KMOD
+diff -Naur linux-2.6.16/drivers/video/i810/i810_main.c linux-2.6.16.16/drivers/video/i810/i810_main.c
+--- linux-2.6.16/drivers/video/i810/i810_main.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/drivers/video/i810/i810_main.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1508,7 +1508,7 @@
+ 		int size = ((cursor->image.width + 7) >> 3) *
+ 			cursor->image.height;
+ 		int i;
+-		u8 *data = kmalloc(64 * 8, GFP_KERNEL);
++		u8 *data = kmalloc(64 * 8, GFP_ATOMIC);
+ 
+ 		if (data == NULL)
+ 			return -ENOMEM;
+diff -Naur linux-2.6.16/fs/9p/vfs_inode.c linux-2.6.16.16/fs/9p/vfs_inode.c
+--- linux-2.6.16/fs/9p/vfs_inode.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/9p/vfs_inode.c	2006-05-11 04:56:24.000000000 +0300
+@@ -614,6 +614,7 @@
+ 
+ 	sb = dir->i_sb;
+ 	v9ses = v9fs_inode2v9ses(dir);
++	dentry->d_op = &v9fs_dentry_operations;
+ 	dirfid = v9fs_fid_lookup(dentry->d_parent);
+ 
+ 	if (!dirfid) {
+@@ -681,8 +682,6 @@
+ 		goto FreeFcall;
+ 
+ 	fid->qid = fcall->params.rstat.stat.qid;
+-
+-	dentry->d_op = &v9fs_dentry_operations;
+ 	v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
+ 
+ 	d_add(dentry, inode);
+diff -Naur linux-2.6.16/fs/char_dev.c linux-2.6.16.16/fs/char_dev.c
+--- linux-2.6.16/fs/char_dev.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/char_dev.c	2006-05-11 04:56:24.000000000 +0300
+@@ -15,6 +15,7 @@
+ #include <linux/module.h>
+ #include <linux/smp_lock.h>
+ #include <linux/devfs_fs_kernel.h>
++#include <linux/seq_file.h>
+ 
+ #include <linux/kobject.h>
+ #include <linux/kobj_map.h>
+@@ -26,8 +27,6 @@
+ 
+ static struct kobj_map *cdev_map;
+ 
+-#define MAX_PROBE_HASH 255	/* random */
+-
+ static DECLARE_MUTEX(chrdevs_lock);
+ 
+ static struct char_device_struct {
+@@ -38,93 +37,29 @@
+ 	char name[64];
+ 	struct file_operations *fops;
+ 	struct cdev *cdev;		/* will die */
+-} *chrdevs[MAX_PROBE_HASH];
++} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
+ 
+ /* index in the above */
+ static inline int major_to_index(int major)
+ {
+-	return major % MAX_PROBE_HASH;
+-}
+-
+-struct chrdev_info {
+-	int index;
+-	struct char_device_struct *cd;
+-};
+-
+-void *get_next_chrdev(void *dev)
+-{
+-	struct chrdev_info *info;
+-
+-	if (dev == NULL) {
+-		info = kmalloc(sizeof(*info), GFP_KERNEL);
+-		if (!info)
+-			goto out;
+-		info->index=0;
+-		info->cd = chrdevs[info->index];
+-		if (info->cd)
+-			goto out;
+-	} else {
+-		info = dev;
+-	}
+-
+-	while (info->index < ARRAY_SIZE(chrdevs)) {
+-		if (info->cd)
+-			info->cd = info->cd->next;
+-		if (info->cd)
+-			goto out;
+-		/*
+-		 * No devices on this chain, move to the next
+-		 */
+-		info->index++;
+-		info->cd = (info->index < ARRAY_SIZE(chrdevs)) ?
+-			chrdevs[info->index] : NULL;
+-		if (info->cd)
+-			goto out;
+-	}
+-
+-out:
+-	return info;
+-}
+-
+-void *acquire_chrdev_list(void)
+-{
+-	down(&chrdevs_lock);
+-	return get_next_chrdev(NULL);
+-}
+-
+-void release_chrdev_list(void *dev)
+-{
+-	up(&chrdevs_lock);
+-	kfree(dev);
++	return major % CHRDEV_MAJOR_HASH_SIZE;
+ }
+ 
++#ifdef CONFIG_PROC_FS
+ 
+-int count_chrdev_list(void)
++void chrdev_show(struct seq_file *f, off_t offset)
+ {
+ 	struct char_device_struct *cd;
+-	int i, count;
+-
+-	count = 0;
+ 
+-	for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
+-		for (cd = chrdevs[i]; cd; cd = cd->next)
+-			count++;
++	if (offset < CHRDEV_MAJOR_HASH_SIZE) {
++		down(&chrdevs_lock);
++		for (cd = chrdevs[offset]; cd; cd = cd->next)
++			seq_printf(f, "%3d %s\n", cd->major, cd->name);
++		up(&chrdevs_lock);
+ 	}
+-
+-	return count;
+ }
+ 
+-int get_chrdev_info(void *dev, int *major, char **name)
+-{
+-	struct chrdev_info *info = dev;
+-
+-	if (info->cd == NULL)
+-		return 1;
+-
+-	*major = info->cd->major;
+-	*name = info->cd->name;
+-	return 0;
+-}
++#endif /* CONFIG_PROC_FS */
+ 
+ /*
+  * Register a single major with a specified minor range.
+diff -Naur linux-2.6.16/fs/cifs/cifsencrypt.c linux-2.6.16.16/fs/cifs/cifsencrypt.c
+--- linux-2.6.16/fs/cifs/cifsencrypt.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/cifs/cifsencrypt.c	2006-05-11 04:56:24.000000000 +0300
+@@ -56,9 +56,6 @@
+ 	int rc = 0;
+ 	char smb_signature[20];
+ 
+-	/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
+-	/* BB remember to add code to save expected sequence number in midQ entry BB */
+-
+ 	if((cifs_pdu == NULL) || (server == NULL))
+ 		return -EINVAL;
+ 
+@@ -85,20 +82,33 @@
+ static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
+ 				const char * key, char * signature)
+ {
+-        struct  MD5Context context;
+-
+-        if((iov == NULL) || (signature == NULL))
+-                return -EINVAL;
++	struct  MD5Context context;
++	int i;
+ 
+-        MD5Init(&context);
+-        MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
++	if((iov == NULL) || (signature == NULL))
++		return -EINVAL;
+ 
+-/*        MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
++	MD5Init(&context);
++	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
++	for(i=0;i<n_vec;i++) {
++		if(iov[i].iov_base == NULL) {
++			cERROR(1,("null iovec entry"));
++			return -EIO;
++		} else if(iov[i].iov_len == 0)
++			break; /* bail out if we are sent nothing to sign */
++		/* The first entry includes a length field (which does not get
++		   signed that occupies the first 4 bytes before the header */
++		if(i==0) {
++			if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
++				break; /* nothing to sign or corrupt header */
++			MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
++		} else
++			MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
++	}
+ 
+-        MD5Final(signature,&context);
++	MD5Final(signature,&context);
+ 
+-	return -EOPNOTSUPP;
+-/*        return 0; */
++	return 0;
+ }
+ 
+ 
+diff -Naur linux-2.6.16/fs/cifs/dir.c linux-2.6.16.16/fs/cifs/dir.c
+--- linux-2.6.16/fs/cifs/dir.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/cifs/dir.c	2006-05-11 04:56:24.000000000 +0300
+@@ -441,6 +441,20 @@
+ 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
+ 	pTcon = cifs_sb->tcon;
+ 
++	/*
++	 * Don't allow the separator character in a path component.
++	 * The VFS will not allow "/", but "\" is allowed by posix.
++	 */
++	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
++		int i;
++		for (i = 0; i < direntry->d_name.len; i++)
++			if (direntry->d_name.name[i] == '\\') {
++				cFYI(1, ("Invalid file name"));
++				FreeXid(xid);
++				return ERR_PTR(-EINVAL);
++			}
++	}
++
+ 	/* can not grab the rename sem here since it would
+ 	deadlock in the cases (beginning of sys_rename itself)
+ 	in which we already have the sb rename sem */
+diff -Naur linux-2.6.16/fs/compat.c linux-2.6.16.16/fs/compat.c
+--- linux-2.6.16/fs/compat.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/compat.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1215,6 +1215,10 @@
+ 	if (ret < 0)
+ 		goto out;
+ 
++	ret = security_file_permission(file, type == READ ? MAY_READ:MAY_WRITE);
++	if (ret)
++		goto out;
++
+ 	fnv = NULL;
+ 	if (type == READ) {
+ 		fn = file->f_op->read;
+diff -Naur linux-2.6.16/fs/ext3/resize.c linux-2.6.16.16/fs/ext3/resize.c
+--- linux-2.6.16/fs/ext3/resize.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/ext3/resize.c	2006-05-11 04:56:24.000000000 +0300
+@@ -974,6 +974,7 @@
+ 	if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
+ 		ext3_warning(sb, __FUNCTION__,
+ 			     "multiple resizers run on filesystem!");
++		unlock_super(sb);
+ 		err = -EBUSY;
+ 		goto exit_put;
+ 	}
+diff -Naur linux-2.6.16/fs/fuse/file.c linux-2.6.16.16/fs/fuse/file.c
+--- linux-2.6.16/fs/fuse/file.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/fuse/file.c	2006-05-11 04:56:24.000000000 +0300
+@@ -397,8 +397,12 @@
+ 		return -EINTR;
+ 
+ 	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
+-	if (!err)
+-		fuse_send_readpages(data.req, file, inode);
++	if (!err) {
++		if (data.req->num_pages)
++			fuse_send_readpages(data.req, file, inode);
++		else
++			fuse_put_request(fc, data.req);
++	}
+ 	return err;
+ }
+ 
+diff -Naur linux-2.6.16/fs/locks.c linux-2.6.16.16/fs/locks.c
+--- linux-2.6.16/fs/locks.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/locks.c	2006-05-11 04:56:24.000000000 +0300
+@@ -432,15 +432,14 @@
+  */
+ static int lease_init(struct file *filp, int type, struct file_lock *fl)
+  {
++	if (assign_type(fl, type) != 0)
++		return -EINVAL;
++
+ 	fl->fl_owner = current->files;
+ 	fl->fl_pid = current->tgid;
+ 
+ 	fl->fl_file = filp;
+ 	fl->fl_flags = FL_LEASE;
+-	if (assign_type(fl, type) != 0) {
+-		locks_free_lock(fl);
+-		return -EINVAL;
+-	}
+ 	fl->fl_start = 0;
+ 	fl->fl_end = OFFSET_MAX;
+ 	fl->fl_ops = NULL;
+@@ -452,16 +451,19 @@
+ static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
+ {
+ 	struct file_lock *fl = locks_alloc_lock();
+-	int error;
++	int error = -ENOMEM;
+ 
+ 	if (fl == NULL)
+-		return -ENOMEM;
++		goto out;
+ 
+ 	error = lease_init(filp, type, fl);
+-	if (error)
+-		return error;
++	if (error) {
++		locks_free_lock(fl);
++		fl = NULL;
++	}
++out:
+ 	*flp = fl;
+-	return 0;
++	return error;
+ }
+ 
+ /* Check if two locks overlap each other.
+@@ -1337,6 +1339,7 @@
+ 		goto out;
+ 
+ 	if (my_before != NULL) {
++		*flp = *my_before;
+ 		error = lease->fl_lmops->fl_change(my_before, arg);
+ 		goto out;
+ 	}
+@@ -2212,7 +2215,12 @@
+ 
+ 	lock_kernel();
+ 	j = 0;
+-	rcu_read_lock();
++
++	/*
++	 * We are not taking a ref to the file structures, so
++	 * we need to acquire ->file_lock.
++	 */
++	spin_lock(&files->file_lock);
+ 	fdt = files_fdtable(files);
+ 	for (;;) {
+ 		unsigned long set;
+@@ -2230,7 +2238,7 @@
+ 			set >>= 1;
+ 		}
+ 	}
+-	rcu_read_unlock();
++	spin_unlock(&files->file_lock);
+ 	unlock_kernel();
+ }
+ EXPORT_SYMBOL(steal_locks);
+diff -Naur linux-2.6.16/fs/nfsd/nfs3proc.c linux-2.6.16.16/fs/nfsd/nfs3proc.c
+--- linux-2.6.16/fs/nfsd/nfs3proc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/nfsd/nfs3proc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -682,7 +682,7 @@
+   PROC(lookup,	 dirop,		dirop,		fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
+   PROC(access,	 access,	access,		fhandle,  RC_NOCACHE, ST+pAT+1),
+   PROC(readlink, readlink,	readlink,	fhandle,  RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
+-  PROC(read,	 read,		read,		fhandle,  RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
++  PROC(read,	 read,		read,		fhandle,  RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE/4),
+   PROC(write,	 write,		write,		fhandle,  RC_REPLBUFF, ST+WC+4),
+   PROC(create,	 create,	create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+   PROC(mkdir,	 mkdir,		create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+diff -Naur linux-2.6.16/fs/nfsd/nfs4proc.c linux-2.6.16.16/fs/nfsd/nfs4proc.c
+--- linux-2.6.16/fs/nfsd/nfs4proc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/nfsd/nfs4proc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -975,7 +975,7 @@
+  */
+ static struct svc_procedure		nfsd_procedures4[2] = {
+   PROC(null,	 void,		void,		void,	  RC_NOCACHE, 1),
+-  PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE)
++  PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE/4)
+ };
+ 
+ struct svc_version	nfsd_version4 = {
+diff -Naur linux-2.6.16/fs/nfsd/nfsproc.c linux-2.6.16.16/fs/nfsd/nfsproc.c
+--- linux-2.6.16/fs/nfsd/nfsproc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/nfsd/nfsproc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -553,7 +553,7 @@
+   PROC(none,	 void,		void,		none,		RC_NOCACHE, ST),
+   PROC(lookup,	 diropargs,	diropres,	fhandle,	RC_NOCACHE, ST+FH+AT),
+   PROC(readlink, readlinkargs,	readlinkres,	none,		RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
+-  PROC(read,	 readargs,	readres,	fhandle,	RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
++  PROC(read,	 readargs,	readres,	fhandle,	RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE/4),
+   PROC(none,	 void,		void,		none,		RC_NOCACHE, ST),
+   PROC(write,	 writeargs,	attrstat,	fhandle,	RC_REPLBUFF, ST+AT),
+   PROC(create,	 createargs,	diropres,	fhandle,	RC_REPLBUFF, ST+FH+AT),
+diff -Naur linux-2.6.16/fs/open.c linux-2.6.16.16/fs/open.c
+--- linux-2.6.16/fs/open.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/open.c	2006-05-11 04:56:24.000000000 +0300
+@@ -330,7 +330,10 @@
+ 
+ asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
+ {
+-	return do_sys_ftruncate(fd, length, 1);
++	long ret = do_sys_ftruncate(fd, length, 1);
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ /* LFS versions of truncate are only needed on 32 bit machines */
+@@ -342,7 +345,10 @@
+ 
+ asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
+ {
+-	return do_sys_ftruncate(fd, length, 0);
++	long ret = do_sys_ftruncate(fd, length, 0);
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ #endif
+ 
+@@ -1083,20 +1089,30 @@
+ 
+ asmlinkage long sys_open(const char __user *filename, int flags, int mode)
+ {
++	long ret;
++
+ 	if (force_o_largefile())
+ 		flags |= O_LARGEFILE;
+ 
+-	return do_sys_open(AT_FDCWD, filename, flags, mode);
++	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ EXPORT_SYMBOL_GPL(sys_open);
+ 
+ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
+ 			   int mode)
+ {
++	long ret;
++
+ 	if (force_o_largefile())
+ 		flags |= O_LARGEFILE;
+ 
+-	return do_sys_open(dfd, filename, flags, mode);
++	ret = do_sys_open(dfd, filename, flags, mode);
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ EXPORT_SYMBOL_GPL(sys_openat);
+ 
+diff -Naur linux-2.6.16/fs/partitions/check.c linux-2.6.16.16/fs/partitions/check.c
+--- linux-2.6.16/fs/partitions/check.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/partitions/check.c	2006-05-11 04:56:24.000000000 +0300
+@@ -345,6 +345,7 @@
+ 	char *name;
+ 	static char *block_str = "block:";
+ 	int size;
++	char *s;
+ 
+ 	size = strlen(block_str) + strlen(disk->disk_name) + 1;
+ 	name = kmalloc(size, GFP_KERNEL);
+@@ -352,6 +353,10 @@
+ 		return NULL;
+ 	strcpy(name, block_str);
+ 	strcat(name, disk->disk_name);
++	/* ewww... some of these buggers have / in name... */
++	s = strchr(name, '/');
++	if (s)
++		*s = '!';
+ 	return name;
+ }
+ 
+diff -Naur linux-2.6.16/fs/proc/base.c linux-2.6.16.16/fs/proc/base.c
+--- linux-2.6.16/fs/proc/base.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/proc/base.c	2006-05-11 04:56:24.000000000 +0300
+@@ -294,16 +294,20 @@
+ 
+ 	files = get_files_struct(task);
+ 	if (files) {
+-		rcu_read_lock();
++		/*
++		 * We are not taking a ref to the file structure, so we must
++		 * hold ->file_lock.
++		 */
++		spin_lock(&files->file_lock);
+ 		file = fcheck_files(files, fd);
+ 		if (file) {
+ 			*mnt = mntget(file->f_vfsmnt);
+ 			*dentry = dget(file->f_dentry);
+-			rcu_read_unlock();
++			spin_unlock(&files->file_lock);
+ 			put_files_struct(files);
+ 			return 0;
+ 		}
+-		rcu_read_unlock();
++		spin_unlock(&files->file_lock);
+ 		put_files_struct(files);
+ 	}
+ 	return -ENOENT;
+@@ -1485,7 +1489,12 @@
+ 	if (!files)
+ 		goto out_unlock;
+ 	inode->i_mode = S_IFLNK;
+-	rcu_read_lock();
++
++	/*
++	 * We are not taking a ref to the file structure, so we must
++	 * hold ->file_lock.
++	 */
++	spin_lock(&files->file_lock);
+ 	file = fcheck_files(files, fd);
+ 	if (!file)
+ 		goto out_unlock2;
+@@ -1493,7 +1502,7 @@
+ 		inode->i_mode |= S_IRUSR | S_IXUSR;
+ 	if (file->f_mode & 2)
+ 		inode->i_mode |= S_IWUSR | S_IXUSR;
+-	rcu_read_unlock();
++	spin_unlock(&files->file_lock);
+ 	put_files_struct(files);
+ 	inode->i_op = &proc_pid_link_inode_operations;
+ 	inode->i_size = 64;
+@@ -1503,7 +1512,7 @@
+ 	return NULL;
+ 
+ out_unlock2:
+-	rcu_read_unlock();
++	spin_unlock(&files->file_lock);
+ 	put_files_struct(files);
+ out_unlock:
+ 	iput(inode);
+diff -Naur linux-2.6.16/fs/proc/proc_misc.c linux-2.6.16.16/fs/proc/proc_misc.c
+--- linux-2.6.16/fs/proc/proc_misc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/proc/proc_misc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -249,144 +249,60 @@
+ 	return seq_open(file, &cpuinfo_op);
+ }
+ 
+-enum devinfo_states {
+-	CHR_HDR,
+-	CHR_LIST,
+-	BLK_HDR,
+-	BLK_LIST,
+-	DEVINFO_DONE
+-};
+-
+-struct devinfo_state {
+-	void *chrdev;
+-	void *blkdev;
+-	unsigned int num_records;
+-	unsigned int cur_record;
+-	enum devinfo_states state;
++static struct file_operations proc_cpuinfo_operations = {
++	.open		= cpuinfo_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= seq_release,
+ };
+ 
+-static void *devinfo_start(struct seq_file *f, loff_t *pos)
++static int devinfo_show(struct seq_file *f, void *v)
+ {
+-	struct devinfo_state *info = f->private;
++	int i = *(loff_t *) v;
+ 
+-	if (*pos) {
+-		if ((info) && (*pos <= info->num_records))
+-			return info;
+-		return NULL;
++	if (i < CHRDEV_MAJOR_HASH_SIZE) {
++		if (i == 0)
++			seq_printf(f, "Character devices:\n");
++		chrdev_show(f, i);
++	} else {
++		i -= CHRDEV_MAJOR_HASH_SIZE;
++		if (i == 0)
++			seq_printf(f, "\nBlock devices:\n");
++		blkdev_show(f, i);
+ 	}
+-	info = kmalloc(sizeof(*info), GFP_KERNEL);
+-	f->private = info;
+-	info->chrdev = acquire_chrdev_list();
+-	info->blkdev = acquire_blkdev_list();
+-	info->state = CHR_HDR;
+-	info->num_records = count_chrdev_list();
+-	info->num_records += count_blkdev_list();
+-	info->num_records += 2; /* Character and Block headers */
+-	*pos = 1;
+-	info->cur_record = *pos;
+-	return info;
++	return 0;
+ }
+ 
+-static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
++static void *devinfo_start(struct seq_file *f, loff_t *pos)
+ {
+-	int idummy;
+-	char *ndummy;
+-	struct devinfo_state *info = f->private;
+-
+-	switch (info->state) {
+-		case CHR_HDR:
+-			info->state = CHR_LIST;
+-			(*pos)++;
+-			/*fallthrough*/
+-		case CHR_LIST:
+-			if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) {
+-				/*
+-				 * The character dev list is complete
+-				 */
+-				info->state = BLK_HDR;
+-			} else {
+-				info->chrdev = get_next_chrdev(info->chrdev);
+-			}
+-			(*pos)++;
+-			break;
+-		case BLK_HDR:
+-			info->state = BLK_LIST;
+-			(*pos)++;
+-			break;
+-		case BLK_LIST:
+-			if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
+-				/*
+-				 * The block dev list is complete
+-				 */
+-				info->state = DEVINFO_DONE;
+-			} else {
+-				info->blkdev = get_next_blkdev(info->blkdev);
+-			}
+-			(*pos)++;
+-			break;
+-		case DEVINFO_DONE:
+-			(*pos)++;
+-			info->cur_record = *pos;
+-			info = NULL;
+-			break;
+-		default:
+-			break;
+-	}
+-	if (info)
+-		info->cur_record = *pos;
+-	return info;
++	if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
++		return pos;
++	return NULL;
+ }
+ 
+-static void devinfo_stop(struct seq_file *f, void *v)
++static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
+ {
+-	struct devinfo_state *info = f->private;
+-
+-	if (info) {
+-		release_chrdev_list(info->chrdev);
+-		release_blkdev_list(info->blkdev);
+-		f->private = NULL;
+-		kfree(info);
+-	}
++	(*pos)++;
++	if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
++		return NULL;
++	return pos;
+ }
+ 
+-static int devinfo_show(struct seq_file *f, void *arg)
++static void devinfo_stop(struct seq_file *f, void *v)
+ {
+-	int major;
+-	char *name;
+-	struct devinfo_state *info = f->private;
+-
+-	switch(info->state) {
+-		case CHR_HDR:
+-			seq_printf(f,"Character devices:\n");
+-			/* fallthrough */
+-		case CHR_LIST:
+-			if (!get_chrdev_info(info->chrdev,&major,&name))
+-				seq_printf(f,"%3d %s\n",major,name);
+-			break;
+-		case BLK_HDR:
+-			seq_printf(f,"\nBlock devices:\n");
+-			/* fallthrough */
+-		case BLK_LIST:
+-			if (!get_blkdev_info(info->blkdev,&major,&name))
+-				seq_printf(f,"%3d %s\n",major,name);
+-			break;
+-		default:
+-			break;
+-	}
+-
+-	return 0;
++	/* Nothing to do */
+ }
+ 
+-static  struct seq_operations devinfo_op = {
+-	.start  = devinfo_start,
+-	.next   = devinfo_next,
+-	.stop   = devinfo_stop,
+-	.show   = devinfo_show,
++static struct seq_operations devinfo_ops = {
++	.start = devinfo_start,
++	.next  = devinfo_next,
++	.stop  = devinfo_stop,
++	.show  = devinfo_show
+ };
+ 
+-static int devinfo_open(struct inode *inode, struct file *file)
++static int devinfo_open(struct inode *inode, struct file *filp)
+ {
+-	return seq_open(file, &devinfo_op);
++	return seq_open(filp, &devinfo_ops);
+ }
+ 
+ static struct file_operations proc_devinfo_operations = {
+@@ -396,13 +312,6 @@
+ 	.release	= seq_release,
+ };
+ 
+-static struct file_operations proc_cpuinfo_operations = {
+-	.open		= cpuinfo_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= seq_release,
+-};
+-
+ extern struct seq_operations vmstat_op;
+ static int vmstat_open(struct inode *inode, struct file *file)
+ {
+diff -Naur linux-2.6.16/fs/proc/vmcore.c linux-2.6.16.16/fs/proc/vmcore.c
+--- linux-2.6.16/fs/proc/vmcore.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/proc/vmcore.c	2006-05-11 04:56:24.000000000 +0300
+@@ -103,8 +103,8 @@
+ 				size_t buflen, loff_t *fpos)
+ {
+ 	ssize_t acc = 0, tmp;
+-	size_t tsz, nr_bytes;
+-	u64 start;
++	size_t tsz;
++	u64 start, nr_bytes;
+ 	struct vmcore *curr_m = NULL;
+ 
+ 	if (buflen == 0 || *fpos >= vmcore_size)
+diff -Naur linux-2.6.16/fs/reiserfs/xattr_acl.c linux-2.6.16.16/fs/reiserfs/xattr_acl.c
+--- linux-2.6.16/fs/reiserfs/xattr_acl.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/reiserfs/xattr_acl.c	2006-05-11 04:56:24.000000000 +0300
+@@ -408,8 +408,9 @@
+ 		acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
+ 		reiserfs_read_unlock_xattrs(inode->i_sb);
+ 		reiserfs_read_unlock_xattr_i(inode);
+-		ret = acl ? 1 : 0;
+-		posix_acl_release(acl);
++		ret = (acl && !IS_ERR(acl));
++		if (ret)
++			posix_acl_release(acl);
+ 	}
+ 
+ 	return ret;
+diff -Naur linux-2.6.16/fs/smbfs/dir.c linux-2.6.16.16/fs/smbfs/dir.c
+--- linux-2.6.16/fs/smbfs/dir.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/smbfs/dir.c	2006-05-11 04:56:24.000000000 +0300
+@@ -434,6 +434,11 @@
+ 	if (dentry->d_name.len > SMB_MAXNAMELEN)
+ 		goto out;
+ 
++	/* Do not allow lookup of names with backslashes in */
++	error = -EINVAL;
++	if (memchr(dentry->d_name.name, '\\', dentry->d_name.len))
++		goto out;
++
+ 	lock_kernel();
+ 	error = smb_proc_getattr(dentry, &finfo);
+ #ifdef SMBFS_PARANOIA
+diff -Naur linux-2.6.16/fs/sysfs/dir.c linux-2.6.16.16/fs/sysfs/dir.c
+--- linux-2.6.16/fs/sysfs/dir.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/sysfs/dir.c	2006-05-11 04:56:24.000000000 +0300
+@@ -302,6 +302,7 @@
+ 	 * Drop reference from dget() on entrance.
+ 	 */
+ 	dput(dentry);
++	kobj->dentry = NULL;
+ }
+ 
+ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
+diff -Naur linux-2.6.16/fs/sysfs/file.c linux-2.6.16.16/fs/sysfs/file.c
+--- linux-2.6.16/fs/sysfs/file.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/sysfs/file.c	2006-05-11 04:56:24.000000000 +0300
+@@ -183,7 +183,7 @@
+ 		return -ENOMEM;
+ 
+ 	if (count >= PAGE_SIZE)
+-		count = PAGE_SIZE;
++		count = PAGE_SIZE - 1;
+ 	error = copy_from_user(buffer->page,buf,count);
+ 	buffer->needs_read_fill = 1;
+ 	return error ? -EFAULT : count;
+diff -Naur linux-2.6.16/fs/sysfs/inode.c linux-2.6.16.16/fs/sysfs/inode.c
+--- linux-2.6.16/fs/sysfs/inode.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/sysfs/inode.c	2006-05-11 04:56:24.000000000 +0300
+@@ -227,12 +227,16 @@
+ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
+ {
+ 	struct sysfs_dirent * sd;
+-	struct sysfs_dirent * parent_sd = dir->d_fsdata;
++	struct sysfs_dirent * parent_sd;
++
++	if (!dir)
++		return;
+ 
+ 	if (dir->d_inode == NULL)
+ 		/* no inode means this hasn't been made visible yet */
+ 		return;
+ 
++	parent_sd = dir->d_fsdata;
+ 	mutex_lock(&dir->d_inode->i_mutex);
+ 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ 		if (!sd->s_element)
+diff -Naur linux-2.6.16/fs/sysfs/symlink.c linux-2.6.16.16/fs/sysfs/symlink.c
+--- linux-2.6.16/fs/sysfs/symlink.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/sysfs/symlink.c	2006-05-11 04:56:24.000000000 +0300
+@@ -66,6 +66,7 @@
+ 	if (!error)
+ 		return 0;
+ 
++	kobject_put(target);
+ 	kfree(sl->link_name);
+ exit2:
+ 	kfree(sl);
+diff -Naur linux-2.6.16/fs/xfs/linux-2.6/xfs_aops.c linux-2.6.16.16/fs/xfs/linux-2.6/xfs_aops.c
+--- linux-2.6.16/fs/xfs/linux-2.6/xfs_aops.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/xfs/linux-2.6/xfs_aops.c	2006-05-11 04:56:24.000000000 +0300
+@@ -616,7 +616,7 @@
+ 				acceptable = (type == IOMAP_UNWRITTEN);
+ 			else if (buffer_delay(bh))
+ 				acceptable = (type == IOMAP_DELAY);
+-			else if (buffer_mapped(bh))
++			else if (buffer_dirty(bh) && buffer_mapped(bh))
+ 				acceptable = (type == 0);
+ 			else
+ 				break;
+diff -Naur linux-2.6.16/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.16.16/fs/xfs/linux-2.6/xfs_iops.c
+--- linux-2.6.16/fs/xfs/linux-2.6/xfs_iops.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/fs/xfs/linux-2.6/xfs_iops.c	2006-05-11 04:56:24.000000000 +0300
+@@ -673,8 +673,7 @@
+ 	if (ia_valid & ATTR_ATIME) {
+ 		vattr.va_mask |= XFS_AT_ATIME;
+ 		vattr.va_atime = attr->ia_atime;
+-		if (ia_valid & ATTR_ATIME_SET)
+-			inode->i_atime = attr->ia_atime;
++		inode->i_atime = attr->ia_atime;
+ 	}
+ 	if (ia_valid & ATTR_MTIME) {
+ 		vattr.va_mask |= XFS_AT_MTIME;
+diff -Naur linux-2.6.16/include/asm-i386/cpufeature.h linux-2.6.16.16/include/asm-i386/cpufeature.h
+--- linux-2.6.16/include/asm-i386/cpufeature.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-i386/cpufeature.h	2006-05-11 04:56:24.000000000 +0300
+@@ -70,6 +70,7 @@
+ #define X86_FEATURE_P3		(3*32+ 6) /* P3 */
+ #define X86_FEATURE_P4		(3*32+ 7) /* P4 */
+ #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
++#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
+ 
+ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
+ #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
+diff -Naur linux-2.6.16/include/asm-i386/i387.h linux-2.6.16.16/include/asm-i386/i387.h
+--- linux-2.6.16/include/asm-i386/i387.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-i386/i387.h	2006-05-11 04:56:24.000000000 +0300
+@@ -13,6 +13,7 @@
+ 
+ #include <linux/sched.h>
+ #include <linux/init.h>
++#include <linux/kernel_stat.h>
+ #include <asm/processor.h>
+ #include <asm/sigcontext.h>
+ #include <asm/user.h>
+@@ -38,17 +39,38 @@
+ extern void kernel_fpu_begin(void);
+ #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
+ 
++/* We need a safe address that is cheap to find and that is already
++   in L1 during context switch. The best choices are unfortunately
++   different for UP and SMP */
++#ifdef CONFIG_SMP
++#define safe_address (__per_cpu_offset[0])
++#else
++#define safe_address (kstat_cpu(0).cpustat.user)
++#endif
++
+ /*
+  * These must be called with preempt disabled
+  */
+ static inline void __save_init_fpu( struct task_struct *tsk )
+ {
++	/* Use more nops than strictly needed in case the compiler
++	   varies code */
+ 	alternative_input(
+-		"fnsave %1 ; fwait ;" GENERIC_NOP2,
+-		"fxsave %1 ; fnclex",
++		"fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
++		"fxsave %[fx]\n"
++		"bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
+ 		X86_FEATURE_FXSR,
+-		"m" (tsk->thread.i387.fxsave)
+-		:"memory");
++		[fx] "m" (tsk->thread.i387.fxsave),
++		[fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
++	/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
++	   is pending.  Clear the x87 state here by setting it to fixed
++   	   values. safe_address is a random variable that should be in L1 */
++	alternative_input(
++		GENERIC_NOP8 GENERIC_NOP2,
++		"emms\n\t"	  	/* clear stack tags */
++		"fildl %[addr]", 	/* set F?P to defined value */
++		X86_FEATURE_FXSAVE_LEAK,
++		[addr] "m" (safe_address));
+ 	task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ }
+ 
+diff -Naur linux-2.6.16/include/asm-i386/pgtable-2level.h linux-2.6.16.16/include/asm-i386/pgtable-2level.h
+--- linux-2.6.16/include/asm-i386/pgtable-2level.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-i386/pgtable-2level.h	2006-05-11 04:56:24.000000000 +0300
+@@ -18,6 +18,9 @@
+ #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
+ #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
+ 
++#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
++#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
++
+ #define ptep_get_and_clear(mm,addr,xp)	__pte(xchg(&(xp)->pte_low, 0))
+ #define pte_same(a, b)		((a).pte_low == (b).pte_low)
+ #define pte_page(x)		pfn_to_page(pte_pfn(x))
+diff -Naur linux-2.6.16/include/asm-i386/pgtable-3level.h linux-2.6.16.16/include/asm-i386/pgtable-3level.h
+--- linux-2.6.16/include/asm-i386/pgtable-3level.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-i386/pgtable-3level.h	2006-05-11 04:56:24.000000000 +0300
+@@ -85,6 +85,26 @@
+ #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+ 			pmd_index(address))
+ 
++/*
++ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
++ * entry, so clear the bottom half first and enforce ordering with a compiler
++ * barrier.
++ */
++static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	ptep->pte_low = 0;
++	smp_wmb();
++	ptep->pte_high = 0;
++}
++
++static inline void pmd_clear(pmd_t *pmd)
++{
++	u32 *tmp = (u32 *)pmd;
++	*tmp = 0;
++	smp_wmb();
++	*(tmp + 1) = 0;
++}
++
+ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+ 	pte_t res;
+diff -Naur linux-2.6.16/include/asm-i386/pgtable.h linux-2.6.16.16/include/asm-i386/pgtable.h
+--- linux-2.6.16/include/asm-i386/pgtable.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-i386/pgtable.h	2006-05-11 04:56:24.000000000 +0300
+@@ -204,12 +204,10 @@
+ extern unsigned long pg0[];
+ 
+ #define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
+-#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
+ 
+ /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
+ #define pmd_none(x)	(!(unsigned long)pmd_val(x))
+ #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+-#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+ #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+ 
+ 
+@@ -269,7 +267,7 @@
+ 	pte_t pte;
+ 	if (full) {
+ 		pte = *ptep;
+-		*ptep = __pte(0);
++		pte_clear(mm, addr, ptep);
+ 	} else {
+ 		pte = ptep_get_and_clear(mm, addr, ptep);
+ 	}
+diff -Naur linux-2.6.16/include/asm-m32r/smp.h linux-2.6.16.16/include/asm-m32r/smp.h
+--- linux-2.6.16/include/asm-m32r/smp.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-m32r/smp.h	2006-05-11 04:56:24.000000000 +0300
+@@ -67,7 +67,8 @@
+ #define raw_smp_processor_id()	(current_thread_info()->cpu)
+ 
+ extern cpumask_t cpu_callout_map;
+-#define cpu_possible_map cpu_callout_map
++extern cpumask_t cpu_possible_map;
++extern cpumask_t cpu_present_map;
+ 
+ static __inline__ int hard_smp_processor_id(void)
+ {
+diff -Naur linux-2.6.16/include/asm-m32r/uaccess.h linux-2.6.16.16/include/asm-m32r/uaccess.h
+--- linux-2.6.16/include/asm-m32r/uaccess.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-m32r/uaccess.h	2006-05-11 04:56:24.000000000 +0300
+@@ -5,17 +5,9 @@
+  *  linux/include/asm-m32r/uaccess.h
+  *
+  *  M32R version.
+- *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
++ *    Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+  */
+ 
+-#undef UACCESS_DEBUG
+-
+-#ifdef UACCESS_DEBUG
+-#define UAPRINTK(args...) printk(args)
+-#else
+-#define UAPRINTK(args...)
+-#endif /* UACCESS_DEBUG */
+-
+ /*
+  * User space memory access functions
+  */
+@@ -38,27 +30,29 @@
+ #define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+ 
+ #ifdef CONFIG_MMU
++
+ #define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+ #define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
+-#else
+-#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+-#define USER_DS		MAKE_MM_SEG(0xFFFFFFFF)
+-#endif /* CONFIG_MMU */
+-
+ #define get_ds()	(KERNEL_DS)
+-#ifdef CONFIG_MMU
+ #define get_fs()	(current_thread_info()->addr_limit)
+ #define set_fs(x)	(current_thread_info()->addr_limit = (x))
+-#else
++
++#else /* not CONFIG_MMU */
++
++#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
++#define USER_DS		MAKE_MM_SEG(0xFFFFFFFF)
++#define get_ds()	(KERNEL_DS)
++
+ static inline mm_segment_t get_fs(void)
+ {
+-  return USER_DS;
++	return USER_DS;
+ }
+ 
+ static inline void set_fs(mm_segment_t s)
+ {
+ }
+-#endif /* CONFIG_MMU */
++
++#endif /* not CONFIG_MMU */
+ 
+ #define segment_eq(a,b)	((a).seg == (b).seg)
+ 
+@@ -83,9 +77,9 @@
+ 		"	subx	%0, %0\n"				\
+ 		"	cmpu	%4, %1\n"				\
+ 		"	subx	%0, %5\n"				\
+-		: "=&r"(flag), "=r"(sum)				\
+-		: "1"(addr), "r"((int)(size)), 				\
+-		  "r"(current_thread_info()->addr_limit.seg), "r"(0)	\
++		: "=&r" (flag), "=r" (sum)				\
++		: "1" (addr), "r" ((int)(size)), 			\
++		  "r" (current_thread_info()->addr_limit.seg), "r" (0)	\
+ 		: "cbit" );						\
+ 	flag; })
+ 
+@@ -113,10 +107,10 @@
+ #else
+ static inline int access_ok(int type, const void *addr, unsigned long size)
+ {
+-  extern unsigned long memory_start, memory_end;
+-  unsigned long val = (unsigned long)addr;
++	extern unsigned long memory_start, memory_end;
++	unsigned long val = (unsigned long)addr;
+ 
+-  return ((val >= memory_start) && ((val + size) < memory_end));
++	return ((val >= memory_start) && ((val + size) < memory_end));
+ }
+ #endif /* CONFIG_MMU */
+ 
+@@ -155,39 +149,6 @@
+  * accesses to the same area of user memory).
+  */
+ 
+-extern void __get_user_1(void);
+-extern void __get_user_2(void);
+-extern void __get_user_4(void);
+-
+-#ifndef MODULE
+-#define __get_user_x(size,ret,x,ptr) 					\
+-	__asm__ __volatile__(						\
+-		"	mv	r0, %0\n"				\
+-		"	mv	r1, %1\n" 				\
+-		"	bl __get_user_" #size "\n"			\
+-		"	mv	%0, r0\n"				\
+-		"	mv	%1, r1\n" 				\
+-		: "=r"(ret), "=r"(x) 					\
+-		: "0"(ptr)						\
+-		: "r0", "r1", "r14" )
+-#else /* MODULE */
+-/*
+- * Use "jl" instead of "bl" for MODULE
+- */
+-#define __get_user_x(size,ret,x,ptr) 					\
+-	__asm__ __volatile__(						\
+-		"	mv	r0, %0\n"				\
+-		"	mv	r1, %1\n" 				\
+-		"	seth	lr, #high(__get_user_" #size ")\n"	\
+-		"	or3	lr, lr, #low(__get_user_" #size ")\n"	\
+-		"	jl 	lr\n"					\
+-		"	mv	%0, r0\n"				\
+-		"	mv	%1, r1\n" 				\
+-		: "=r"(ret), "=r"(x) 					\
+-		: "0"(ptr)						\
+-		: "r0", "r1", "r14" )
+-#endif
+-
+ /* Careful: we have to cast the result to the type of the pointer for sign
+    reasons */
+ /**
+@@ -208,20 +169,7 @@
+  * On error, the variable @x is set to zero.
+  */
+ #define get_user(x,ptr)							\
+-({	int __ret_gu;							\
+-	unsigned long __val_gu;						\
+-	__chk_user_ptr(ptr);						\
+-	switch(sizeof (*(ptr))) {					\
+-	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
+-	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;		\
+-	case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;		\
+-	default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;		\
+-	}								\
+-	(x) = (__typeof__(*(ptr)))__val_gu;				\
+-	__ret_gu;							\
+-})
+-
+-extern void __put_user_bad(void);
++	__get_user_check((x),(ptr),sizeof(*(ptr)))
+ 
+ /**
+  * put_user: - Write a simple value into user space.
+@@ -240,8 +188,7 @@
+  * Returns zero on success, or -EFAULT on error.
+  */
+ #define put_user(x,ptr)							\
+-  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+-
++	__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+ 
+ /**
+  * __get_user: - Get a simple variable from user space, with less checking.
+@@ -264,8 +211,64 @@
+  * On error, the variable @x is set to zero.
+  */
+ #define __get_user(x,ptr) \
+-  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
++	__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+ 
++#define __get_user_nocheck(x,ptr,size)					\
++({									\
++	long __gu_err = 0;						\
++	unsigned long __gu_val;						\
++	might_sleep();							\
++	__get_user_size(__gu_val,(ptr),(size),__gu_err);		\
++	(x) = (__typeof__(*(ptr)))__gu_val;				\
++	__gu_err;							\
++})
++
++#define __get_user_check(x,ptr,size)					\
++({									\
++	long __gu_err = -EFAULT;					\
++	unsigned long __gu_val = 0;					\
++	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
++	might_sleep();							\
++	if (access_ok(VERIFY_READ,__gu_addr,size))			\
++		__get_user_size(__gu_val,__gu_addr,(size),__gu_err);	\
++	(x) = (__typeof__(*(ptr)))__gu_val;				\
++	__gu_err;							\
++})
++
++extern long __get_user_bad(void);
++
++#define __get_user_size(x,ptr,size,retval)				\
++do {									\
++	retval = 0;							\
++	__chk_user_ptr(ptr);						\
++	switch (size) {							\
++	  case 1: __get_user_asm(x,ptr,retval,"ub"); break;		\
++	  case 2: __get_user_asm(x,ptr,retval,"uh"); break;		\
++	  case 4: __get_user_asm(x,ptr,retval,""); break;		\
++	  default: (x) = __get_user_bad();				\
++	}								\
++} while (0)
++
++#define __get_user_asm(x, addr, err, itype)				\
++	__asm__ __volatile__(						\
++		"	.fillinsn\n"					\
++		"1:	ld"itype" %1,@%2\n"				\
++		"	.fillinsn\n"					\
++		"2:\n"							\
++		".section .fixup,\"ax\"\n"				\
++		"	.balign 4\n"					\
++		"3:	ldi %0,%3\n"					\
++		"	seth r14,#high(2b)\n"				\
++		"	or3 r14,r14,#low(2b)\n"				\
++		"	jmp r14\n"					\
++		".previous\n"						\
++		".section __ex_table,\"a\"\n"				\
++		"	.balign 4\n"					\
++		"	.long 1b,3b\n"					\
++		".previous"						\
++		: "=&r" (err), "=&r" (x)				\
++		: "r" (addr), "i" (-EFAULT), "0" (err)			\
++		: "r14", "memory")
+ 
+ /**
+  * __put_user: - Write a simple value into user space, with less checking.
+@@ -287,11 +290,13 @@
+  * Returns zero on success, or -EFAULT on error.
+  */
+ #define __put_user(x,ptr) \
+-  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++	__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++
+ 
+ #define __put_user_nocheck(x,ptr,size)					\
+ ({									\
+ 	long __pu_err;							\
++	might_sleep();							\
+ 	__put_user_size((x),(ptr),(size),__pu_err);			\
+ 	__pu_err;							\
+ })
+@@ -308,28 +313,28 @@
+ })
+ 
+ #if defined(__LITTLE_ENDIAN__)
+-#define __put_user_u64(x, addr, err)                                    \
+-        __asm__ __volatile__(                                           \
+-                "       .fillinsn\n"                                    \
+-                "1:     st %L1,@%2\n"                                    \
+-                "       .fillinsn\n"                                    \
+-                "2:     st %H1,@(4,%2)\n"                                \
+-                "       .fillinsn\n"                                    \
+-                "3:\n"                                                  \
+-                ".section .fixup,\"ax\"\n"                              \
+-                "       .balign 4\n"                                    \
+-                "4:     ldi %0,%3\n"                                    \
+-                "       seth r14,#high(3b)\n"                           \
+-                "       or3 r14,r14,#low(3b)\n"                         \
+-                "       jmp r14\n"                                      \
+-                ".previous\n"                                           \
+-                ".section __ex_table,\"a\"\n"                           \
+-                "       .balign 4\n"                                    \
+-                "       .long 1b,4b\n"                                  \
+-                "       .long 2b,4b\n"                                  \
+-                ".previous"                                             \
+-                : "=&r"(err)                                             \
+-                : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
++#define __put_user_u64(x, addr, err)					\
++        __asm__ __volatile__(						\
++                "       .fillinsn\n"					\
++                "1:     st %L1,@%2\n"					\
++                "       .fillinsn\n"					\
++                "2:     st %H1,@(4,%2)\n"				\
++                "       .fillinsn\n"					\
++                "3:\n"							\
++                ".section .fixup,\"ax\"\n"				\
++                "       .balign 4\n"					\
++                "4:     ldi %0,%3\n"					\
++                "       seth r14,#high(3b)\n"				\
++                "       or3 r14,r14,#low(3b)\n"				\
++                "       jmp r14\n"					\
++                ".previous\n"						\
++                ".section __ex_table,\"a\"\n"				\
++                "       .balign 4\n"					\
++                "       .long 1b,4b\n"					\
++                "       .long 2b,4b\n"					\
++                ".previous"						\
++                : "=&r" (err)						\
++                : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)		\
+                 : "r14", "memory")
+ 
+ #elif defined(__BIG_ENDIAN__)
+@@ -353,13 +358,15 @@
+ 		"	.long 1b,4b\n"					\
+ 		"	.long 2b,4b\n"					\
+ 		".previous"						\
+-		: "=&r"(err)						\
+-		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
++		: "=&r" (err)						\
++		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)		\
+ 		: "r14", "memory")
+ #else
+ #error no endian defined
+ #endif
+ 
++extern void __put_user_bad(void);
++
+ #define __put_user_size(x,ptr,size,retval)				\
+ do {									\
+ 	retval = 0;							\
+@@ -398,52 +405,8 @@
+ 		"	.balign 4\n"					\
+ 		"	.long 1b,3b\n"					\
+ 		".previous"						\
+-		: "=&r"(err)						\
+-		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
+-		: "r14", "memory")
+-
+-#define __get_user_nocheck(x,ptr,size)					\
+-({									\
+-	long __gu_err;							\
+-	unsigned long __gu_val;						\
+-	__get_user_size(__gu_val,(ptr),(size),__gu_err);		\
+-	(x) = (__typeof__(*(ptr)))__gu_val;				\
+-	__gu_err;							\
+-})
+-
+-extern long __get_user_bad(void);
+-
+-#define __get_user_size(x,ptr,size,retval)				\
+-do {									\
+-	retval = 0;							\
+-	__chk_user_ptr(ptr);						\
+-	switch (size) {							\
+-	  case 1: __get_user_asm(x,ptr,retval,"ub"); break;		\
+-	  case 2: __get_user_asm(x,ptr,retval,"uh"); break;		\
+-	  case 4: __get_user_asm(x,ptr,retval,""); break;		\
+-	  default: (x) = __get_user_bad();				\
+-	}								\
+-} while (0)
+-
+-#define __get_user_asm(x, addr, err, itype)				\
+-	__asm__ __volatile__(						\
+-		"	.fillinsn\n"					\
+-		"1:	ld"itype" %1,@%2\n"				\
+-		"	.fillinsn\n"					\
+-		"2:\n"							\
+-		".section .fixup,\"ax\"\n"				\
+-		"	.balign 4\n"					\
+-		"3:	ldi %0,%3\n"					\
+-		"	seth r14,#high(2b)\n"				\
+-		"	or3 r14,r14,#low(2b)\n"				\
+-		"	jmp r14\n"					\
+-		".previous\n"						\
+-		".section __ex_table,\"a\"\n"				\
+-		"	.balign 4\n"					\
+-		"	.long 1b,3b\n"					\
+-		".previous"						\
+-		: "=&r"(err), "=&r"(x)					\
+-		: "r"(addr), "i"(-EFAULT), "0"(err)			\
++		: "=&r" (err)						\
++		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)		\
+ 		: "r14", "memory")
+ 
+ /*
+@@ -453,7 +416,6 @@
+  * anything, so this is accurate.
+  */
+ 
+-
+ /*
+  * Copy To/From Userspace
+  */
+@@ -511,8 +473,9 @@
+ 		"	.long 2b,9b\n"					\
+ 		"	.long 3b,9b\n"					\
+ 		".previous\n"						\
+-		: "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)	\
+-		: "0"(to), "1"(from), "2"(size), "3"(size / 4)		\
++		: "=&r" (__dst), "=&r" (__src), "=&r" (size),		\
++		  "=&r" (__c)						\
++		: "0" (to), "1" (from), "2" (size), "3" (size / 4)	\
+ 		: "r14", "memory");					\
+ } while (0)
+ 
+@@ -573,8 +536,9 @@
+ 		"	.long 2b,7b\n"					\
+ 		"	.long 3b,7b\n"					\
+ 		".previous\n"						\
+-		: "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)	\
+-		: "0"(to), "1"(from), "2"(size), "3"(size / 4)		\
++		: "=&r" (__dst), "=&r" (__src), "=&r" (size),		\
++		  "=&r" (__c)						\
++		: "0" (to), "1" (from), "2" (size), "3" (size / 4)	\
+ 		: "r14", "memory");					\
+ } while (0)
+ 
+@@ -676,7 +640,7 @@
+ #define copy_from_user(to,from,n)			\
+ ({							\
+ 	might_sleep();					\
+-__generic_copy_from_user((to),(from),(n));	\
++	__generic_copy_from_user((to),(from),(n));	\
+ })
+ 
+ long __must_check strncpy_from_user(char *dst, const char __user *src,
+diff -Naur linux-2.6.16/include/asm-mips/bitops.h linux-2.6.16.16/include/asm-mips/bitops.h
+--- linux-2.6.16/include/asm-mips/bitops.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-mips/bitops.h	2006-05-11 04:56:24.000000000 +0300
+@@ -654,7 +654,12 @@
+ {
+ #ifdef CONFIG_32BIT
+ #ifdef CONFIG_CPU_MIPS32
+-	__asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
++	__asm__ (
++	"	.set	mips32					\n"
++	"	clz	%0, %1					\n"
++	"	.set	mips0					\n"
++	: "=r" (word)
++	: "r" (word));
+ 
+ 	return 32 - word;
+ #else
+@@ -678,7 +683,12 @@
+ #ifdef CONFIG_64BIT
+ #ifdef CONFIG_CPU_MIPS64
+ 
+-	__asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
++	__asm__ (
++	"	.set	mips64					\n"
++	"	dclz	%0, %1					\n"
++	"	.set	mips0					\n"
++	: "=r" (word)
++	: "r" (word));
+ 
+ 	return 64 - word;
+ #else
+diff -Naur linux-2.6.16/include/asm-mips/byteorder.h linux-2.6.16.16/include/asm-mips/byteorder.h
+--- linux-2.6.16/include/asm-mips/byteorder.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-mips/byteorder.h	2006-05-11 04:56:24.000000000 +0300
+@@ -19,7 +19,9 @@
+ static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+ {
+ 	__asm__(
++	"	.set	mips32r2		\n"
+ 	"	wsbh	%0, %1			\n"
++	"	.set	mips0			\n"
+ 	: "=r" (x)
+ 	: "r" (x));
+ 
+@@ -30,8 +32,10 @@
+ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+ {
+ 	__asm__(
++	"	.set	mips32r2		\n"
+ 	"	wsbh	%0, %1			\n"
+ 	"	rotr	%0, %0, 16		\n"
++	"	.set	mips0			\n"
+ 	: "=r" (x)
+ 	: "r" (x));
+ 
+diff -Naur linux-2.6.16/include/asm-mips/interrupt.h linux-2.6.16.16/include/asm-mips/interrupt.h
+--- linux-2.6.16/include/asm-mips/interrupt.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-mips/interrupt.h	2006-05-11 04:56:24.000000000 +0300
+@@ -20,7 +20,9 @@
+ 	"	.set	reorder						\n"
+ 	"	.set	noat						\n"
+ #ifdef CONFIG_CPU_MIPSR2
++	"	.set	mips32r2					\n"
+ 	"	ei							\n"
++	"	.set	mips0						\n"
+ #else
+ 	"	mfc0	$1,$12						\n"
+ 	"	ori	$1,0x1f						\n"
+@@ -63,7 +65,9 @@
+ 	"	.set	push						\n"
+ 	"	.set	noat						\n"
+ #ifdef CONFIG_CPU_MIPSR2
++	"	.set	mips32r2					\n"
+ 	"	di							\n"
++	"	.set	mips0						\n"
+ #else
+ 	"	mfc0	$1,$12						\n"
+ 	"	ori	$1,0x1f						\n"
+@@ -103,8 +107,10 @@
+ 	"	.set	reorder						\n"
+ 	"	.set	noat						\n"
+ #ifdef CONFIG_CPU_MIPSR2
++	"	.set	mips32r2					\n"
+ 	"	di	\\result					\n"
+ 	"	andi	\\result, 1					\n"
++	"	.set	mips0						\n"
+ #else
+ 	"	mfc0	\\result, $12					\n"
+ 	"	ori	$1, \\result, 0x1f				\n"
+@@ -133,9 +139,11 @@
+ 	 * Slow, but doesn't suffer from a relativly unlikely race
+ 	 * condition we're having since days 1.
+ 	 */
++	"	.set	mips32r2					\n"
+ 	"	beqz	\\flags, 1f					\n"
+ 	"	 di							\n"
+ 	"	ei							\n"
++	"	.set	mips0						\n"
+ 	"1:								\n"
+ #elif defined(CONFIG_CPU_MIPSR2)
+ 	/*
+diff -Naur linux-2.6.16/include/asm-mips/r4kcache.h linux-2.6.16.16/include/asm-mips/r4kcache.h
+--- linux-2.6.16/include/asm-mips/r4kcache.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-mips/r4kcache.h	2006-05-11 04:56:24.000000000 +0300
+@@ -37,7 +37,7 @@
+ 	"	cache	%0, %1					\n"	\
+ 	"	.set	pop					\n"	\
+ 	:								\
+-	: "i" (op), "m" (*(unsigned char *)(addr)))
++	: "i" (op), "R" (*(unsigned char *)(addr)))
+ 
+ static inline void flush_icache_line_indexed(unsigned long addr)
+ {
+diff -Naur linux-2.6.16/include/asm-powerpc/floppy.h linux-2.6.16.16/include/asm-powerpc/floppy.h
+--- linux-2.6.16/include/asm-powerpc/floppy.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-powerpc/floppy.h	2006-05-11 04:56:24.000000000 +0300
+@@ -35,6 +35,7 @@
+ #ifdef CONFIG_PCI
+ 
+ #include <linux/pci.h>
++#include <asm/ppc-pci.h>	/* for ppc64_isabridge_dev */
+ 
+ #define fd_dma_setup(addr,size,mode,io) powerpc_fd_dma_setup(addr,size,mode,io)
+ 
+@@ -52,12 +53,12 @@
+ 	if (bus_addr 
+ 	    && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
+ 		/* different from last time -- unmap prev */
+-		pci_unmap_single(NULL, bus_addr, prev_size, prev_dir);
++		pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir);
+ 		bus_addr = 0;
+ 	}
+ 
+ 	if (!bus_addr)	/* need to map it */
+-		bus_addr = pci_map_single(NULL, addr, size, dir);
++		bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir);
+ 
+ 	/* remember this one as prev */
+ 	prev_addr = addr;
+diff -Naur linux-2.6.16/include/asm-x86_64/cpufeature.h linux-2.6.16.16/include/asm-x86_64/cpufeature.h
+--- linux-2.6.16/include/asm-x86_64/cpufeature.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-x86_64/cpufeature.h	2006-05-11 04:56:24.000000000 +0300
+@@ -64,6 +64,7 @@
+ #define X86_FEATURE_REP_GOOD	(3*32+ 4) /* rep microcode works well on this CPU */
+ #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
+ #define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
++#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
+ 
+ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
+ #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
+diff -Naur linux-2.6.16/include/asm-x86_64/i387.h linux-2.6.16.16/include/asm-x86_64/i387.h
+--- linux-2.6.16/include/asm-x86_64/i387.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/asm-x86_64/i387.h	2006-05-11 04:56:24.000000000 +0300
+@@ -72,6 +72,23 @@
+ #define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
+ #define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
+ 
++#define X87_FSW_ES (1 << 7)	/* Exception Summary */
++
++/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
++   is pending. Clear the x87 state here by setting it to fixed
++   values. The kernel data segment can be sometimes 0 and sometimes
++   new user value. Both should be ok.
++   Use the PDA as safe address because it should be already in L1. */
++static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
++{
++	if (unlikely(fx->swd & X87_FSW_ES))
++		 asm volatile("fnclex");
++	alternative_input(ASM_NOP8 ASM_NOP2,
++	     	     "    emms\n"		/* clear stack tags */
++	     	     "    fildl %%gs:0",	/* load to clear state */
++		     X86_FEATURE_FXSAVE_LEAK);
++}
++
+ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) 
+ { 
+ 	int err;
+@@ -119,6 +136,7 @@
+ #endif
+ 	if (unlikely(err))
+ 		__clear_user(fx, sizeof(struct i387_fxsave_struct));
++	/* No need to clear here because the caller clears USED_MATH */
+ 	return err;
+ } 
+ 
+@@ -149,7 +167,7 @@
+ 				"i" (offsetof(__typeof__(*tsk),
+ 					      thread.i387.fxsave)));
+ #endif
+-	__asm__ __volatile__("fnclex");
++	clear_fpu_state(&tsk->thread.i387.fxsave);
+ }
+ 
+ static inline void kernel_fpu_begin(void)
+diff -Naur linux-2.6.16/include/linux/cpu.h linux-2.6.16.16/include/linux/cpu.h
+--- linux-2.6.16/include/linux/cpu.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/cpu.h	2006-05-11 04:56:24.000000000 +0300
+@@ -32,7 +32,7 @@
+ };
+ 
+ extern int register_cpu(struct cpu *, int, struct node *);
+-extern struct sys_device *get_cpu_sysdev(int cpu);
++extern struct sys_device *get_cpu_sysdev(unsigned cpu);
+ #ifdef CONFIG_HOTPLUG_CPU
+ extern void unregister_cpu(struct cpu *, struct node *);
+ #endif
+diff -Naur linux-2.6.16/include/linux/cpumask.h linux-2.6.16.16/include/linux/cpumask.h
+--- linux-2.6.16/include/linux/cpumask.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/cpumask.h	2006-05-11 04:56:24.000000000 +0300
+@@ -408,6 +408,7 @@
+ })
+ 
+ #define for_each_cpu(cpu)	  for_each_cpu_mask((cpu), cpu_possible_map)
++#define for_each_possible_cpu(cpu)  for_each_cpu_mask((cpu), cpu_possible_map)
+ #define for_each_online_cpu(cpu)  for_each_cpu_mask((cpu), cpu_online_map)
+ #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
+ 
+diff -Naur linux-2.6.16/include/linux/fb.h linux-2.6.16.16/include/linux/fb.h
+--- linux-2.6.16/include/linux/fb.h	2006-05-18 01:12:24.000000000 +0300
++++ linux-2.6.16.16/include/linux/fb.h	2006-05-17 21:41:31.000000000 +0300
+@@ -840,12 +840,10 @@
+ #define FB_LEFT_POS(bpp)          (32 - bpp)
+ #define FB_SHIFT_HIGH(val, bits)  ((val) >> (bits))
+ #define FB_SHIFT_LOW(val, bits)   ((val) << (bits))
+-#define FB_BIT_NR(b)              (7 - (b))
+ #else
+ #define FB_LEFT_POS(bpp)          (0)
+ #define FB_SHIFT_HIGH(val, bits)  ((val) << (bits))
+ #define FB_SHIFT_LOW(val, bits)   ((val) >> (bits))
+-#define FB_BIT_NR(b)              (b)
+ #endif
+ 
+     /*
+diff -Naur linux-2.6.16/include/linux/fs.h linux-2.6.16.16/include/linux/fs.h
+--- linux-2.6.16/include/linux/fs.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/fs.h	2006-05-11 04:56:24.000000000 +0300
+@@ -1383,6 +1383,7 @@
+ extern void bd_release(struct block_device *);
+ 
+ /* fs/char_dev.c */
++#define CHRDEV_MAJOR_HASH_SIZE	255
+ extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
+ extern int register_chrdev_region(dev_t, unsigned, const char *);
+ extern int register_chrdev(unsigned int, const char *,
+@@ -1390,25 +1391,17 @@
+ extern int unregister_chrdev(unsigned int, const char *);
+ extern void unregister_chrdev_region(dev_t, unsigned);
+ extern int chrdev_open(struct inode *, struct file *);
+-extern int get_chrdev_list(char *);
+-extern void *acquire_chrdev_list(void);
+-extern int count_chrdev_list(void);
+-extern void *get_next_chrdev(void *);
+-extern int get_chrdev_info(void *, int *, char **);
+-extern void release_chrdev_list(void *);
++extern void chrdev_show(struct seq_file *,off_t);
+ 
+ /* fs/block_dev.c */
++#define BLKDEV_MAJOR_HASH_SIZE	255
+ #define BDEVNAME_SIZE	32	/* Largest string for a blockdev identifier */
+ extern const char *__bdevname(dev_t, char *buffer);
+ extern const char *bdevname(struct block_device *bdev, char *buffer);
+ extern struct block_device *lookup_bdev(const char *);
+ extern struct block_device *open_bdev_excl(const char *, int, void *);
+ extern void close_bdev_excl(struct block_device *);
+-extern void *acquire_blkdev_list(void);
+-extern int count_blkdev_list(void);
+-extern void *get_next_blkdev(void *);
+-extern int get_blkdev_info(void *, int *, char **);
+-extern void release_blkdev_list(void *);
++extern void blkdev_show(struct seq_file *,off_t);
+ 
+ extern void init_special_inode(struct inode *, umode_t, dev_t);
+ 
+diff -Naur linux-2.6.16/include/linux/mm.h linux-2.6.16.16/include/linux/mm.h
+--- linux-2.6.16/include/linux/mm.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/mm.h	2006-05-11 04:56:24.000000000 +0300
+@@ -229,10 +229,9 @@
+ 		unsigned long private;		/* Mapping-private opaque data:
+ 					 	 * usually used for buffer_heads
+ 						 * if PagePrivate set; used for
+-						 * swp_entry_t if PageSwapCache.
+-						 * When page is free, this
++						 * swp_entry_t if PageSwapCache;
+ 						 * indicates order in the buddy
+-						 * system.
++						 * system if PG_buddy is set.
+ 						 */
+ 		struct address_space *mapping;	/* If low bit clear, points to
+ 						 * inode address_space, or NULL.
+diff -Naur linux-2.6.16/include/linux/page-flags.h linux-2.6.16.16/include/linux/page-flags.h
+--- linux-2.6.16/include/linux/page-flags.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/page-flags.h	2006-05-11 04:56:24.000000000 +0300
+@@ -74,7 +74,9 @@
+ #define PG_mappedtodisk		16	/* Has blocks allocated on-disk */
+ #define PG_reclaim		17	/* To be reclaimed asap */
+ #define PG_nosave_free		18	/* Free, should not be written */
+-#define PG_uncached		19	/* Page has been mapped as uncached */
++#define PG_buddy		19	/* Page is free, on buddy lists */
++
++#define PG_uncached		20	/* Page has been mapped as uncached */
+ 
+ /*
+  * Global page accounting.  One instance per CPU.  Only unsigned longs are
+@@ -319,6 +321,10 @@
+ #define SetPageNosaveFree(page)	set_bit(PG_nosave_free, &(page)->flags)
+ #define ClearPageNosaveFree(page)		clear_bit(PG_nosave_free, &(page)->flags)
+ 
++#define PageBuddy(page)		test_bit(PG_buddy, &(page)->flags)
++#define __SetPageBuddy(page)	__set_bit(PG_buddy, &(page)->flags)
++#define __ClearPageBuddy(page)	__clear_bit(PG_buddy, &(page)->flags)
++
+ #define PageMappedToDisk(page)	test_bit(PG_mappedtodisk, &(page)->flags)
+ #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
+ #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
+diff -Naur linux-2.6.16/include/linux/proc_fs.h linux-2.6.16.16/include/linux/proc_fs.h
+--- linux-2.6.16/include/linux/proc_fs.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/proc_fs.h	2006-05-11 04:56:24.000000000 +0300
+@@ -78,7 +78,7 @@
+ struct vmcore {
+ 	struct list_head list;
+ 	unsigned long long paddr;
+-	unsigned long size;
++	unsigned long long size;
+ 	loff_t offset;
+ };
+ 
+diff -Naur linux-2.6.16/include/linux/raid/raid1.h linux-2.6.16.16/include/linux/raid/raid1.h
+--- linux-2.6.16/include/linux/raid/raid1.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/raid/raid1.h	2006-05-11 04:56:24.000000000 +0300
+@@ -130,6 +130,6 @@
+  * with failure when last write completes (and all failed).
+  * Record that bi_end_io was called with this flag...
+  */
+-#define	R1BIO_Returned 4
++#define	R1BIO_Returned 6
+ 
+ #endif
+diff -Naur linux-2.6.16/include/linux/rtc.h linux-2.6.16.16/include/linux/rtc.h
+--- linux-2.6.16/include/linux/rtc.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/linux/rtc.h	2006-05-11 04:56:24.000000000 +0300
+@@ -11,8 +11,6 @@
+ #ifndef _LINUX_RTC_H_
+ #define _LINUX_RTC_H_
+ 
+-#include <linux/interrupt.h>
+-
+ /*
+  * The struct used to pass data via the following ioctl. Similar to the
+  * struct tm in <time.h>, but it needs to be here so that the kernel 
+@@ -95,6 +93,8 @@
+ 
+ #ifdef __KERNEL__
+ 
++#include <linux/interrupt.h>
++
+ typedef struct rtc_task {
+ 	void (*func)(void *private_data);
+ 	void *private_data;
+diff -Naur linux-2.6.16/include/net/ip.h linux-2.6.16.16/include/net/ip.h
+--- linux-2.6.16/include/net/ip.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/net/ip.h	2006-05-11 04:56:24.000000000 +0300
+@@ -95,6 +95,7 @@
+ extern int		ip_mr_input(struct sk_buff *skb);
+ extern int		ip_output(struct sk_buff *skb);
+ extern int		ip_mc_output(struct sk_buff *skb);
++extern int		ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+ extern int		ip_do_nat(struct sk_buff *skb);
+ extern void		ip_send_check(struct iphdr *ip);
+ extern int		ip_queue_xmit(struct sk_buff *skb, int ipfragok);
+diff -Naur linux-2.6.16/include/net/sctp/structs.h linux-2.6.16.16/include/net/sctp/structs.h
+--- linux-2.6.16/include/net/sctp/structs.h	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/include/net/sctp/structs.h	2006-05-11 04:56:24.000000000 +0300
+@@ -702,6 +702,7 @@
+ 	__u8 tsn_gap_acked;	/* Is this chunk acked by a GAP ACK? */
+ 	__s8 fast_retransmit;	 /* Is this chunk fast retransmitted? */
+ 	__u8 tsn_missing_report; /* Data chunk missing counter. */
++	__u8 data_accepted; 	/* At least 1 chunk in this packet accepted */
+ };
+ 
+ void sctp_chunk_hold(struct sctp_chunk *);
+diff -Naur linux-2.6.16/ipc/shm.c linux-2.6.16.16/ipc/shm.c
+--- linux-2.6.16/ipc/shm.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/ipc/shm.c	2006-05-11 04:56:24.000000000 +0300
+@@ -161,6 +161,8 @@
+ 	ret = shmem_mmap(file, vma);
+ 	if (ret == 0) {
+ 		vma->vm_ops = &shm_vm_ops;
++		if (!(vma->vm_flags & VM_WRITE))
++			vma->vm_flags &= ~VM_MAYWRITE;
+ 		shm_inc(file->f_dentry->d_inode->i_ino);
+ 	}
+ 
+diff -Naur linux-2.6.16/ipc/util.c linux-2.6.16.16/ipc/util.c
+--- linux-2.6.16/ipc/util.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/ipc/util.c	2006-05-11 04:56:24.000000000 +0300
+@@ -182,8 +182,7 @@
+ 	if(new == NULL)
+ 		return size;
+ 	new->size = newsize;
+-	memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
+-					sizeof(struct ipc_id_ary));
++	memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
+ 	for(i=size;i<newsize;i++) {
+ 		new->p[i] = NULL;
+ 	}
+diff -Naur linux-2.6.16/kernel/auditsc.c linux-2.6.16.16/kernel/auditsc.c
+--- linux-2.6.16/kernel/auditsc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/auditsc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -966,11 +966,6 @@
+ 	if (context->in_syscall) {
+ 		struct audit_context *newctx;
+ 
+-#if defined(__NR_vm86) && defined(__NR_vm86old)
+-		/* vm86 mode should only be entered once */
+-		if (major == __NR_vm86 || major == __NR_vm86old)
+-			return;
+-#endif
+ #if AUDIT_DEBUG
+ 		printk(KERN_ERR
+ 		       "audit(:%d) pid=%d in syscall=%d;"
+diff -Naur linux-2.6.16/kernel/exec_domain.c linux-2.6.16.16/kernel/exec_domain.c
+--- linux-2.6.16/kernel/exec_domain.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/exec_domain.c	2006-05-11 04:56:24.000000000 +0300
+@@ -140,6 +140,7 @@
+ 	ep = lookup_exec_domain(personality);
+ 	if (ep == current_thread_info()->exec_domain) {
+ 		current->personality = personality;
++		module_put(ep->module);
+ 		return 0;
+ 	}
+ 
+diff -Naur linux-2.6.16/kernel/fork.c linux-2.6.16.16/kernel/fork.c
+--- linux-2.6.16/kernel/fork.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/fork.c	2006-05-11 04:56:24.000000000 +0300
+@@ -720,7 +720,7 @@
+ 	free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
+ 	free_fd_array(new_fdt->fd, new_fdt->max_fds);
+ 	kmem_cache_free(files_cachep, newf);
+-	goto out;
++	return NULL;
+ }
+ 
+ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
+diff -Naur linux-2.6.16/kernel/power/process.c linux-2.6.16.16/kernel/power/process.c
+--- linux-2.6.16/kernel/power/process.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/power/process.c	2006-05-11 04:56:24.000000000 +0300
+@@ -25,8 +25,7 @@
+ 	    (p->flags & PF_NOFREEZE) ||
+ 	    (p->exit_state == EXIT_ZOMBIE) ||
+ 	    (p->exit_state == EXIT_DEAD) ||
+-	    (p->state == TASK_STOPPED) ||
+-	    (p->state == TASK_TRACED))
++	    (p->state == TASK_STOPPED))
+ 		return 0;
+ 	return 1;
+ }
+diff -Naur linux-2.6.16/kernel/ptrace.c linux-2.6.16.16/kernel/ptrace.c
+--- linux-2.6.16/kernel/ptrace.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/ptrace.c	2006-05-11 04:56:24.000000000 +0300
+@@ -57,10 +57,6 @@
+ 			signal_wake_up(child, 1);
+ 		}
+ 	}
+-	if (child->signal->flags & SIGNAL_GROUP_EXIT) {
+-		sigaddset(&child->pending.signal, SIGKILL);
+-		signal_wake_up(child, 1);
+-	}
+ 	spin_unlock(&child->sighand->siglock);
+ }
+ 
+@@ -82,7 +78,8 @@
+ 		SET_LINKS(child);
+ 	}
+ 
+-	ptrace_untrace(child);
++	if (child->state == TASK_TRACED)
++		ptrace_untrace(child);
+ }
+ 
+ /*
+diff -Naur linux-2.6.16/kernel/sched.c linux-2.6.16.16/kernel/sched.c
+--- linux-2.6.16/kernel/sched.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/sched.c	2006-05-11 04:56:24.000000000 +0300
+@@ -237,6 +237,7 @@
+ 
+ 	task_t *migration_thread;
+ 	struct list_head migration_queue;
++	int cpu;
+ #endif
+ 
+ #ifdef CONFIG_SCHEDSTATS
+@@ -1660,6 +1661,9 @@
+ /*
+  * double_rq_lock - safely lock two runqueues
+  *
++ * We must take them in cpu order to match code in
++ * dependent_sleeper and wake_dependent_sleeper.
++ *
+  * Note this does not disable interrupts like task_rq_lock,
+  * you need to do so manually before calling.
+  */
+@@ -1671,7 +1675,7 @@
+ 		spin_lock(&rq1->lock);
+ 		__acquire(rq2->lock);	/* Fake it out ;) */
+ 	} else {
+-		if (rq1 < rq2) {
++		if (rq1->cpu < rq2->cpu) {
+ 			spin_lock(&rq1->lock);
+ 			spin_lock(&rq2->lock);
+ 		} else {
+@@ -1707,7 +1711,7 @@
+ 	__acquires(this_rq->lock)
+ {
+ 	if (unlikely(!spin_trylock(&busiest->lock))) {
+-		if (busiest < this_rq) {
++		if (busiest->cpu < this_rq->cpu) {
+ 			spin_unlock(&this_rq->lock);
+ 			spin_lock(&busiest->lock);
+ 			spin_lock(&this_rq->lock);
+@@ -6035,6 +6039,7 @@
+ 		rq->push_cpu = 0;
+ 		rq->migration_thread = NULL;
+ 		INIT_LIST_HEAD(&rq->migration_queue);
++		rq->cpu = i;
+ #endif
+ 		atomic_set(&rq->nr_iowait, 0);
+ 
+diff -Naur linux-2.6.16/kernel/signal.c linux-2.6.16.16/kernel/signal.c
+--- linux-2.6.16/kernel/signal.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/signal.c	2006-05-11 04:56:24.000000000 +0300
+@@ -975,7 +975,6 @@
+ 		if (t == NULL)
+ 			/* restart balancing at this thread */
+ 			t = p->signal->curr_target = p;
+-		BUG_ON(t->tgid != p->tgid);
+ 
+ 		while (!wants_signal(sig, t)) {
+ 			t = next_thread(t);
+@@ -1689,6 +1688,7 @@
+ 	/* Let the debugger run.  */
+ 	set_current_state(TASK_TRACED);
+ 	spin_unlock_irq(&current->sighand->siglock);
++	try_to_freeze();
+ 	read_lock(&tasklist_lock);
+ 	if (likely(current->ptrace & PT_PTRACED) &&
+ 	    likely(current->parent != current->real_parent ||
+@@ -1942,9 +1942,9 @@
+ 			/* Let the debugger run.  */
+ 			ptrace_stop(signr, signr, info);
+ 
+-			/* We're back.  Did the debugger cancel the sig or group_exit? */
++			/* We're back.  Did the debugger cancel the sig?  */
+ 			signr = current->exit_code;
+-			if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT)
++			if (signr == 0)
+ 				continue;
+ 
+ 			current->exit_code = 0;
+diff -Naur linux-2.6.16/kernel/sys.c linux-2.6.16.16/kernel/sys.c
+--- linux-2.6.16/kernel/sys.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/sys.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1657,7 +1657,19 @@
+ 	    (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
+ 	     new_rlim.rlim_cur <= cputime_to_secs(
+ 		     current->signal->it_prof_expires))) {
+-		cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur);
++		unsigned long rlim_cur = new_rlim.rlim_cur;
++		cputime_t cputime;
++
++		if (rlim_cur == 0) {
++			/*
++			 * The caller is asking for an immediate RLIMIT_CPU
++			 * expiry.  But we use the zero value to mean "it was
++			 * never set".  So let's cheat and make it one second
++			 * instead
++			 */
++			rlim_cur = 1;
++		}
++		cputime = secs_to_cputime(rlim_cur);
+ 		read_lock(&tasklist_lock);
+ 		spin_lock_irq(&current->sighand->siglock);
+ 		set_process_cpu_timer(current, CPUCLOCK_PROF,
+diff -Naur linux-2.6.16/kernel/uid16.c linux-2.6.16.16/kernel/uid16.c
+--- linux-2.6.16/kernel/uid16.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/kernel/uid16.c	2006-05-11 04:56:24.000000000 +0300
+@@ -20,43 +20,67 @@
+ 
+ asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group)
+ {
+-	return sys_chown(filename, low2highuid(user), low2highgid(group));
++	long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group)
+ {
+-	return sys_lchown(filename, low2highuid(user), low2highgid(group));
++	long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
+ {
+-	return sys_fchown(fd, low2highuid(user), low2highgid(group));
++	long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
+ {
+-	return sys_setregid(low2highgid(rgid), low2highgid(egid));
++	long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_setgid16(old_gid_t gid)
+ {
+-	return sys_setgid(low2highgid(gid));
++	long ret = sys_setgid(low2highgid(gid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
+ {
+-	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
++	long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_setuid16(old_uid_t uid)
+ {
+-	return sys_setuid(low2highuid(uid));
++	long ret = sys_setuid(low2highuid(uid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
+ {
+-	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
+-		low2highuid(suid));
++	long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
++				 low2highuid(suid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid)
+@@ -72,8 +96,11 @@
+ 
+ asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
+ {
+-	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
+-		low2highgid(sgid));
++	long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
++				 low2highgid(sgid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid)
+@@ -89,12 +116,18 @@
+ 
+ asmlinkage long sys_setfsuid16(old_uid_t uid)
+ {
+-	return sys_setfsuid(low2highuid(uid));
++	long ret = sys_setfsuid(low2highuid(uid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ asmlinkage long sys_setfsgid16(old_gid_t gid)
+ {
+-	return sys_setfsgid(low2highgid(gid));
++	long ret = sys_setfsgid(low2highgid(gid));
++	/* avoid REGPARM breakage on x86: */
++	prevent_tail_call(ret);
++	return ret;
+ }
+ 
+ static int groups16_to_user(old_gid_t __user *grouplist,
+diff -Naur linux-2.6.16/Makefile linux-2.6.16.16/Makefile
+--- linux-2.6.16/Makefile	2006-05-18 01:12:20.000000000 +0300
++++ linux-2.6.16.16/Makefile	2006-05-17 21:41:27.000000000 +0300
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 6
+ SUBLEVEL = 16
+-EXTRAVERSION =
++EXTRAVERSION = .16
+ NAME=Sliding Snow Leopard
+ 
+ # *DOCUMENTATION*
+diff -Naur linux-2.6.16/mm/madvise.c linux-2.6.16.16/mm/madvise.c
+--- linux-2.6.16/mm/madvise.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/mm/madvise.c	2006-05-11 04:56:24.000000000 +0300
+@@ -168,6 +168,9 @@
+ 			return -EINVAL;
+ 	}
+ 
++	if ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE))
++		return -EACCES;
++
+ 	mapping = vma->vm_file->f_mapping;
+ 
+ 	offset = (loff_t)(start - vma->vm_start)
+diff -Naur linux-2.6.16/mm/page_alloc.c linux-2.6.16.16/mm/page_alloc.c
+--- linux-2.6.16/mm/page_alloc.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/mm/page_alloc.c	2006-05-11 04:56:24.000000000 +0300
+@@ -153,7 +153,8 @@
+ 			1 << PG_reclaim |
+ 			1 << PG_slab    |
+ 			1 << PG_swapcache |
+-			1 << PG_writeback );
++			1 << PG_writeback |
++			1 << PG_buddy );
+ 	set_page_count(page, 0);
+ 	reset_page_mapcount(page);
+ 	page->mapping = NULL;
+@@ -224,12 +225,12 @@
+ 
+ static inline void set_page_order(struct page *page, int order) {
+ 	set_page_private(page, order);
+-	__SetPagePrivate(page);
++	__SetPageBuddy(page);
+ }
+ 
+ static inline void rmv_page_order(struct page *page)
+ {
+-	__ClearPagePrivate(page);
++	__ClearPageBuddy(page);
+ 	set_page_private(page, 0);
+ }
+ 
+@@ -268,11 +269,13 @@
+  * This function checks whether a page is free && is the buddy
+  * we can do coalesce a page and its buddy if
+  * (a) the buddy is not in a hole &&
+- * (b) the buddy is free &&
+- * (c) the buddy is on the buddy system &&
+- * (d) a page and its buddy have the same order.
+- * for recording page's order, we use page_private(page) and PG_private.
++ * (b) the buddy is in the buddy system &&
++ * (c) a page and its buddy have the same order.
++ *
++ * For recording whether a page is in the buddy system, we use PG_buddy.
++ * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
+  *
++ * For recording page's order, we use page_private(page).
+  */
+ static inline int page_is_buddy(struct page *page, int order)
+ {
+@@ -281,10 +284,10 @@
+ 		return 0;
+ #endif
+ 
+-       if (PagePrivate(page)           &&
+-           (page_order(page) == order) &&
+-            page_count(page) == 0)
++	if (PageBuddy(page) && page_order(page) == order) {
++		BUG_ON(page_count(page) != 0);
+                return 1;
++	}
+        return 0;
+ }
+ 
+@@ -301,7 +304,7 @@
+  * as necessary, plus some accounting needed to play nicely with other
+  * parts of the VM system.
+  * At each level, we keep a list of pages, which are heads of continuous
+- * free pages of length of (1 << order) and marked with PG_Private.Page's
++ * free pages of length of (1 << order) and marked with PG_buddy. Page's
+  * order is recorded in page_private(page) field.
+  * So when we are allocating or freeing one, we can derive the state of the
+  * other.  That is, if we allocate a small block, and both were   
+@@ -364,7 +367,8 @@
+ 			1 << PG_slab	|
+ 			1 << PG_swapcache |
+ 			1 << PG_writeback |
+-			1 << PG_reserved ))))
++			1 << PG_reserved |
++			1 << PG_buddy ))))
+ 		bad_page(page);
+ 	if (PageDirty(page))
+ 		__ClearPageDirty(page);
+@@ -522,7 +526,8 @@
+ 			1 << PG_slab    |
+ 			1 << PG_swapcache |
+ 			1 << PG_writeback |
+-			1 << PG_reserved ))))
++			1 << PG_reserved |
++			1 << PG_buddy ))))
+ 		bad_page(page);
+ 
+ 	/*
+diff -Naur linux-2.6.16/net/atm/clip.c linux-2.6.16.16/net/atm/clip.c
+--- linux-2.6.16/net/atm/clip.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/atm/clip.c	2006-05-11 04:56:24.000000000 +0300
+@@ -613,12 +613,19 @@
+ 
+ 
+ static int clip_device_event(struct notifier_block *this,unsigned long event,
+-    void *dev)
++			     void *arg)
+ {
++	struct net_device *dev = arg;
++
++	if (event == NETDEV_UNREGISTER) {
++		neigh_ifdown(&clip_tbl, dev);
++		return NOTIFY_DONE;
++	}
++
+ 	/* ignore non-CLIP devices */
+-	if (((struct net_device *) dev)->type != ARPHRD_ATM ||
+-	    ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit)
++	if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
+ 		return NOTIFY_DONE;
++
+ 	switch (event) {
+ 		case NETDEV_UP:
+ 			DPRINTK("clip_device_event NETDEV_UP\n");
+@@ -686,14 +693,12 @@
+ static void atmarpd_close(struct atm_vcc *vcc)
+ {
+ 	DPRINTK("atmarpd_close\n");
+-	atmarpd = NULL; /* assumed to be atomic */
+-	barrier();
+-	unregister_inetaddr_notifier(&clip_inet_notifier);
+-	unregister_netdevice_notifier(&clip_dev_notifier);
+-	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
+-		printk(KERN_ERR "atmarpd_close: closing with requests "
+-		    "pending\n");
++
++	rtnl_lock();
++	atmarpd = NULL;
+ 	skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
++	rtnl_unlock();
++
+ 	DPRINTK("(done)\n");
+ 	module_put(THIS_MODULE);
+ }
+@@ -714,7 +719,12 @@
+ 
+ static int atm_init_atmarp(struct atm_vcc *vcc)
+ {
+-	if (atmarpd) return -EADDRINUSE;
++	rtnl_lock();
++	if (atmarpd) {
++		rtnl_unlock();
++		return -EADDRINUSE;
++	}
++
+ 	if (start_timer) {
+ 		start_timer = 0;
+ 		init_timer(&idle_timer);
+@@ -731,10 +741,7 @@
+ 	vcc->push = NULL;
+ 	vcc->pop = NULL; /* crash */
+ 	vcc->push_oam = NULL; /* crash */
+-	if (register_netdevice_notifier(&clip_dev_notifier))
+-		printk(KERN_ERR "register_netdevice_notifier failed\n");
+-	if (register_inetaddr_notifier(&clip_inet_notifier))
+-		printk(KERN_ERR "register_inetaddr_notifier failed\n");
++	rtnl_unlock();
+ 	return 0;
+ }
+ 
+@@ -992,6 +999,8 @@
+ 
+ 	clip_tbl_hook = &clip_tbl;
+ 	register_atm_ioctl(&clip_ioctl_ops);
++	register_netdevice_notifier(&clip_dev_notifier);
++	register_inetaddr_notifier(&clip_inet_notifier);
+ 
+ #ifdef CONFIG_PROC_FS
+ {
+@@ -1012,6 +1021,9 @@
+ 
+ 	remove_proc_entry("arp", atm_proc_root);
+ 
++	unregister_inetaddr_notifier(&clip_inet_notifier);
++	unregister_netdevice_notifier(&clip_dev_notifier);
++
+ 	deregister_atm_ioctl(&clip_ioctl_ops);
+ 
+ 	/* First, stop the idle timer, so it stops banging
+diff -Naur linux-2.6.16/net/bridge/br_netfilter.c linux-2.6.16.16/net/bridge/br_netfilter.c
+--- linux-2.6.16/net/bridge/br_netfilter.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/bridge/br_netfilter.c	2006-05-11 04:56:24.000000000 +0300
+@@ -739,6 +739,15 @@
+ 	return NF_STOLEN;
+ }
+ 
++static int br_nf_dev_queue_xmit(struct sk_buff *skb)
++{
++	if (skb->protocol == htons(ETH_P_IP) &&
++	    skb->len > skb->dev->mtu &&
++	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
++		return ip_fragment(skb, br_dev_queue_push_xmit);
++	else
++		return br_dev_queue_push_xmit(skb);
++}
+ 
+ /* PF_BRIDGE/POST_ROUTING ********************************************/
+ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
+@@ -798,7 +807,7 @@
+ 		realoutdev = nf_bridge->netoutdev;
+ #endif
+ 	NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
+-	        br_dev_queue_push_xmit);
++	        br_nf_dev_queue_xmit);
+ 
+ 	return NF_STOLEN;
+ 
+@@ -843,7 +852,7 @@
+ 	if ((out->hard_start_xmit == br_dev_xmit &&
+ 	    okfn != br_nf_forward_finish &&
+ 	    okfn != br_nf_local_out_finish &&
+-	    okfn != br_dev_queue_push_xmit)
++	    okfn != br_nf_dev_queue_xmit)
+ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ 	    || ((out->priv_flags & IFF_802_1Q_VLAN) &&
+ 	    VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
+diff -Naur linux-2.6.16/net/core/dev.c linux-2.6.16.16/net/core/dev.c
+--- linux-2.6.16/net/core/dev.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/core/dev.c	2006-05-11 04:56:24.000000000 +0300
+@@ -2932,11 +2932,11 @@
+ 
+ 		switch(dev->reg_state) {
+ 		case NETREG_REGISTERING:
++			dev->reg_state = NETREG_REGISTERED;
+ 			err = netdev_register_sysfs(dev);
+ 			if (err)
+ 				printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
+ 				       dev->name, err);
+-			dev->reg_state = NETREG_REGISTERED;
+ 			break;
+ 
+ 		case NETREG_UNREGISTERING:
+diff -Naur linux-2.6.16/net/core/sock.c linux-2.6.16.16/net/core/sock.c
+--- linux-2.6.16/net/core/sock.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/core/sock.c	2006-05-11 04:56:24.000000000 +0300
+@@ -404,8 +404,9 @@
+ 			if (!valbool) {
+ 				sk->sk_bound_dev_if = 0;
+ 			} else {
+-				if (optlen > IFNAMSIZ) 
+-					optlen = IFNAMSIZ; 
++				if (optlen > IFNAMSIZ - 1)
++					optlen = IFNAMSIZ - 1;
++				memset(devname, 0, sizeof(devname));
+ 				if (copy_from_user(devname, optval, optlen)) {
+ 					ret = -EFAULT;
+ 					break;
+diff -Naur linux-2.6.16/net/ipv4/fib_trie.c linux-2.6.16.16/net/ipv4/fib_trie.c
+--- linux-2.6.16/net/ipv4/fib_trie.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv4/fib_trie.c	2006-05-11 04:56:24.000000000 +0300
+@@ -314,11 +314,6 @@
+ 	kfree(container_of(head, struct leaf, rcu));
+ }
+ 
+-static inline void free_leaf(struct leaf *leaf)
+-{
+-	call_rcu(&leaf->rcu, __leaf_free_rcu);
+-}
+-
+ static void __leaf_info_free_rcu(struct rcu_head *head)
+ {
+ 	kfree(container_of(head, struct leaf_info, rcu));
+@@ -357,7 +352,12 @@
+ 
+ static inline void tnode_free(struct tnode *tn)
+ {
+-	call_rcu(&tn->rcu, __tnode_free_rcu);
++	if(IS_LEAF(tn)) {
++		struct leaf *l = (struct leaf *) tn;
++		call_rcu_bh(&l->rcu, __leaf_free_rcu);
++	}
++        else
++		call_rcu(&tn->rcu, __tnode_free_rcu);
+ }
+ 
+ static struct leaf *leaf_new(void)
+diff -Naur linux-2.6.16/net/ipv4/ip_output.c linux-2.6.16.16/net/ipv4/ip_output.c
+--- linux-2.6.16/net/ipv4/ip_output.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv4/ip_output.c	2006-05-11 04:56:24.000000000 +0300
+@@ -86,8 +86,6 @@
+ 
+ int sysctl_ip_default_ttl = IPDEFTTL;
+ 
+-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
+-
+ /* Generate a checksum for an outgoing IP datagram. */
+ __inline__ void ip_send_check(struct iphdr *iph)
+ {
+@@ -421,7 +419,7 @@
+  *	single device frame, and queue such a frame for sending.
+  */
+ 
+-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
++int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+ {
+ 	struct iphdr *iph;
+ 	int raw = 0;
+@@ -673,6 +671,8 @@
+ 	return err;
+ }
+ 
++EXPORT_SYMBOL(ip_fragment);
++
+ int
+ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
+ {
+@@ -1249,11 +1249,7 @@
+ 	iph->tos = inet->tos;
+ 	iph->tot_len = htons(skb->len);
+ 	iph->frag_off = df;
+-	if (!df) {
+-		__ip_select_ident(iph, &rt->u.dst, 0);
+-	} else {
+-		iph->id = htons(inet->id++);
+-	}
++	ip_select_ident(iph, &rt->u.dst, sk);
+ 	iph->ttl = ttl;
+ 	iph->protocol = sk->sk_protocol;
+ 	iph->saddr = rt->rt_src;
+diff -Naur linux-2.6.16/net/ipv4/netfilter/ip_conntrack_netlink.c linux-2.6.16.16/net/ipv4/netfilter/ip_conntrack_netlink.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_conntrack_netlink.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv4/netfilter/ip_conntrack_netlink.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1619,7 +1619,7 @@
+ 	printk("ctnetlink: unregistering from nfnetlink.\n");
+ 
+ #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+-	ip_conntrack_unregister_notifier(&ctnl_notifier_exp);
++	ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
+ 	ip_conntrack_unregister_notifier(&ctnl_notifier);
+ #endif
+ 
+diff -Naur linux-2.6.16/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.16.16/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+--- linux-2.6.16/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	2006-05-11 04:56:24.000000000 +0300
+@@ -235,12 +235,15 @@
+ 			flag = 1;
+ 		}
+ 
+-		/* Cookie Ack/Echo chunks not the first OR 
+-		   Init / Init Ack / Shutdown compl chunks not the only chunks */
+-		if ((sch->type == SCTP_CID_COOKIE_ACK 
++		/*
++		 * Cookie Ack/Echo chunks not the first OR
++		 * Init / Init Ack / Shutdown compl chunks not the only chunks
++		 * OR zero-length.
++		 */
++		if (((sch->type == SCTP_CID_COOKIE_ACK
+ 			|| sch->type == SCTP_CID_COOKIE_ECHO
+ 			|| flag)
+-		     && count !=0 ) {
++		      && count !=0) || !sch->length) {
+ 			DEBUGP("Basic checks failed\n");
+ 			return 1;
+ 		}
+diff -Naur linux-2.6.16/net/ipv4/route.c linux-2.6.16.16/net/ipv4/route.c
+--- linux-2.6.16/net/ipv4/route.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv4/route.c	2006-05-11 04:56:24.000000000 +0300
+@@ -2750,7 +2750,10 @@
+ 	/* Reserve room for dummy headers, this skb can pass
+ 	   through good chunk of routing engine.
+ 	 */
+-	skb->mac.raw = skb->data;
++	skb->mac.raw = skb->nh.raw = skb->data;
++
++	/* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
++	skb->nh.iph->protocol = IPPROTO_ICMP;
+ 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
+ 
+ 	if (rta[RTA_SRC - 1])
+diff -Naur linux-2.6.16/net/ipv4/tcp_output.c linux-2.6.16.16/net/ipv4/tcp_output.c
+--- linux-2.6.16/net/ipv4/tcp_output.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv4/tcp_output.c	2006-05-11 04:56:24.000000000 +0300
+@@ -537,7 +537,9 @@
+ 	buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
+ 	if (buff == NULL)
+ 		return -ENOMEM; /* We'll just try again later. */
+-	sk_charge_skb(sk, buff);
++
++	buff->truesize = skb->len - len;
++	skb->truesize -= buff->truesize;
+ 
+ 	/* Correct the sequence numbers. */
+ 	TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
+diff -Naur linux-2.6.16/net/ipv6/exthdrs.c linux-2.6.16.16/net/ipv6/exthdrs.c
+--- linux-2.6.16/net/ipv6/exthdrs.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv6/exthdrs.c	2006-05-11 04:56:24.000000000 +0300
+@@ -489,6 +489,18 @@
+ {
+ 	struct inet6_skb_parm *opt = IP6CB(skb);
+ 
++	/*
++	 * skb->nh.raw is equal to skb->data, and
++	 * skb->h.raw - skb->nh.raw is always equal to
++	 * sizeof(struct ipv6hdr) by definition of
++	 * hop-by-hop options.
++	 */
++	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
++	    !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
++		kfree_skb(skb);
++		return -1;
++	}
++
+ 	opt->hop = sizeof(struct ipv6hdr);
+ 	if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
+ 		skb->h.raw += (skb->h.raw[1]+1)<<3;
+diff -Naur linux-2.6.16/net/ipv6/xfrm6_policy.c linux-2.6.16.16/net/ipv6/xfrm6_policy.c
+--- linux-2.6.16/net/ipv6/xfrm6_policy.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/ipv6/xfrm6_policy.c	2006-05-11 04:56:24.000000000 +0300
+@@ -191,16 +191,18 @@
+ static inline void
+ _decode_session6(struct sk_buff *skb, struct flowi *fl)
+ {
+-	u16 offset = sizeof(struct ipv6hdr);
++	u16 offset = skb->h.raw - skb->nh.raw;
+ 	struct ipv6hdr *hdr = skb->nh.ipv6h;
+-	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+-	u8 nexthdr = skb->nh.ipv6h->nexthdr;
++	struct ipv6_opt_hdr *exthdr;
++	u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
+ 
+ 	memset(fl, 0, sizeof(struct flowi));
+ 	ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
+ 	ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
+ 
+ 	while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
++		exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
++
+ 		switch (nexthdr) {
+ 		case NEXTHDR_ROUTING:
+ 		case NEXTHDR_HOP:
+diff -Naur linux-2.6.16/net/netfilter/nf_conntrack_netlink.c linux-2.6.16.16/net/netfilter/nf_conntrack_netlink.c
+--- linux-2.6.16/net/netfilter/nf_conntrack_netlink.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/netfilter/nf_conntrack_netlink.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1641,7 +1641,7 @@
+ 	printk("ctnetlink: unregistering from nfnetlink.\n");
+ 
+ #ifdef CONFIG_NF_CONNTRACK_EVENTS
+-	nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
++	nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
+ 	nf_conntrack_unregister_notifier(&ctnl_notifier);
+ #endif
+ 
+diff -Naur linux-2.6.16/net/netfilter/nf_conntrack_proto_sctp.c linux-2.6.16.16/net/netfilter/nf_conntrack_proto_sctp.c
+--- linux-2.6.16/net/netfilter/nf_conntrack_proto_sctp.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/netfilter/nf_conntrack_proto_sctp.c	2006-05-11 04:56:24.000000000 +0300
+@@ -240,12 +240,15 @@
+ 			flag = 1;
+ 		}
+ 
+-		/* Cookie Ack/Echo chunks not the first OR 
+-		   Init / Init Ack / Shutdown compl chunks not the only chunks */
+-		if ((sch->type == SCTP_CID_COOKIE_ACK 
++		/*
++		 * Cookie Ack/Echo chunks not the first OR
++		 * Init / Init Ack / Shutdown compl chunks not the only chunks
++		 * OR zero-length.
++		 */
++		if (((sch->type == SCTP_CID_COOKIE_ACK
+ 			|| sch->type == SCTP_CID_COOKIE_ECHO
+ 			|| flag)
+-		     && count !=0 ) {
++		      && count !=0) || !sch->length) {
+ 			DEBUGP("Basic checks failed\n");
+ 			return 1;
+ 		}
+diff -Naur linux-2.6.16/net/sctp/inqueue.c linux-2.6.16.16/net/sctp/inqueue.c
+--- linux-2.6.16/net/sctp/inqueue.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/sctp/inqueue.c	2006-05-11 04:56:24.000000000 +0300
+@@ -149,6 +149,7 @@
+ 		/* This is the first chunk in the packet.  */
+ 		chunk->singleton = 1;
+ 		ch = (sctp_chunkhdr_t *) chunk->skb->data;
++		chunk->data_accepted = 0;
+ 	}
+ 
+         chunk->chunk_hdr = ch;
+diff -Naur linux-2.6.16/net/sctp/sm_statefuns.c linux-2.6.16.16/net/sctp/sm_statefuns.c
+--- linux-2.6.16/net/sctp/sm_statefuns.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/sctp/sm_statefuns.c	2006-05-11 04:56:24.000000000 +0300
+@@ -636,8 +636,9 @@
+ 	 */
+         chunk->subh.cookie_hdr =
+ 		(struct sctp_signed_cookie *)chunk->skb->data;
+-	skb_pull(chunk->skb,
+-		 ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
++	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
++					 sizeof(sctp_chunkhdr_t)))
++		goto nomem;
+ 
+ 	/* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint
+ 	 * "Z" will reply with a COOKIE ACK chunk after building a TCB
+@@ -965,7 +966,8 @@
+ 	 */
+ 	chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;
+ 	paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
+-	skb_pull(chunk->skb, paylen);
++	if (!pskb_pull(chunk->skb, paylen))
++		goto nomem;
+ 
+ 	reply = sctp_make_heartbeat_ack(asoc, chunk,
+ 					chunk->subh.hb_hdr, paylen);
+@@ -1860,8 +1862,9 @@
+ 	 * are in good shape.
+ 	 */
+         chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
+-	skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+-		 sizeof(sctp_chunkhdr_t));
++	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
++					sizeof(sctp_chunkhdr_t)))
++		goto nomem;
+ 
+ 	/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie
+ 	 * of a duplicate COOKIE ECHO match the Verification Tags of the
+@@ -5151,7 +5154,9 @@
+ 	int tmp;
+ 	__u32 tsn;
+ 	int account_value;
++	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
+ 	struct sock *sk = asoc->base.sk;
++	int rcvbuf_over = 0;
+ 
+ 	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
+ 	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
+@@ -5162,10 +5167,16 @@
+ 	/* ASSERT:  Now skb->data is really the user data.  */
+ 
+ 	/*
+-	 * if we are established, and we have used up our receive
+-	 * buffer memory, drop the frame
++	 * If we are established, and we have used up our receive buffer
++	 * memory, think about droping the frame.
++	 * Note that we have an opportunity to improve performance here.
++	 * If we accept one chunk from an skbuff, we have to keep all the
++	 * memory of that skbuff around until the chunk is read into user
++	 * space. Therefore, once we accept 1 chunk we may as well accept all
++	 * remaining chunks in the skbuff. The data_accepted flag helps us do
++	 * that.
+ 	 */
+-	if (asoc->state == SCTP_STATE_ESTABLISHED) {
++	if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) {
+ 		/*
+ 		 * If the receive buffer policy is 1, then each
+ 		 * association can allocate up to sk_rcvbuf bytes
+@@ -5176,9 +5187,25 @@
+ 			account_value = atomic_read(&asoc->rmem_alloc);
+ 		else
+ 			account_value = atomic_read(&sk->sk_rmem_alloc);
+-
+-		if (account_value > sk->sk_rcvbuf)
+-			return SCTP_IERROR_IGNORE_TSN;
++		if (account_value > sk->sk_rcvbuf) {
++			/*
++			 * We need to make forward progress, even when we are
++			 * under memory pressure, so we always allow the
++			 * next tsn after the ctsn ack point to be accepted.
++			 * This lets us avoid deadlocks in which we have to
++			 * drop frames that would otherwise let us drain the
++			 * receive queue.
++			 */
++			if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn)
++				return SCTP_IERROR_IGNORE_TSN;
++
++			/*
++			 * We're going to accept the frame but we should renege
++			 * to make space for it. This will send us down that
++			 * path later in this function.
++			 */
++			rcvbuf_over = 1;
++		}
+ 	}
+ 
+ 	/* Process ECN based congestion.
+@@ -5226,6 +5253,7 @@
+ 	datalen -= sizeof(sctp_data_chunk_t);
+ 
+ 	deliver = SCTP_CMD_CHUNK_ULP;
++	chunk->data_accepted = 1;
+ 
+ 	/* Think about partial delivery. */
+ 	if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
+@@ -5242,7 +5270,8 @@
+ 	 * large spill over.
+ 	 */
+ 	if (!asoc->rwnd || asoc->rwnd_over ||
+-	    (datalen > asoc->rwnd + asoc->frag_point)) {
++	    (datalen > asoc->rwnd + asoc->frag_point) ||
++	    rcvbuf_over) {
+ 
+ 		/* If this is the next TSN, consider reneging to make
+ 		 * room.   Note: Playing nice with a confused sender.  A
+@@ -5250,8 +5279,8 @@
+ 		 * space and in the future we may want to detect and
+ 		 * do more drastic reneging.
+ 		 */
+-		if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
+-		    (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
++		if (sctp_tsnmap_has_gap(map) &&
++		    (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
+ 			SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
+ 			deliver = SCTP_CMD_RENEGE;
+ 		} else {
+diff -Naur linux-2.6.16/net/sctp/sm_statetable.c linux-2.6.16.16/net/sctp/sm_statetable.c
+--- linux-2.6.16/net/sctp/sm_statetable.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/sctp/sm_statetable.c	2006-05-11 04:56:24.000000000 +0300
+@@ -366,9 +366,9 @@
+ 	/* SCTP_STATE_EMPTY */ \
+ 	{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
+ 	/* SCTP_STATE_CLOSED */ \
+-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
++	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ 	/* SCTP_STATE_COOKIE_WAIT */ \
+-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
++	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ 	/* SCTP_STATE_COOKIE_ECHOED */ \
+ 	{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ 	/* SCTP_STATE_ESTABLISHED */ \
+@@ -380,7 +380,7 @@
+ 	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+ 	{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
+ 	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
++	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ } /* TYPE_SCTP_ECN_ECNE */
+ 
+ #define TYPE_SCTP_ECN_CWR { \
+@@ -401,7 +401,7 @@
+ 	/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+ 	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ 	/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
++	{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
+ } /* TYPE_SCTP_ECN_CWR */
+ 
+ #define TYPE_SCTP_SHUTDOWN_COMPLETE { \
+@@ -647,7 +647,7 @@
+ 	/* SCTP_STATE_EMPTY */ \
+ 	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ 	/* SCTP_STATE_CLOSED */ \
+-	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
++	{.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
+ 	/* SCTP_STATE_COOKIE_WAIT */ \
+ 	{.fn = sctp_sf_do_prm_requestheartbeat,		      \
+ 	 .name = "sctp_sf_do_prm_requestheartbeat"},          \
+diff -Naur linux-2.6.16/net/sctp/ulpqueue.c linux-2.6.16.16/net/sctp/ulpqueue.c
+--- linux-2.6.16/net/sctp/ulpqueue.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/net/sctp/ulpqueue.c	2006-05-11 04:56:24.000000000 +0300
+@@ -279,6 +279,7 @@
+ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
+ {
+ 	struct sk_buff *pos;
++	struct sk_buff *new = NULL;
+ 	struct sctp_ulpevent *event;
+ 	struct sk_buff *pnext, *last;
+ 	struct sk_buff *list = skb_shinfo(f_frag)->frag_list;
+@@ -297,11 +298,33 @@
+ 	 */
+ 	if (last)
+ 		last->next = pos;
+-	else
+-		skb_shinfo(f_frag)->frag_list = pos;
++ 	else {
++ 		if (skb_cloned(f_frag)) {
++ 			/* This is a cloned skb, we can't just modify
++ 			 * the frag_list.  We need a new skb to do that.
++ 			 * Instead of calling skb_unshare(), we'll do it
++ 			 * ourselves since we need to delay the free.
++ 			 */
++ 			new = skb_copy(f_frag, GFP_ATOMIC);
++ 			if (!new)
++ 				return NULL;	/* try again later */
++
++ 			new->sk = f_frag->sk;
++
++ 			skb_shinfo(new)->frag_list = pos;
++ 		} else
++ 			skb_shinfo(f_frag)->frag_list = pos;
++ 	}
+ 
+ 	/* Remove the first fragment from the reassembly queue.  */
+ 	__skb_unlink(f_frag, queue);
++
++ 	/* if we did unshare, then free the old skb and re-assign */
++ 	if (new) {
++ 		kfree_skb(f_frag);
++ 		f_frag = new;
++ 	}
++
+ 	while (pos) {
+ 
+ 		pnext = pos->next;
+diff -Naur linux-2.6.16/security/keys/key.c linux-2.6.16.16/security/keys/key.c
+--- linux-2.6.16/security/keys/key.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/security/keys/key.c	2006-05-11 04:56:24.000000000 +0300
+@@ -785,6 +785,10 @@
+ 
+ 	key_check(keyring);
+ 
++	key_ref = ERR_PTR(-ENOTDIR);
++	if (keyring->type != &key_type_keyring)
++		goto error_2;
++
+ 	down_write(&keyring->sem);
+ 
+ 	/* if we're going to allocate a new key, we're going to have
+diff -Naur linux-2.6.16/security/keys/keyring.c linux-2.6.16.16/security/keys/keyring.c
+--- linux-2.6.16/security/keys/keyring.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/security/keys/keyring.c	2006-05-11 04:56:24.000000000 +0300
+@@ -437,6 +437,7 @@
+ /*
+  * search the given keyring only (no recursion)
+  * - keyring must be locked by caller
++ * - caller must guarantee that the keyring is a keyring
+  */
+ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+ 			       const struct key_type *ktype,
+diff -Naur linux-2.6.16/security/selinux/ss/mls.c linux-2.6.16.16/security/selinux/ss/mls.c
+--- linux-2.6.16/security/selinux/ss/mls.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/security/selinux/ss/mls.c	2006-05-11 04:56:24.000000000 +0300
+@@ -264,7 +264,7 @@
+ 
+ 	if (!selinux_mls_enabled) {
+ 		if (def_sid != SECSID_NULL && oldc)
+-			*scontext += strlen(*scontext);
++			*scontext += strlen(*scontext)+1;
+ 		return 0;
+ 	}
+ 
+diff -Naur linux-2.6.16/sound/isa/opti9xx/opti92x-ad1848.c linux-2.6.16.16/sound/isa/opti9xx/opti92x-ad1848.c
+--- linux-2.6.16/sound/isa/opti9xx/opti92x-ad1848.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/sound/isa/opti9xx/opti92x-ad1848.c	2006-05-11 04:56:24.000000000 +0300
+@@ -2088,9 +2088,11 @@
+ 	int error;
+ 	struct platform_device *device;
+ 
++#ifdef CONFIG_PNP
+ 	pnp_register_card_driver(&opti9xx_pnpc_driver);
+ 	if (snd_opti9xx_pnp_is_probed)
+ 		return 0;
++#endif
+ 	if (! is_isapnp_selected()) {
+ 		error = platform_driver_register(&snd_opti9xx_driver);
+ 		if (error < 0)
+@@ -2102,7 +2104,9 @@
+ 		}
+ 		platform_driver_unregister(&snd_opti9xx_driver);
+ 	}
++#ifdef CONFIG_PNP
+ 	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
++#endif
+ #ifdef MODULE
+ 	printk(KERN_ERR "no OPTi " CHIP_NAME " soundcard found\n");
+ #endif
+@@ -2115,7 +2119,9 @@
+ 		platform_device_unregister(snd_opti9xx_platform_device);
+ 		platform_driver_unregister(&snd_opti9xx_driver);
+ 	}
++#ifdef CONFIG_PNP
+ 	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
++#endif
+ }
+ 
+ module_init(alsa_card_opti9xx_init)
+diff -Naur linux-2.6.16/sound/oss/dmasound/tas_common.c linux-2.6.16.16/sound/oss/dmasound/tas_common.c
+--- linux-2.6.16/sound/oss/dmasound/tas_common.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/sound/oss/dmasound/tas_common.c	2006-05-11 04:56:24.000000000 +0300
+@@ -195,8 +195,8 @@
+ 
+ 	printk(KERN_INFO "tas driver [%s])\n", driver_name);
+ 
+-#ifndef CONFIG_I2C_KEYWEST
+-	request_module("i2c-keywest");
++#ifndef CONFIG_I2C_POWERMAC
++	request_module("i2c-powermac");
+ #endif
+ 	tas_node = find_devices("deq");
+ 	if (tas_node == NULL)
+diff -Naur linux-2.6.16/sound/pci/hda/patch_realtek.c linux-2.6.16.16/sound/pci/hda/patch_realtek.c
+--- linux-2.6.16/sound/pci/hda/patch_realtek.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/sound/pci/hda/patch_realtek.c	2006-05-11 04:56:24.000000000 +0300
+@@ -2948,6 +2948,8 @@
+ 	{ .modelname = "basic", .config = ALC260_BASIC },
+ 	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
+ 	  .config = ALC260_BASIC }, /* Sony VAIO */
++	{ .pci_subvendor = 0x152d, .pci_subdevice = 0x0729,
++	  .config = ALC260_BASIC }, /* CTL Travel Master U553W */
+ 	{ .modelname = "hp", .config = ALC260_HP },
+ 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
+ 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
+diff -Naur linux-2.6.16/sound/ppc/daca.c linux-2.6.16.16/sound/ppc/daca.c
+--- linux-2.6.16/sound/ppc/daca.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/sound/ppc/daca.c	2006-05-11 04:56:24.000000000 +0300
+@@ -256,7 +256,7 @@
+ 
+ #ifdef CONFIG_KMOD
+ 	if (current->fs->root)
+-		request_module("i2c-keywest");
++		request_module("i2c-powermac");
+ #endif /* CONFIG_KMOD */	
+ 
+ 	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
+diff -Naur linux-2.6.16/sound/ppc/tumbler.c linux-2.6.16.16/sound/ppc/tumbler.c
+--- linux-2.6.16/sound/ppc/tumbler.c	2006-03-20 07:53:29.000000000 +0200
++++ linux-2.6.16.16/sound/ppc/tumbler.c	2006-05-11 04:56:24.000000000 +0300
+@@ -1314,7 +1314,7 @@
+ 
+ #ifdef CONFIG_KMOD
+ 	if (current->fs->root)
+-		request_module("i2c-keywest");
++		request_module("i2c-powermac");
+ #endif /* CONFIG_KMOD */	
+ 
+ 	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/packages/linux/linux-h6300-omap1-2.6.16.16/linux-h6300-omap2-2.6.16.16.patch b/packages/linux/linux-h6300-omap1-2.6.16.16/linux-h6300-omap2-2.6.16.16.patch
new file mode 100644
index 0000000000..98b4365f98
--- /dev/null
+++ b/packages/linux/linux-h6300-omap1-2.6.16.16/linux-h6300-omap2-2.6.16.16.patch
@@ -0,0 +1,3736 @@
+diff -Naur linux-2.6.16.16/arch/arm/Kconfig h6300_dev/arch/arm/Kconfig
+--- linux-2.6.16.16/arch/arm/Kconfig	2006-05-17 21:41:27.000000000 +0300
++++ h6300_dev/arch/arm/Kconfig	2006-04-02 00:23:01.000000000 +0300
+@@ -811,6 +811,8 @@
+ 
+ source "drivers/video/Kconfig"
+ 
++source "drivers/telephony/Kconfig"
++
+ source "sound/Kconfig"
+ 
+ source "drivers/usb/Kconfig"
+diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/board-h6300.c h6300_dev/arch/arm/mach-omap1/board-h6300.c
+--- linux-2.6.16.16/arch/arm/mach-omap1/board-h6300.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/arch/arm/mach-omap1/board-h6300.c	2006-04-24 20:53:29.000000000 +0300
+@@ -0,0 +1,424 @@
++/*
++ * Modified from board-h6300.c
++ *
++ * Code for generic OMAP board. Should work on many OMAP systems where
++ * the device drivers take care of all the necessary hardware initialization.
++ * Do not put any board specific code to this file; create a new machine
++ * type if you need custom low-level initializations.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/input.h>
++
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++#include <asm/arch/gpio.h>
++
++#include <asm/arch/tc.h>
++#include <asm/arch/usb.h>
++#include <asm/arch/keypad.h>
++#include <asm/arch/common.h>
++#include <asm/arch/mcbsp.h>
++#include <asm/arch/omap-alsa.h>
++#include <asm/arch/h6300_uart_info.h>
++
++#define _h6300_KEY_CALENDAR	67 	// xmodmap 75 aka F9
++#define _H6300_KEY_TELEPHONE	68 	// xmodmap 76 aka F10
++#define _H6300_KEY_HOMEPAGE	87 	// xmodmap 87 aka Num_Lock
++#define _H6300_KEY_MAIL		88 	// xmodmap 88 aka Scroll_Lock
++
++/*
++ * Following 5 keypad events are not really sent to userspace. 
++ * Instead if the good combination of them is sent, then that is send.
++ * (up, right, down, left, enter)
++ */
++#define	_H6300_JOYPAD_UP_RIGHT		1	// 00001
++#define _H6300_JOYPAD_DOWN_RIGHT	2	// 00010
++#define _h6300_JOYPAD_DOWN_LEFT		4	// 00100
++#define _h6300_JOYPAD_UP_LEFT		8	// 01000
++#define _H6300_JOYPAD_KEY_OK		16	// 10000
++
++static int h6300_keymap[] = {
++	KEY(2, 0, _h6300_KEY_CALENDAR),		// address button in the bottom left	
++	KEY(2, 3, _H6300_KEY_TELEPHONE),	// start call button in the bottom
++	KEY(3, 1, _H6300_KEY_HOMEPAGE),		// stop call button in the bottom
++	KEY(3, 4, _H6300_KEY_MAIL),		// messaging button in the bottom right
++
++	KEY(0, 0, KEY_VOLUMEUP),	// volume up button in the right side
++	KEY(0, 1, KEY_VOLUMEDOWN),	// volume down button in the right side
++	KEY(3, 2, KEY_RECORD),		// record button in the left side
++	
++	KEY(1, 0, _h6300_JOYPAD_UP_LEFT),	
++	KEY(1, 1, _h6300_JOYPAD_DOWN_LEFT),	
++	KEY(1, 2, _H6300_JOYPAD_KEY_OK),		
++	KEY(1, 3, _H6300_JOYPAD_DOWN_RIGHT),
++	KEY(1, 4, _H6300_JOYPAD_UP_RIGHT),	
++	
++	KEY(4, 0, KEY_RIGHT),
++	KEY(4, 1, KEY_DOWN),
++	KEY(4, 2, KEY_LEFT),		
++	KEY(4, 3, KEY_UP),
++	KEY(4, 4, KEY_ENTER),
++
++	0
++};
++
++/*
++ * Bluetooth - Relies on h6300_bt module,
++ * so make the calls indirectly through pointers. Requires that the
++ * h6300_bt bluetooth module be loaded before any attempt to use
++ * bluetooth (obviously).
++ */
++
++static struct h6300_uart_funcs bt_funcs;
++static struct h6300_uart_funcs gsm_funcs;
++
++static void h6300_bt_configure(struct uart_omap_port *up, int enable)
++{
++	printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() started\n");
++	if (bt_funcs.configure != NULL)
++		bt_funcs.configure(up, enable);
++	printk(KERN_NOTICE "board-h6300.c, h6300_bt_configure() done\n");
++}
++
++static void h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
++{
++	printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() started\n");
++	if (bt_funcs.set_txrx != NULL)
++	{
++		printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx(), bt_funcs.set_txrx != NULL\n");
++		bt_funcs.set_txrx(up, txrx);
++	}
++	printk(KERN_NOTICE "board-h6300.c, h6300_bt_set_txrx() done\n");
++}
++
++static int h6300_bt_get_txrx(struct uart_omap_port *up)
++{
++	int	retVal;
++	
++	printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() started\n");
++	if (bt_funcs.get_txrx != NULL)
++	{
++		retVal	= bt_funcs.get_txrx(up);
++		printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
++		return retVal;
++	}
++	else
++	{
++		printk(KERN_NOTICE "board-h6300.c, h6300_bt_get_txrx() done, returning 0\n");
++		return 0;
++	}
++}
++
++static struct platform_omap_serial_funcs h6300_omap_bt_funcs = {
++	.configure	= h6300_bt_configure,
++	.set_txrx	= h6300_bt_set_txrx,
++	.get_txrx	= h6300_bt_get_txrx,
++};
++
++struct platform_device btuart_device = {
++	.name	= "h6300_bt",
++	.id	= 1,
++};
++EXPORT_SYMBOL(btuart_device);
++
++static void h6300_gsm_configure(struct uart_omap_port *up, int enable)
++{
++	printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() started\n");
++	if (gsm_funcs.configure != NULL)
++		gsm_funcs.configure(up, enable);
++	printk(KERN_NOTICE "board-h6300.c, h6300_gsm_configure() done\n");
++}
++
++static void h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
++{
++	printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() started\n");
++	if (bt_funcs.set_txrx != NULL)
++	{
++		printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx(), bt_funcs.set_txrx != NULL\n");
++		gsm_funcs.set_txrx(up, txrx);
++	}
++	printk(KERN_NOTICE "board-h6300.c, h6300_gsm_set_txrx() done\n");
++}
++
++static int h6300_gsm_get_txrx(struct uart_omap_port *up)
++{
++	int	retVal;
++	
++	printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() started\n");
++	if (bt_funcs.get_txrx != NULL)
++	{
++		retVal	= gsm_funcs.get_txrx(up);
++		printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx(), bt_funcs.get_trx != null, done, retVal %d\n", retVal);
++		return retVal;
++	}
++	else
++	{
++		printk(KERN_NOTICE "board-h6300.c, h6300_gsm_get_txrx() done, returning 0\n");
++		return 0;
++	}
++}
++
++static struct platform_omap_serial_funcs h6300_omap_gsm_funcs = {
++	.configure	= h6300_gsm_configure,
++	.set_txrx	= h6300_gsm_set_txrx,
++	.get_txrx	= h6300_gsm_get_txrx,
++};
++
++struct platform_device gsmuart_device = {
++	.name	= "h6300_gsm",
++	.id	= 1,
++};
++EXPORT_SYMBOL(gsmuart_device);
++
++#if 0
++static struct mtd_partition h6300_partitions[] = {
++	/* bootloader (U-Boot, etc) in first sector */
++	{
++	      .name		= "bootloader",
++	      .offset		= 0,
++	      .size		= SZ_128K,
++	      .mask_flags	= MTD_WRITEABLE, /* force read-only */
++	},
++	/* bootloader params in the next sector */
++	{
++	      .name		= "params",
++	      .offset		= MTDPART_OFS_APPEND,
++	      .size		= SZ_128K,
++	      .mask_flags	= 0,
++	},
++	/* kernel */
++	{
++	      .name		= "kernel",
++	      .offset		= MTDPART_OFS_APPEND,
++	      .size		= SZ_2M,
++	      .mask_flags	= 0
++	},
++	/* rest of flash1 is a file system */
++	{
++	      .name		= "rootfs",
++	      .offset		= MTDPART_OFS_APPEND,
++	      .size		= SZ_16M - SZ_2M - 2 * SZ_128K,
++	      .mask_flags	= 0
++	},
++	/* file system */
++	{
++	      .name		= "filesystem",
++	      .offset		= MTDPART_OFS_APPEND,
++	      .size		= MTDPART_SIZ_FULL,
++	      .mask_flags	= 0
++	}
++};
++
++static struct flash_platform_data h6300_flash_data = {
++	.map_name	= "cfi_probe",
++	.width		= 2,
++	.parts		= h6300_partitions,
++	.nr_parts	= ARRAY_SIZE(h6300_partitions),
++};
++
++static struct resource h6300_flash_resource = {
++	.start		= OMAP_CS0_PHYS,
++	.end		= OMAP_CS0_PHYS + SZ_32M - 1,
++	.flags		= IORESOURCE_MEM,
++};
++
++static struct platform_device h6300_flash_device = {
++	.name	= "omapflash",
++	.id		= 0,
++	.dev	= {
++		.platform_data	= &h6300_flash_data,
++	},
++static struct platform_device h6300_flash_device = {
++	.name	= "omapflash",
++	.id		= 0,
++	.dev	= {
++		.platform_data	= &h6300_flash_data,
++	},
++	.num_resources	= 1,
++	.resource	= &h6300_flash_resource,
++};
++#endif
++
++static struct resource h6300_kp_resources[] = {
++	[0] = {
++		.start	= INT_KEYBOARD,
++		.end	= INT_KEYBOARD,
++		.flags	= IORESOURCE_IRQ,
++	},
++};
++
++static struct omap_kp_platform_data h6300_kp_data = {
++	.rows	= 8,
++	.cols	= 8,
++	.keymap = h6300_keymap,
++	.rep	= 1,	// turns repeat bit on
++};
++
++static struct platform_device h6300_kp_device = {
++	.name		= "omap-keypad",
++	.id		= -1,
++	.dev		= {
++		.platform_data = &h6300_kp_data,
++	},
++	.num_resources	= ARRAY_SIZE(h6300_kp_resources),
++	.resource	= h6300_kp_resources,
++};
++
++static struct resource h6300_wlan_resource[] = {
++        [0] = {
++                .start          = OMAP_CS1_PHYS,
++                .end            = OMAP_CS1_PHYS + SZ_32M -1,
++                .flags          = IORESOURCE_MEM,
++        },
++
++        [1] = {
++                .start  = OMAP_GPIO_IRQ(11),
++                .end    = OMAP_GPIO_IRQ(11),
++                .flags  = IORESOURCE_IRQ,
++        },
++};
++
++static struct platform_device h6300_wlan_device = {
++        .name           = "tnetw1100b",
++        .id             = 0,
++        .num_resources  = 2,
++        .resource       = h6300_wlan_resource,
++};
++
++static struct omap_mcbsp_reg_cfg mcbsp_regs = { 
++	.spcr2	= 0x0000,
++	.spcr1	= 0x0000,
++	.rcr2	= 0x8041,
++	.rcr1	= 0x0040,
++	.xcr2	= 0x00a1,
++	.xcr1	= 0x00a0,
++	.srgr2	= 0xb000,
++	.srgr1	= 0x0000,
++	.pcr0	= 0x0081,
++};
++
++static struct omap_alsa_codec_config alsa_config = {
++	.name                   = "iPAQ h6300 TSC2101",
++	.mcbsp_regs_alsa        = &mcbsp_regs,
++	.codec_configure_dev    = NULL, //tsc2101_configure,
++	.codec_set_samplerate   = NULL, //tsc2101_set_samplerate,
++	.codec_clock_setup      = NULL, //tsc2101_clock_setup,
++	.codec_clock_on         = NULL, //tsc2101_clock_on,
++	.codec_clock_off        = NULL, //tsc2101_clock_off,
++	.get_default_samplerate = NULL, //tsc2101_get_default_samplerate,
++};
++
++static struct platform_device h6300_mcbsp1_device = {
++	.name	= "omap_alsa_mcbsp",
++	.id	= 1,
++	.dev = {
++		.platform_data	= &alsa_config,
++	},
++};
++
++static struct platform_device h6300_lcd_device = {
++	.name	= "lcd_h6300",
++	.id	= -1,
++};
++
++static struct platform_device *h6300_devices[] __initdata = {
++	&h6300_lcd_device,
++	&btuart_device,
++	&gsmuart_device,
++	&h6300_kp_device,
++	&h6300_mcbsp1_device,
++	&h6300_wlan_device,
++	//&h6300_flash_device,
++};
++
++static void __init h6300_init_irq(void)
++{
++	omap1_init_common_hw();
++	omap_init_irq();
++	omap_gpio_init();
++
++	/* this is now done in the drivers/input/touschreen/omap/ts_hx.c*/
++	//omap_request_gpio(2);
++	//omap_set_gpio_direction(2, 0);
++	//omap_set_gpio_dataout(2, 1);
++}
++
++/* assume no Mini-AB port */
++
++static struct omap_usb_config h6300_usb_config __initdata = {
++	.hmc_mode	= 0,
++	.register_dev	= 1,
++	.pins[0]	= 0,
++};
++
++static struct omap_lcd_config h6300_lcd_config __initdata = {
++	.ctrl_name	= "internal",
++};
++
++static struct omap_mmc_config h6300_mmc_config __initdata = {
++	.mmc [0] = {
++		.enabled 	= 1,
++		.wire4		= 1,
++		.wp_pin		= OMAP_GPIO_IRQ(13),
++		.power_pin	= -1, // tps65010 ?
++		.switch_pin	= -1, // OMAP_MPUIO(1),	// = -1, // ARMIO2?
++	},
++};
++
++static struct omap_uart_config h6300_uart_config __initdata = {
++	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
++};
++
++static struct omap_board_config_kernel h6300_config[] = {
++	{ OMAP_TAG_USB, 	&h6300_usb_config },
++	{ OMAP_TAG_MMC,		&h6300_mmc_config },
++	{ OMAP_TAG_UART,	&h6300_uart_config },
++	{ OMAP_TAG_LCD,		&h6300_lcd_config },
++};
++
++static void __init h6300_init(void)
++{
++	int ret;
++	
++	ret = platform_add_devices(h6300_devices, ARRAY_SIZE(h6300_devices));
++	if (ret) 
++	{
++		printk(KERN_WARNING "Unable to add h6300 platform devices like bluetooth");
++	}
++	omap_board_config	= h6300_config;
++	omap_board_config_size	= ARRAY_SIZE(h6300_config);
++	omap_serial_init();
++}
++
++static void __init h6300_map_io(void)
++{
++	omap1_map_common_io();
++	
++	btuart_device.dev.platform_data		= &h6300_omap_bt_funcs;
++	gsmuart_device.dev.platform_data	= &h6300_omap_gsm_funcs;
++}
++
++MACHINE_START(OMAP_H6300, "HP iPAQ h6300")
++	/* MAINTAINER("Everett Coleman II <gcc80x86@fuzzyneural.net>") */
++	.phys_io		= 0xfff00000,
++	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
++	.boot_params	= 0x10000100,
++	.map_io			= h6300_map_io,
++	.init_irq		= h6300_init_irq,
++	.init_machine	= h6300_init,
++	.timer			= &omap_timer,
++MACHINE_END
+diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/Kconfig h6300_dev/arch/arm/mach-omap1/Kconfig
+--- linux-2.6.16.16/arch/arm/mach-omap1/Kconfig	2006-05-17 21:41:27.000000000 +0300
++++ h6300_dev/arch/arm/mach-omap1/Kconfig	2006-04-02 20:47:24.000000000 +0300
+@@ -26,6 +26,15 @@
+           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
+           have such a board.
+ 
++config MACH_OMAP_H6300
++	bool "HP iPAQ h6300 series"
++	depends on ARCH_OMAP1 && ARCH_OMAP15XX
++	select I2C
++	select PCA9535
++	help
++          HP iPAQ h6315, h6340 and h6365 devices that are based 
++          on the OMAP 1510. Say Y here if you have such a device.
++
+ config MACH_OMAP_H2
+ 	bool "TI H2 Support"
+ 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
+diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/Makefile h6300_dev/arch/arm/mach-omap1/Makefile
+--- linux-2.6.16.16/arch/arm/mach-omap1/Makefile	2006-05-17 21:41:28.000000000 +0300
++++ h6300_dev/arch/arm/mach-omap1/Makefile	2006-04-02 00:23:01.000000000 +0300
+@@ -23,6 +23,7 @@
+ obj-$(CONFIG_MACH_OMAP_PALMTE)		+= board-palmte.o
+ obj-$(CONFIG_MACH_NOKIA770)		+= board-nokia770.o
+ obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o
++obj-$(CONFIG_MACH_OMAP_H6300)		+= board-h6300.o
+ 
+ ifeq ($(CONFIG_ARCH_OMAP15XX),y)
+ # Innovator-1510 FPGA
+@@ -36,4 +37,3 @@
+ led-$(CONFIG_MACH_OMAP_PERSEUS2)	+= leds-h2p2-debug.o
+ led-$(CONFIG_MACH_OMAP_OSK)		+= leds-osk.o
+ obj-$(CONFIG_LEDS)			+= $(led-y)
+-
+diff -Naur linux-2.6.16.16/arch/arm/mach-omap1/mux.c h6300_dev/arch/arm/mach-omap1/mux.c
+--- linux-2.6.16.16/arch/arm/mach-omap1/mux.c	2006-05-17 21:41:28.000000000 +0300
++++ h6300_dev/arch/arm/mach-omap1/mux.c	2006-02-21 23:54:33.000000000 +0200
+@@ -200,6 +200,13 @@
+ MUX_CFG("P15_1610_UWIRE_CS3",	 8,   12,    1,	  1,  22,   0,	  1,	 1,  1)
+ MUX_CFG("N15_1610_UWIRE_CS1",	 7,   18,    2,	  1,  14,   0,	 NA,	 0,  1)
+ 
++/* OMAP-1510 uWire */
++MUX_CFG("P15_1510_UWIRE_CS3",  8,   12,    1,	 NA,   0,   0,  NA,  0,  1)
++MUX_CFG("N14_1510_UWIRE_CS0",  8,    9,    1,	 NA,   0,   0,  NA,  0,  1)
++MUX_CFG("V19_1510_UWIRE_SCLK", 8,    6,    0,	 NA,   0,   0,  NA,  0,  1)
++MUX_CFG("W21_1510_UWIRE_SDO",  8,    3,    0,	 NA,   0,   0,  NA,  0,  1)
++MUX_CFG("U18_1510_UWIRE_SDI",  8,    0,    0,	  1,  18,   0,  NA,  0,  1)
++
+ /* OMAP-1610 Flash */
+ MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,	 NA,   0,   0,	 NA,	 0,  1)
+ MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,	 NA,   0,   0,	 NA,	 0,  1)
+@@ -262,6 +269,7 @@
+ MUX_CFG("T20_1610_LOW_PWR",	 7,   12,    1,	  NA,   0,   0,   NA,	 0,  0)
+ 
+ /* MCLK Settings */
++MUX_CFG("R10_1510_MCLK_ON",	 B,   18,    0,	  2,   22,   1,   NA,	 1,  1)
+ MUX_CFG("V5_1710_MCLK_ON",	 B,   15,    0,	  NA,   0,   0,   NA,	 0,  0)
+ MUX_CFG("V5_1710_MCLK_OFF",	 B,   15,    6,	  NA,   0,   0,   NA,	 0,  0)
+ MUX_CFG("R10_1610_MCLK_ON",	 B,   18,    0,	  NA,  22,   0,	  NA,	 1,  0)
+diff -Naur linux-2.6.16.16/arch/arm/plat-omap/devices.c h6300_dev/arch/arm/plat-omap/devices.c
+--- linux-2.6.16.16/arch/arm/plat-omap/devices.c	2006-05-17 21:41:28.000000000 +0300
++++ h6300_dev/arch/arm/plat-omap/devices.c	2006-05-18 00:59:02.000000000 +0300
+@@ -92,7 +92,7 @@
+ 
+ static void omap_init_kp(void)
+ {
+-	if (machine_is_omap_h2() || machine_is_omap_h3()) {
++	if (machine_is_omap_h2() || machine_is_omap_h3() || machine_is_omap_h6300()) {
+ 		omap_cfg_reg(F18_1610_KBC0);
+ 		omap_cfg_reg(D20_1610_KBC1);
+ 		omap_cfg_reg(D19_1610_KBC2);
+diff -Naur linux-2.6.16.16/arch/arm/plat-omap/dma.c h6300_dev/arch/arm/plat-omap/dma.c
+--- linux-2.6.16.16/arch/arm/plat-omap/dma.c	2006-05-17 21:41:28.000000000 +0300
++++ h6300_dev/arch/arm/plat-omap/dma.c	2006-02-06 15:36:21.000000000 +0200
+@@ -30,6 +30,7 @@
+ #include <asm/hardware.h>
+ #include <asm/dma.h>
+ #include <asm/io.h>
++#include <asm/mach-types.h>
+ 
+ #include <asm/arch/tc.h>
+ 
+@@ -1086,6 +1087,10 @@
+ 	}
+ 
+ 	if (omap_dma_in_1510_mode()) {
++		u16 l = omap_readw(OMAP1510_DMA_LCD_CTRL);
++		l &= ~(1 << 6);
++		omap_writew (l, OMAP1510_DMA_LCD_CTRL);
++
+ 		omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
+ 		omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
+ 		omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
+diff -Naur linux-2.6.16.16/arch/arm/tools/mach-types h6300_dev/arch/arm/tools/mach-types
+--- linux-2.6.16.16/arch/arm/tools/mach-types	2006-05-11 04:56:24.000000000 +0300
++++ h6300_dev/arch/arm/tools/mach-types	2006-04-24 20:53:29.000000000 +0300
+@@ -576,7 +576,7 @@
+ s3c2460			MACH_S3C2460		S3C2460			560
+ pdm			MACH_PDM		PDM			561
+ h4700			MACH_H4700		H4700			562
+-h6300			MACH_H6300		H6300			563
++omap_h6300		MACH_OMAP_H6300		OMAP_H6300		563
+ rz1700			MACH_RZ1700		RZ1700			564
+ a716			MACH_A716		A716			565
+ estk2440a		MACH_ESTK2440A		ESTK2440A		566
+diff -Naur linux-2.6.16.16/drivers/bluetooth/Kconfig h6300_dev/drivers/bluetooth/Kconfig
+--- linux-2.6.16.16/drivers/bluetooth/Kconfig	2006-05-17 21:41:29.000000000 +0300
++++ h6300_dev/drivers/bluetooth/Kconfig	2006-02-21 23:54:33.000000000 +0200
+@@ -166,6 +166,16 @@
+ 
+ 	  Say Y here to compile support for virtual HCI devices into the
+ 	  kernel or say M to compile it as module (hci_vhci).
++	  
++config BT_H6300
++	tristate "H6300 BRF6100 BT DRIVER"
++	help
++	  Bluetooth H6300 BRF6100 driver.
++	  This driver provides the firmware loading mechanism for the BRF6100
++	  bt hardware in iPAQ h6300.
++
++	  Say Y here to compile support for BRF6100 BT devices into the
++	  kernel or say M to compile it as module (h6300_BT).	  
+ 
+ endmenu
+ 
+diff -Naur linux-2.6.16.16/drivers/bluetooth/Makefile h6300_dev/drivers/bluetooth/Makefile
+--- linux-2.6.16.16/drivers/bluetooth/Makefile	2006-05-17 21:41:29.000000000 +0300
++++ h6300_dev/drivers/bluetooth/Makefile	2006-02-21 23:54:33.000000000 +0200
+@@ -13,6 +13,7 @@
+ obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
+ obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
+ obj-$(CONFIG_BT_HCIBRF6150)	+= brf6150.o
++obj-$(CONFIG_BT_H6300)		+= omap/
+ 
+ hci_uart-y				:= hci_ldisc.o
+ hci_uart-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o
+diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_brf6100.c h6300_dev/drivers/bluetooth/omap/h6300_bt_brf6100.c
+--- linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_brf6100.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/bluetooth/omap/h6300_bt_brf6100.c	2006-01-23 00:09:23.000000000 +0200
+@@ -0,0 +1,154 @@
++/* 
++ * Bluetooth interface driver for TI BRF6100 on h6300
++ * 
++ * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
++ * Ideas taken from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
++ * 
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++#include <asm/arch/h6300_uart_info.h>
++#include "h6300_bt_led.h"
++
++static void
++h6300_bt_configure(struct uart_omap_port *up, int enable)
++{
++	printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable);
++	
++	// printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
++	if (enable == 0) {
++		omap_set_gpio_dataout(GPIO_N_BT_RST, 1);	// turn off gpio, note 1 == off for negative gpios
++		mdelay(5);
++		h6300_clear_led(INDEX_BT_LED);
++	}
++	else if (enable == 1) {
++		omap_set_gpio_dataout(GPIO_N_BT_RST, 1);	// turn on gpio, note 0 == on for negative gpios
++		mdelay(5);				
++	}
++	else if (enable == 2) {
++		/*
++		 * BRF6150's RTS goes low when firmware is ready
++		 * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms
++		 */
++/*		
++		int tries = 0; 
++		do 
++		{
++			mdelay(10);
++		} 
++		while ((BTMSR & MSR_CTS) == 0 && tries++ < 50);
++*/				
++		h6300_set_led(INDEX_BT_LED, 16, 16);
++	}
++	printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n");
++}
++
++static void
++h6300_bt_set_txrx(struct uart_omap_port *up, int txrx)
++{
++	printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx);
++	/* do nothing */
++}
++
++static int
++h6300_bt_get_txrx(struct uart_omap_port *up)
++{
++	printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n");
++	/* do nothing */
++	return 0;
++}
++
++static int
++h6300_bt_probe(struct platform_device *pdev)
++{
++	struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data;
++
++	omap_request_gpio(GPIO_BT_PWR_EN);		// ask bt_power_en gpio, remember to release in remove_function
++	omap_set_gpio_direction(GPIO_BT_PWR_EN, 1);	// set gpio direction to be output
++	omap_set_gpio_dataout(GPIO_BT_PWR_EN, 1);	// turn on gpio
++
++	mdelay(200);
++
++	omap_request_gpio(GPIO_N_BT_RST);		// ask bt_reset gpio, remember to release in remove_function
++	omap_set_gpio_direction(GPIO_N_BT_RST, 1);	// set gpio direction to be output
++	omap_set_gpio_dataout(GPIO_N_BT_RST, 0);	// turn on gpio, note 0 == on for negative gpios
++	
++	/* configure bluetooth UART */
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
++
++	funcs->configure	= h6300_bt_configure;
++	funcs->set_txrx		= h6300_bt_set_txrx;
++	funcs->get_txrx		= h6300_bt_get_txrx;
++
++	/* Make sure the LED is off */
++	h6300_clear_led(INDEX_BT_LED);
++	
++	printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n");	
++
++	return 0;
++}
++
++static int
++h6300_bt_remove(struct platform_device *pdev)
++{
++	struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data;
++	
++	printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n");	
++	
++	omap_free_gpio(GPIO_BT_PWR_EN);
++	omap_free_gpio(GPIO_N_BT_RST);
++
++	funcs->configure	= NULL;
++	funcs->set_txrx		= NULL;
++	funcs->get_txrx		= NULL;
++
++	/* Make sure the LED is off */
++	h6300_clear_led(INDEX_BT_LED);
++	
++	printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n");
++
++	return 0;
++}
++
++static struct platform_driver bt_driver = {
++	.probe    = h6300_bt_probe,
++	.remove   = h6300_bt_remove,
++	.driver = {
++		.name =	"h6300_bt",
++	},
++};
++
++static int __init
++h6300_bt_init(void)
++{
++	printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n");
++	return platform_driver_register(&bt_driver);
++}
++
++static void __exit
++h6300_bt_exit(void)
++{
++	printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n");
++	platform_driver_unregister(&bt_driver);
++}
++
++module_init(h6300_bt_init);
++module_exit(h6300_bt_exit);
++
++MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
++MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver.");
++MODULE_LICENSE("GPL");
++
+diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.c h6300_dev/drivers/bluetooth/omap/h6300_bt_led.c
+--- linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/bluetooth/omap/h6300_bt_led.c	2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,41 @@
++/* 
++ * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300.
++ * 
++ * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
++ * Ideas from the brf6150 bt driver made by Todd Blumer for the pxa hx4700.
++ * 
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++/* 
++ * Low level access for disabling h6300 bt led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_clear_led(int led_num)
++{
++	printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n");
++	//hx4700_set_led(led_num, 0, 16);
++}
++EXPORT_SYMBOL(h6300_clear_led);
++
++/* 
++ * Low level access for setting up the bt led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_set_led(int led_num, int duty_time, int cycle_time)
++{
++	printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n");
++}
++EXPORT_SYMBOL(h6300_set_led);
+diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.h h6300_dev/drivers/bluetooth/omap/h6300_bt_led.h
+--- linux-2.6.16.16/drivers/bluetooth/omap/h6300_bt_led.h	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/bluetooth/omap/h6300_bt_led.h	2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,9 @@
++#ifndef H6300_BT_LED_H_
++#define H6300_BT_LED_H_
++
++#define INDEX_BT_LED	2
++
++void h6300_clear_led(int led_num);
++void h6300_set_led(int led_num, int duty_time, int cycle_time);
++
++#endif /*H6300_BT_LED_H_*/
+diff -Naur linux-2.6.16.16/drivers/bluetooth/omap/Makefile h6300_dev/drivers/bluetooth/omap/Makefile
+--- linux-2.6.16.16/drivers/bluetooth/omap/Makefile	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/bluetooth/omap/Makefile	2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,6 @@
++#
++# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
++#
++
++h6300_bt-objs				:= h6300_bt_led.o h6300_bt_brf6100.o
++obj-$(CONFIG_BT_H6300)		+= h6300_bt.o
+diff -Naur linux-2.6.16.16/drivers/i2c/busses/i2c-omap.c h6300_dev/drivers/i2c/busses/i2c-omap.c
+--- linux-2.6.16.16/drivers/i2c/busses/i2c-omap.c	2006-05-17 21:41:29.000000000 +0300
++++ h6300_dev/drivers/i2c/busses/i2c-omap.c	2006-04-02 00:23:01.000000000 +0300
+@@ -163,17 +163,22 @@
+ 
+ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+ {
+-	if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
++	if (cpu_is_omap24xx()) {
+ 		dev->iclk = clk_get(dev->dev, "i2c_ick");
+-		if (IS_ERR(dev->iclk))
++		if (IS_ERR(dev->iclk)) {
+ 			return -ENODEV;
++		}
++		dev->fclk = clk_get(dev->dev, "i2c_fck");
++		if (IS_ERR(dev->fclk)) {
++			clk_put(dev->fclk);
++			return -ENODEV;
++		}
+ 	}
+ 
+-	dev->fclk = clk_get(dev->dev, "i2c_fck");
+-	if (IS_ERR(dev->fclk)) {
+-		if (dev->iclk != NULL)
+-			clk_put(dev->iclk);
+-		return -ENODEV;
++	if (cpu_class_is_omap1()) {
++		dev->fclk = clk_get(dev->dev, "i2c_fck");
++		if (IS_ERR(dev->fclk))
++			return -ENODEV;
+ 	}
+ 
+ 	return 0;
+diff -Naur linux-2.6.16.16/drivers/i2c/chips/Kconfig h6300_dev/drivers/i2c/chips/Kconfig
+--- linux-2.6.16.16/drivers/i2c/chips/Kconfig	2006-05-17 21:41:29.000000000 +0300
++++ h6300_dev/drivers/i2c/chips/Kconfig	2006-04-24 20:53:29.000000000 +0300
+@@ -46,6 +46,16 @@
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called pcf8574.
+ 
++config PCA9535
++        tristate "Philips PCA9535 16-bit I/O port"
++        depends on I2C 
++        help
++          If you say yes here you get support for the Philips PCA9535
++          16-bit I/O port.
++	
++          This driver can also be built as a module.  If so, the module
++          will be called pca9535.
++
+ config SENSORS_PCA9539
+ 	tristate "Philips PCA9539 16-bit I/O port"
+ 	depends on I2C && EXPERIMENTAL
+diff -Naur linux-2.6.16.16/drivers/i2c/chips/Makefile h6300_dev/drivers/i2c/chips/Makefile
+--- linux-2.6.16.16/drivers/i2c/chips/Makefile	2006-05-17 21:41:29.000000000 +0300
++++ h6300_dev/drivers/i2c/chips/Makefile	2006-04-24 20:53:29.000000000 +0300
+@@ -7,6 +7,7 @@
+ obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
+ obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
+ obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
++obj-$(CONFIG_PCA9535)   		+= pca9535.o
+ obj-$(CONFIG_SENSORS_PCA9539)	+= pca9539.o
+ obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
+ obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
+diff -Naur linux-2.6.16.16/drivers/i2c/chips/pca9535.c h6300_dev/drivers/i2c/chips/pca9535.c
+--- linux-2.6.16.16/drivers/i2c/chips/pca9535.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/i2c/chips/pca9535.c	2006-04-24 20:53:29.000000000 +0300
+@@ -0,0 +1,412 @@
++/*
++    Driver for Philips PCA9535 16-bit low power I/O port with interrupt
++
++    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., 675 Mass Ave, Cambridge, MA 02139, USA.
++    
++    Copyright (C) 2005 Husam Senussi
++    Framework based on Pawel Kolodziejski's pca9535 driver in 
++    handheld.org's 2.6.13 kernel. Driver updated by Mika Laitio.
++*/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/hwmon.h>
++#include <linux/err.h>
++
++#include <asm/arch/pca9535.h>
++#include <linux/delay.h>
++
++#include <linux/interrupt.h>
++#include <asm/mach-types.h>
++#include <asm/irq.h>
++#include <asm/mach/arch.h>
++#include <asm/hardware.h>
++
++EXPORT_SYMBOL(pca9535_gpio_read);
++EXPORT_SYMBOL(pca9535_gpio_write);
++EXPORT_SYMBOL(pca9535_gpio_direction);
++
++static int pca9535_attach_adapter(struct i2c_adapter *adapter);
++static int pca9535_detach_client(struct i2c_client *client);
++static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one);
++static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr);
++static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 param);
++
++enum pca9535_cmd
++{
++        PCA9535_INPUT_0         = 0,
++        PCA9535_INPUT_1         = 1,
++        PCA9535_OUTPUT_0        = 2,
++        PCA9535_OUTPUT_1        = 3,
++        PCA9535_INVERT_0        = 4,
++        PCA9535_INVERT_1        = 5,
++        PCA9535_DIRECTION_0     = 6,
++        PCA9535_DIRECTION_1     = 7,
++};
++
++struct pca9535_data {
++	struct semaphore  lock;
++        struct i2c_client client;
++};
++
++static struct i2c_driver pca9535_driver = {
++        .driver = {
++                .name   = "pca9535",
++        },
++	.attach_adapter		= pca9535_attach_adapter,
++	.detach_client		= pca9535_detach_client,
++};
++
++static struct i2c_client   *pca9535_i2c_client = NULL;
++static struct pca9535_data pca9535_inited;
++
++static unsigned short normal_i2c[] = { 0x20, I2C_CLIENT_END };
++
++#define DRIVER_VERSION  "20 OCT 2005"
++#define DRIVER_NAME     "PCA9535"
++
++/* 
++ * sysfs callback function.
++ */ 
++static ssize_t pca9535_show(struct device *dev, struct device_attribute *attr,
++                            char *buf)
++{
++        struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
++        struct i2c_client *client = to_i2c_client(dev);
++        return sprintf(buf, "%02X\n", (pca9535_read_reg(client, psa->index) >> 8));
++}
++
++/* 
++ * sysfs callback function.
++ */ 
++static ssize_t pca9535_store(struct device *dev, struct device_attribute *attr,
++                             const char *buf, size_t count)
++{
++        struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
++        struct i2c_client *client = to_i2c_client(dev);
++        unsigned long val = simple_strtoul(buf, NULL, 0);
++	unsigned long old = pca9535_read_reg(client, psa->index);
++
++        if (val > 0xff)
++                return -EINVAL;
++	
++	val = (old & 0xff) | (val << 8);
++        pca9535_write_reg(client, psa->index, val);
++        return count;
++}
++
++#define PCA9535_ENTRY_RO(name, cmd_idx) \
++        static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9535_show, NULL, cmd_idx)
++
++#define PCA9535_ENTRY_RW(name, cmd_idx) \
++        static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9535_show, \
++                                  pca9535_store, cmd_idx)
++
++PCA9535_ENTRY_RO(input0, PCA9535_INPUT_0);
++PCA9535_ENTRY_RO(input1, PCA9535_INPUT_1);
++PCA9535_ENTRY_RW(output0, PCA9535_OUTPUT_0);
++PCA9535_ENTRY_RW(output1, PCA9535_OUTPUT_1);
++PCA9535_ENTRY_RW(invert0, PCA9535_INVERT_0);
++PCA9535_ENTRY_RW(invert1, PCA9535_INVERT_1);
++PCA9535_ENTRY_RW(direction0, PCA9535_DIRECTION_0);
++PCA9535_ENTRY_RW(direction1, PCA9535_DIRECTION_1);
++
++static struct attribute *pca9535_attributes[] = {
++        &sensor_dev_attr_input0.dev_attr.attr,
++        &sensor_dev_attr_input1.dev_attr.attr,
++        &sensor_dev_attr_output0.dev_attr.attr,
++        &sensor_dev_attr_output1.dev_attr.attr,
++        &sensor_dev_attr_invert0.dev_attr.attr,
++        &sensor_dev_attr_invert1.dev_attr.attr,
++        &sensor_dev_attr_direction0.dev_attr.attr,
++        &sensor_dev_attr_direction1.dev_attr.attr,
++        NULL
++};
++
++static struct attribute_group pca9535_defattr_group = {
++        .attrs = pca9535_attributes,
++};
++//End of sysfs management code. 
++
++I2C_CLIENT_INSMOD;
++
++u32 pca9535_read_input(void)
++{
++	return pca9535_read_reg(pca9535_i2c_client, 0);
++}
++EXPORT_SYMBOL(pca9535_read_input);
++
++void pca9535_write_output(u16 param)
++{
++	pca9535_write_reg(pca9535_i2c_client, 2, param);
++}
++EXPORT_SYMBOL(pca9535_write_output);
++
++void pca9535_set_dir(u16 param)
++{
++	pca9535_write_reg(pca9535_i2c_client, 6, param);
++}
++EXPORT_SYMBOL(pca9535_set_dir);
++
++static int pca9535_attach_adapter(struct i2c_adapter *adapter)
++{
++	return i2c_probe(adapter, &addr_data, pca9535_attach);
++}
++
++static int pca9535_attach(struct i2c_adapter *adapter, int address, int zero_or_minus_one)
++{
++	struct i2c_client *new_client;
++	int err = 0;
++
++	new_client = &(pca9535_inited.client);
++	i2c_set_clientdata(new_client, 0);
++	new_client->addr = address;
++	new_client->adapter = adapter;
++	new_client->driver = &pca9535_driver;
++	strcpy(new_client->name, DRIVER_NAME);
++
++	if ((err = i2c_attach_client(new_client)))
++		goto exit_free;
++
++	pca9535_i2c_client = new_client;
++	
++	init_MUTEX(&pca9535_inited.lock);
++	i2c_set_clientdata(pca9535_i2c_client, &pca9535_inited);
++	
++	sysfs_create_group(&pca9535_i2c_client->dev.kobj, &pca9535_defattr_group);
++	
++	printk("pca9535_attach() ok, address = %d, zero_or_minus_one = %d\n", address, zero_or_minus_one);
++	return 0;
++
++exit_free:
++	printk("pca9535_attach() failed, error code = %d\n", err);
++	return err;
++}
++
++static int pca9535_detach_client(struct i2c_client *client)
++{
++	int err;
++
++	if ((err = i2c_detach_client(client))) {
++		dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
++		return err;
++	}
++	pca9535_i2c_client = NULL;
++
++	return 0;
++}
++
++static int __init pca9535_init(void)
++{
++	return i2c_add_driver(&pca9535_driver);
++}
++
++static void __exit pca9535_exit(void)
++{
++        i2c_del_driver(&pca9535_driver);
++}
++
++/* 
++ * Reads the value of GPIO available via I2C.
++ */
++int pca9535_gpio_read(int gpio){
++	unsigned char reg = 0;
++	unsigned long val = 0;
++
++	printk("9535_gpio_read() called\n");
++	if(!pca9535_i2c_client)
++		return -ENODEV;
++
++	if(gpio < GPIO0 || gpio > GPIO17)
++		return -EINVAL;
++
++	if(gpio >= GPIO0 && gpio <= GPIO7){
++		reg   	 = PCA9535_INPUT_0;
++		gpio	-= GPIO0;
++	}else if(gpio >= GPIO8 && gpio <= GPIO17){
++		reg    	 = PCA9535_INPUT_1;
++                gpio    -= GPIO8;
++	}
++
++	down(&pca9535_inited.lock);
++
++	// Read the existing values first
++	val = pca9535_read_reg(pca9535_i2c_client, reg) >> 8;
++	val = (val >> gpio) & 0x01;
++
++	up(&pca9535_inited.lock);
++
++	return val;
++}
++
++/* 
++ * Set the value of I2C GPIO.
++ */
++int pca9535_gpio_write(int gpio, unsigned char value){
++	unsigned char in_reg  = 0;
++        unsigned char out_reg = 0;
++        unsigned long val = 0;
++	unsigned long old = 0;
++	int	      ret = 0;
++
++        if(!pca9535_i2c_client)
++                return -ENODEV;
++
++        if(gpio < GPIO0 || gpio > GPIO17)
++                return -EINVAL;
++
++        if(gpio >= GPIO0 && gpio <= GPIO7){
++                in_reg   = PCA9535_INPUT_0;
++                out_reg  = PCA9535_OUTPUT_0;
++                gpio    -= GPIO0;
++        }else if(gpio >= GPIO8 && gpio <= GPIO17){
++                in_reg   = PCA9535_INPUT_1;
++                out_reg  = PCA9535_OUTPUT_1;
++                gpio    -= GPIO8;
++        }
++
++	down(&pca9535_inited.lock);
++
++        // Read the existing values first
++        val = pca9535_read_reg(pca9535_i2c_client, in_reg);
++	old = val >> 8;
++
++	switch(value){
++	case LOW:
++		old |= (1 << gpio);
++		break;
++	case HI:
++		old &= ~(1 << gpio);
++		break;
++	default:
++		ret = -EINVAL;
++		goto error;
++	}
++
++	val = (val & 0xff) | (old << 8);	
++
++	// write the values back to the register
++	pca9535_write_reg(pca9535_i2c_client, out_reg, val);
++error:
++
++	up(&pca9535_inited.lock);
++	return ret;
++}
++
++/*
++ * Set the direction of I2C GPIO.
++ */ 
++int pca9535_gpio_direction(int gpio, unsigned char direction){
++        unsigned char reg = 0;
++        unsigned long val = 0;
++	unsigned long old = 0;
++        int           ret = 0;
++
++        if(!pca9535_i2c_client)
++                return -ENODEV;
++
++        if(gpio < GPIO0 || gpio > GPIO17)
++                return -EINVAL;
++
++        if(gpio >= GPIO0 && gpio <= GPIO7){
++                reg   	 = PCA9535_DIRECTION_0;
++                gpio    -= GPIO0;
++        }else if(gpio >= GPIO8 && gpio <= GPIO17){
++                reg   	 = PCA9535_DIRECTION_1;
++                gpio    -= GPIO8;
++        }
++
++        down(&pca9535_inited.lock);
++
++        // Read the existing values first
++        old = pca9535_read_reg(pca9535_i2c_client, reg);
++	val = old >> 8;
++
++        switch(direction){
++        case GPIO_INPUT: 
++                val |= (1 << gpio);
++                break;
++        case GPIO_OUTPUT: 
++                val &= ~(1 << gpio);
++                break;
++        default:
++                ret = -EINVAL;
++                goto error;
++        }
++
++	val = (old & 0xff) | (val << 8);
++
++        // write the values back to the register
++        pca9535_write_reg(pca9535_i2c_client, reg, val);
++error:
++
++        up(&pca9535_inited.lock);
++        return ret;
++}
++
++static u32 pca9535_read_reg(struct i2c_client *client, u8 regaddr)
++{
++	char buffer[3];
++	int r;
++	u32 data;
++
++	buffer[0] = regaddr;
++	buffer[1] = 0;
++	buffer[2] = 0;
++
++	r = i2c_master_send(client, buffer, 1);
++	if (r != 1) {
++		printk(KERN_ERR "pca9535: read failed, status %d\n", r);
++		return 0xffffffff;
++	}
++
++	r = i2c_master_recv(client, buffer, 3);
++	if (r != 3) {
++		printk(KERN_ERR "pca9535: read failed, status %d\n", r);
++		return 0xffffffff;
++	}
++
++	data = buffer[1];
++	data |= buffer[2] << 8;
++	//printk(KERN_ERR "%s: reading %x in %x\n", __FUNCTION__, data, regaddr);
++
++	return data;
++}
++
++static void pca9535_write_reg(struct i2c_client *client, u8 regaddr, u16 data)
++{
++	char buffer[3];
++	int r;
++
++	//printk(KERN_ERR "%s: writing %x in %x\n", __FUNCTION__, data, regaddr);
++	buffer[0] = regaddr;
++	buffer[1] = data >> 8;
++	buffer[2] = data & 0xff;
++
++	r = i2c_master_send(client, buffer, 3);
++	if (r != 3) {
++		printk(KERN_ERR "pca9535: write failed, status %d\n", r);
++	}
++}
++
++MODULE_AUTHOR("Husam Senussi <husamsenussi@gmail.com>");
++MODULE_DESCRIPTION("PCA9535 driver");
++MODULE_LICENSE("GPL");
++
++module_init(pca9535_init);
++module_exit(pca9535_exit);
+diff -Naur linux-2.6.16.16/drivers/input/keyboard/omap-keypad.c h6300_dev/drivers/input/keyboard/omap-keypad.c
+--- linux-2.6.16.16/drivers/input/keyboard/omap-keypad.c	2006-05-17 21:41:29.000000000 +0300
++++ h6300_dev/drivers/input/keyboard/omap-keypad.c	2006-04-24 20:53:29.000000000 +0300
+@@ -4,11 +4,12 @@
+  * OMAP Keypad Driver
+  *
+  * Copyright (C) 2003 Nokia Corporation
+- * Written by Timo Ter�s <ext-timo.teras@nokia.com>
++ * Written by Timo Ter�s <ext-timo.teras@nokia.com>
++ * iPAQ h6300 key and joypad support added by Mika Laitio. (2005)
+  *
+  * Added support for H2 & H3 Keypad
+  * Copyright (C) 2004 Texas Instruments
+- *
++ * 
+  * 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
+@@ -44,6 +45,19 @@
+ #include <asm/arch/mux.h>
+ 
+ #undef NEW_BOARD_LEARNING_MODE
++//#define NEW_BOARD_LEARNING_MODE 1
++
++/*
++ * Following 5 keypad events are not really sent to userspace. 
++ * Instead if the good combination of them is sent, then that is send.
++ * (up, right, down, left, enter)
++ */
++#define	_H6300_JOYPAD_UP_RIGHT		1	// 00001
++#define _H6300_JOYPAD_DOWN_RIGHT	2	// 00010
++#define _h6300_JOYPAD_DOWN_LEFT		4	// 00100
++#define _h6300_JOYPAD_UP_LEFT		8	// 01000
++#define _H6300_JOYPAD_KEY_OK		16	// 10000
++#define _H6300_JOYPAD_REPORT_COLUMN	4
+ 
+ static void omap_kp_tasklet(unsigned long);
+ static void omap_kp_timer(unsigned long);
+@@ -53,6 +67,8 @@
+ static int kp_enable = 1;
+ static int kp_cur_group = -1;
+ 
++static int prevJoypadKeycodePressEmulated;
++
+ struct omap_kp {
+ 	struct input_dev *input;
+ 	struct timer_list timer;
+@@ -139,7 +155,7 @@
+ 		for (col = 0; col < omap_kp->cols; col++) {
+ 			omap_writew(~(1 << col) & 0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
+ 
+-			if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3()) {
++			if (machine_is_omap_osk() || machine_is_omap_h2() || machine_is_omap_h3() || machine_is_omap_h6300()) {
+ 				udelay(9);
+ 			} else {
+ 				udelay(4);
+@@ -169,17 +185,26 @@
+ 	return -1;
+ }
+ 
++int is_key_down(unsigned char new_state[],
++		int col,
++		int row)
++{
++	return (new_state[col] & (1 << row)) ? 1 : 0;
++}
++
+ static void omap_kp_tasklet(unsigned long data)
+ {
+ 	struct omap_kp *omap_kp_data = (struct omap_kp *) data;
+ 	unsigned char new_state[8], changed, key_down = 0;
+ 	int col, row;
+ 	int spurious = 0;
++	int report_key, report_col, report_row, joypad_checked;	// h6300-joypad specific variables
+ 
+ 	/* check for any changes */
+ 	omap_kp_scan_keypad(omap_kp_data, new_state);
+ 
+ 	/* check for changes and print those */
++	joypad_checked	= 0;
+ 	for (col = 0; col < omap_kp_data->cols; col++) {
+ 		changed = new_state[col] ^ keypad_state[col];
+ 		key_down |= new_state[col];
+@@ -201,14 +226,177 @@
+ 				spurious = 1;
+ 				continue;
+ 			}
+-
+-			if (!(kp_cur_group == (key & GROUP_MASK) ||
+-			      kp_cur_group == -1))
+-				continue;
+-
+-			kp_cur_group = key & GROUP_MASK;
+-			input_report_key(omap_kp_data->input, key & ~GROUP_MASK,
+-					 !!(new_state[col] & (1 << row)));
++ 			if (machine_is_omap_h6300() && 
++ 			   ((col == 1) || (col == _H6300_JOYPAD_REPORT_COLUMN)))
++ 			{
++ 				if (col == _H6300_JOYPAD_REPORT_COLUMN)
++ 				{
++ 					continue;
++ 				}
++ 				if ((joypad_checked == 0) &&
++ 				    ((key == _H6300_JOYPAD_KEY_OK) ||
++ 				     (key == _h6300_JOYPAD_UP_LEFT) ||
++ 	    			     (key == _H6300_JOYPAD_UP_RIGHT) ||
++ 				     (key == _H6300_JOYPAD_DOWN_RIGHT) ||
++ 				     (key == _h6300_JOYPAD_DOWN_LEFT)))
++ 				{
++ 					if (is_key_down(new_state, col, row))
++ 					{
++ 						/*
++ 						 * only enter pressed
++ 						 * 1 0 0 _H6300_JOYPAD_KEY_OK 0 0
++ 						 * --> 100100 == 36
++ 						 */
++ 						 if (new_state[1] == 36)
++ 						 {
++ 						 	joypad_checked	= 1;
++ 							prevJoypadKeycodePressEmulated	= KEY_ENTER;
++ 							new_state[_H6300_JOYPAD_REPORT_COLUMN]	= 48;	//110000
++ 							report_key	= prevJoypadKeycodePressEmulated;
++ 							report_col	= _H6300_JOYPAD_REPORT_COLUMN;
++ 							report_row	= 4;
++ 							input_report_key(omap_kp_data->input,
++ 									report_key,
++ 							 		new_state[report_col] & (1 << report_row));
++ 						 }						
++ 						/*
++ 						 * enter, up_left and up_right sensors pressed.
++ 						 * 1 _H6300_JOYPAD_UP_RIGHT 0 _H6300_JOYPAD_KEY_OK 0 _h6300_JOYPAD_UP_LEFT
++ 						 * --> 110101 == 53
++ 						 * OR
++ 						 * 1 KEY_UP_RIGHT 0 0 0 _h6300_JOYPAD_UP_LEFT
++ 						 * --> 110001 == 42
++ 						 * --> move to up
++ 						 */
++ 						else if ((new_state[1] == 53) ||
++ 						         (new_state[1] == 49))
++ 						{
++ 							joypad_checked	= 1;
++ 							prevJoypadKeycodePressEmulated	= KEY_UP;
++ 							new_state[_H6300_JOYPAD_REPORT_COLUMN]	= 40;	//101000
++ 							report_key	= prevJoypadKeycodePressEmulated;
++ 							report_col	= _H6300_JOYPAD_REPORT_COLUMN;
++ 							report_row	= 3;
++ 							input_report_key(omap_kp_data->input,
++ 									report_key,
++ 							 		new_state[report_col] & (1 << report_row));
++ 						}
++ 						/*
++ 						 * enter, down_left and down_right sensors pressed
++ 						 * --> 101110 == 46
++ 						 * OR
++ 						 * down_left and down_right
++ 						 * -->101010 == 42
++ 						 * --> move to down
++ 						 */
++ 						else if ((new_state[1] == 46) ||
++ 							 (new_state[1] == 42))
++ 						{
++ 							joypad_checked	= 1;
++ 							prevJoypadKeycodePressEmulated	= KEY_DOWN;
++ 							new_state[_H6300_JOYPAD_REPORT_COLUMN]	= 34;	//100010
++ 							report_key	= prevJoypadKeycodePressEmulated;
++ 							report_col	= _H6300_JOYPAD_REPORT_COLUMN;
++ 							report_row	= 1;
++ 							input_report_key(omap_kp_data->input,
++ 									report_key,
++ 							 		new_state[report_col] & (1 << report_row));
++ 						}												
++ 						/*
++ 						 * enter, up_right and down_right sensors pressed
++ 						 * --> 111100 == 60
++ 						 * or
++ 						 * down_right and up_right
++ 						 * --> 111000 == 56
++ 						 * --> move to right
++ 						 */
++ 						else if ((new_state[1] == 60) ||
++ 							 (new_state[1] == 56))
++ 						{
++ 							joypad_checked	= 1;
++ 							prevJoypadKeycodePressEmulated	= KEY_RIGHT;
++ 							new_state[_H6300_JOYPAD_REPORT_COLUMN]	= 33;	//100001
++ 							report_key	= prevJoypadKeycodePressEmulated;
++ 							report_col	= _H6300_JOYPAD_REPORT_COLUMN;
++ 							report_row	= 0;
++ 							input_report_key(omap_kp_data->input,
++ 									report_key,
++ 							 		new_state[report_col] & (1 << report_row));
++ 						}
++ 						/*
++ 						 * enter, up_left and down_left sensors pressed
++ 						 * --> 100111 == 39
++ 						 * or up_left and down_left
++ 						 * --> 100011 == 35
++ 						 * --> move to left
++ 						 */
++ 						else if ((new_state[1] == 39) ||
++ 							 (new_state[1] == 35))
++ 						{
++ 							joypad_checked	= 1;
++ 							prevJoypadKeycodePressEmulated	= KEY_LEFT;
++ 							new_state[_H6300_JOYPAD_REPORT_COLUMN]	= 36;	//100100
++ 							report_key	= prevJoypadKeycodePressEmulated;
++ 							report_col	= _H6300_JOYPAD_REPORT_COLUMN;
++ 							report_row	= 2;
++ 							input_report_key(omap_kp_data->input,
++ 									report_key,
++ 							 		new_state[report_col] & (1 << report_row));
++ 						}
++ 						else
++ 						{
++ 							//printk("missed new_state = %d\n", new_state[1]);
++ 						}
++ 					}
++ 					else
++ 					{
++ 						if (prevJoypadKeycodePressEmulated != 0)
++ 						{
++ 							// report key up event
++ 							joypad_checked	= 1;
++ 							new_state[_H6300_JOYPAD_REPORT_COLUMN]	= 32;	//100000
++ 							report_key	= prevJoypadKeycodePressEmulated;
++ 							report_col	= _H6300_JOYPAD_REPORT_COLUMN;
++ 							switch(prevJoypadKeycodePressEmulated)
++ 							{
++ 								case KEY_RIGHT:
++									report_row	= 0;
++ 									break;
++ 								case KEY_DOWN:
++ 									report_row	= 1;
++ 									break;
++ 								case KEY_LEFT:
++ 									report_row	= 2;
++ 									break;
++ 								case KEY_UP:
++ 									report_row	= 3;
++ 									break;
++ 								case KEY_ENTER:
++ 									report_row	= 4;
++ 									break;
++ 								default:
++ 									printk(KERN_WARNING "Unknown iPAQ h6300 column 1 key = %d released. This should newer happen!\n",
++ 										key);
++ 									report_row	= 0;
++ 							}
++ 							input_report_key(omap_kp_data->input,
++ 									report_key,
++ 							 		new_state[report_col] & (1 << report_row));
++ 							prevJoypadKeycodePressEmulated	= 0;
++ 						}
++ 					}
++ 				}
++ 			}
++ 			else
++ 			{
++				if (!(kp_cur_group == (key & GROUP_MASK) ||
++				      kp_cur_group == -1))
++					continue;
++
++				kp_cur_group = key & GROUP_MASK;
++				input_report_key(omap_kp_data->input, key & ~GROUP_MASK,
++						 !!(new_state[col] & (1 << row)));
++ 			}
+ #endif
+ 		}
+ 	}
+@@ -348,10 +536,11 @@
+ 			omap_set_gpio_direction(row_gpios[i], 1);
+ 		}
+ 	}
++	prevJoypadKeycodePressEmulated		= 0;
+ 
+ 	init_timer(&omap_kp->timer);
+ 	omap_kp->timer.function = omap_kp_timer;
+-	omap_kp->timer.data = (unsigned long) omap_kp;
++	omap_kp->timer.data = (unsigned long)omap_kp;
+ 
+ 	/* get the irq and init timer*/
+ 	tasklet_enable(&kp_tasklet);
+@@ -376,7 +565,7 @@
+ 	input_register_device(omap_kp->input);
+ 
+ 	if (machine_is_omap_h2() || machine_is_omap_h3() ||
+-	    machine_is_omap_perseus2()) {
++	    machine_is_omap_perseus2() || machine_is_omap_h6300()) {
+ 		omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
+ 	}
+ 	/* scan current status and enable interrupt */
+@@ -447,6 +636,6 @@
+ module_init(omap_kp_init);
+ module_exit(omap_kp_exit);
+ 
+-MODULE_AUTHOR("Timo Ter�s");
++MODULE_AUTHOR("Timo Ter�s");
+ MODULE_DESCRIPTION("OMAP Keypad Driver");
+ MODULE_LICENSE("GPL");
+diff -Naur linux-2.6.16.16/drivers/input/touchscreen/omap/Makefile h6300_dev/drivers/input/touchscreen/omap/Makefile
+--- linux-2.6.16.16/drivers/input/touchscreen/omap/Makefile	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/input/touchscreen/omap/Makefile	2005-10-22 03:52:45.000000000 +0300
+@@ -8,5 +8,6 @@
+ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_H3) += ts_hx.o
+ objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += ts_inn1510.o
+ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_OSK) += ts_osk.o
++objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += ts_hx.o
+ 
+ omapts-objs := omap_ts.o $(objs-yy)
+diff -Naur linux-2.6.16.16/drivers/input/touchscreen/omap/omap_ts.c h6300_dev/drivers/input/touchscreen/omap/omap_ts.c
+--- linux-2.6.16.16/drivers/input/touchscreen/omap/omap_ts.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/input/touchscreen/omap/omap_ts.c	2006-02-21 23:54:33.000000000 +0200
+@@ -46,7 +46,7 @@
+ #define OMAP_TS_NAME	"omap_ts"
+ 
+ static struct ts_device *__initdata ts_devs[] = {
+-#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
++#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) || defined(CONFIG_MACH_OMAP_H6300)
+ 	&hx_ts,
+ #endif
+ #ifdef CONFIG_MACH_OMAP_OSK
+diff -Naur linux-2.6.16.16/drivers/input/touchscreen/omap/ts_hx.c h6300_dev/drivers/input/touchscreen/omap/ts_hx.c
+--- linux-2.6.16.16/drivers/input/touchscreen/omap/ts_hx.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/input/touchscreen/omap/ts_hx.c	2006-04-24 20:53:29.000000000 +0300
+@@ -39,6 +39,7 @@
+ 
+ #define	H2_GPIO_NUM		4
+ #define	H3_GPIO_NUM		48
++#define H6300_GPIO_NUM	2
+ 
+ #define OMAP_TSC2101_XRES		       500
+ #define TOUCHSCREEN_DATA_REGISTERS_PAGE	 0x0
+@@ -88,6 +89,9 @@
+ 	} else if (machine_is_omap_h3()) {
+ 		gpio = H3_GPIO_NUM;
+ 		omap_cfg_reg(W19_1610_GPIO48);
++	} else if (machine_is_omap_h6300 ()) {
++		gpio = H6300_GPIO_NUM;
++		omap_cfg_reg(M14_1510_GPIO2);	
+ 	} else
+ 		return -ENODEV;
+ 
+@@ -180,5 +184,7 @@
+ 		omap_free_gpio(H2_GPIO_NUM);
+ 	else if (machine_is_omap_h3())
+ 		omap_free_gpio(H3_GPIO_NUM);
++	else if (machine_is_omap_h6300())
++		omap_free_gpio(H6300_GPIO_NUM);
+ }
+ #endif
+diff -Naur linux-2.6.16.16/drivers/mmc/mmc.c h6300_dev/drivers/mmc/mmc.c
+--- linux-2.6.16.16/drivers/mmc/mmc.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/mmc/mmc.c	2006-03-28 10:34:39.000000000 +0300
+@@ -964,7 +964,7 @@
+ 		mmc_decode_scr(card);
+ 	}
+ 
+-	mmc_deselect_cards(host);
++	//mmc_deselect_cards(host);
+ }
+ 
+ static unsigned int mmc_calculate_clock(struct mmc_host *host)
+diff -Naur linux-2.6.16.16/drivers/ssi/omap-tsc2101.c h6300_dev/drivers/ssi/omap-tsc2101.c
+--- linux-2.6.16.16/drivers/ssi/omap-tsc2101.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/ssi/omap-tsc2101.c	2006-04-24 20:53:29.000000000 +0300
+@@ -36,10 +36,11 @@
+ #include <asm/arch/hardware.h>
+ #include <asm/hardware/tsc2101.h>
+ #include <asm/arch/gpioexpander.h>
++#include <asm/arch/gpio.h>
+ 
+ #include "omap-tsc2101.h"
+ 
+-#if CONFIG_ARCH_OMAP16XX
++#if CONFIG_ARCH_OMAP1
+ #include <../drivers/ssi/omap-uwire.h>
+ #else
+ #error "Unsupported configuration"
+@@ -66,27 +67,28 @@
+ 	if (count++ == 0) {
+ 		int ret = 0;
+ 		/* set the Mux to provide MCLK to TSC2101 */
+-		if (machine_is_omap_h3()) {
++		if (machine_is_omap_h3())
+ 			ret = omap_cfg_reg(V5_1710_MCLK_ON);
+-		} else {
+-			if (machine_is_omap_h2()) {
+-				ret = omap_cfg_reg(R10_1610_MCLK_ON);
++		else if (machine_is_omap_h2())
++			ret = omap_cfg_reg(R10_1610_MCLK_ON);
++		else if (machine_is_omap_h6300())
++			ret = omap_cfg_reg(R10_1510_MCLK_ON);
++
++		if (!cpu_is_omap1510 ()) {
++			/* Get the MCLK */
++			tsc2101_mclk_ck = clk_get(NULL, "mclk");
++			if (NULL == tsc2101_mclk_ck) {
++				printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
++				ret = -EPERM;
++				goto done;
+ 			}
+-		}
+-
+-		/* Get the MCLK */
+-		tsc2101_mclk_ck = clk_get(NULL, "mclk");
+-		if (NULL == tsc2101_mclk_ck) {
+-			printk(KERN_ERR "Unable to get the clock MCLK!!!\n");;
+-			ret = -EPERM;
+-			goto done;
+-		}
+-		if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
+-			printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
+-			ret = -EPERM;
+-			goto done;
+-		}
+-		clk_enable(tsc2101_mclk_ck);
++			if (clk_set_rate(tsc2101_mclk_ck, 12000000)) {
++				printk(KERN_ERR "Unable to set rate to the MCLK!!!\n");;
++				ret = -EPERM;
++				goto done;
++			}
++			clk_enable(tsc2101_mclk_ck);
++		} /* if (!cpu_is_omap1510 ()) */
+ 
+ 		ret = omap_tsc2101_configure();
+ 
+@@ -116,10 +118,16 @@
+ 			}
+ 		}
+ 
+-		/* Release the MCLK */
+-		clk_disable(tsc2101_mclk_ck);
+-		clk_put(tsc2101_mclk_ck);
+-		tsc2101_mclk_ck = NULL;
++		if (!cpu_is_omap1510 ()) {
++			/* Release the MCLK */
++			clk_disable(tsc2101_mclk_ck);
++			clk_put(tsc2101_mclk_ck);
++			tsc2101_mclk_ck = NULL;
++		}
++
++#if defined(CONFIG_MACH_OMAP_H6300)
++		omap_free_gpio(8);
++#endif
+ 
+ 		module_put(THIS_MODULE);
+ 	}
+@@ -150,7 +158,10 @@
+ 			return;
+ 		}
+ 	}
+-	if (machine_is_omap_h3()) {
++	if (machine_is_omap_h3() || machine_is_omap_h6300()) {
++
++		if (machine_is_omap_h6300())
++			omap_set_gpio_dataout (8, 0);
+ 
+ 		ret =
+ 		    omap_uwire_data_transfer(0, ((page << 11) | (address << 5)),
+@@ -159,6 +170,8 @@
+ 			printk(KERN_ERR
+ 			       "uwire-write returned error for address %x\n",
+ 			       address);
++		if (machine_is_omap_h6300())
++			omap_set_gpio_dataout (8, 1);
+ 			return;
+ 		}
+ 		ret = omap_uwire_data_transfer(0, data, 16, 0, NULL, 0);
+@@ -166,10 +179,14 @@
+ 			printk(KERN_ERR
+ 			       "uwire-write returned error for address %x\n",
+ 			       address);
++			if (machine_is_omap_h6300())
++				omap_set_gpio_dataout (8, 1);
+ 			return;
+ 		}
+-	}
+ 
++		if (machine_is_omap_h6300())
++			omap_set_gpio_dataout (8, 1);
++	}
+ }
+ 
+ void omap_tsc2101_reads(int page, u8 startaddress, u16 * data, int numregs)
+@@ -178,9 +195,13 @@
+ 	if (machine_is_omap_h2()) {
+ 		cs = 1;
+ 	}
+-	if (machine_is_omap_h3()) {
++	if (machine_is_omap_h3() || machine_is_omap_h6300()) {
+ 		cs = 0;
+ 	}
++
++	if (machine_is_omap_h6300())
++		omap_set_gpio_dataout(8, 0);
++
+ 	(void)omap_uwire_data_transfer(cs, (0x8000 | (page << 11)
+ 					    | (startaddress << 5)),
+ 				       16, 0, NULL, 1);
+@@ -188,6 +209,9 @@
+ 		omap_uwire_data_transfer(cs, 0, 0, 16, data, 1);
+ 	}
+ 	omap_uwire_data_transfer(cs, 0, 0, 16, data, 0);
++
++	if (machine_is_omap_h6300())
++		omap_set_gpio_dataout(8, 1);
+ }
+ 
+ u16 omap_tsc2101_read(int page, u8 address)
+@@ -228,9 +252,24 @@
+ 		omap_cfg_reg(N14_1610_UWIRE_CS0);
+ 		omap_uwire_configure_mode(0, uwire_flags);
+ 	}
++	if (machine_is_omap_h6300()) {
++		uwire_flags = UWIRE_READ_RISING_EDGE | UWIRE_WRITE_RISING_EDGE;
++		omap_cfg_reg(N14_1510_UWIRE_CS0);
++		omap_uwire_configure_mode(0, uwire_flags);
++
++		omap_request_gpio(8);
++		omap_set_gpio_dataout(8, 0);
++		omap_set_gpio_direction (8, 0);
++	}
+ 
+ 	/* Configure MCLK enable */
+-	omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);	
++	if (cpu_is_omap16xx() || cpu_is_omap1710())
++		omap_writel(omap_readl(PU_PD_SEL_2) | (1 << 22), PU_PD_SEL_2);	
++	if (machine_is_omap_h6300()) {
++		omap_cfg_reg(V19_1510_UWIRE_SCLK);
++		omap_cfg_reg(W21_1510_UWIRE_SDO);
++		omap_cfg_reg(U18_1510_UWIRE_SDI);
++	}
+ 
+ 	return 0;
+ }
+@@ -243,5 +282,5 @@
+ 
+ MODULE_AUTHOR("Texas Instruments");
+ MODULE_DESCRIPTION
+-    ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
++    ("Glue audio driver for the TI OMAP1510/1610/OMAP1710 TSC2101 codec.");
+ MODULE_LICENSE("GPL");
+diff -Naur linux-2.6.16.16/drivers/ssi/omap-uwire.c h6300_dev/drivers/ssi/omap-uwire.c
+--- linux-2.6.16.16/drivers/ssi/omap-uwire.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/ssi/omap-uwire.c	2006-04-24 20:53:29.000000000 +0300
+@@ -10,7 +10,7 @@
+  * Ported to 2.6 uwire interface.
+  * Copyright (C) 2004 Texas Instruments.
+  *
+- * Generalization patches by Juha Yrj�l� <juha.yrjola@nokia.com>
++ * Generalization patches by Juha Yrj�l� <juha.yrjola@nokia.com>
+  *
+  *  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
+@@ -212,6 +212,10 @@
+ 		omap_cfg_reg(N14_1610_UWIRE_CS0);
+ 		omap_cfg_reg(P15_1610_UWIRE_CS3);
+ 	}
++	if (machine_is_omap_h6300()) {
++		omap_cfg_reg(N14_1510_UWIRE_CS0);
++		omap_cfg_reg(P15_1510_UWIRE_CS3);
++	}
+ 	if (machine_is_omap_perseus2()) {
+ 		/* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
+ 		int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
+diff -Naur linux-2.6.16.16/drivers/telephony/Kconfig h6300_dev/drivers/telephony/Kconfig
+--- linux-2.6.16.16/drivers/telephony/Kconfig	2006-05-11 04:56:24.000000000 +0300
++++ h6300_dev/drivers/telephony/Kconfig	2005-10-06 02:34:39.000000000 +0300
+@@ -41,7 +41,18 @@
+ 	help
+ 	  Say Y here to configure in PCMCIA service support for the Quicknet
+ 	  cards manufactured by Quicknet Technologies, Inc.  This changes the
+-	  card initialization code to work with the card manager daemon.
++	  card initialization code to work with the card manager daemon.	  
++
++config GSM_H6300
++	tristate "H6300 P5186 GSM/GPRS DRIVER"
++	depends on PHONE && I2C && PCA9535
++	help
++	  Bluetooth H6300 P5186 gsm/gprs driver.
++	  This driver provides the firmware loading mechanism for the P5185
++	  gsm/gprs hardware in iPAQ h6300.
++
++	  Say Y here to compile support for P5186 gsm/gprs devices into the
++	  kernel or say M to compile it as module (h6300_gsm).
+ 
+ endmenu
+ 
+diff -Naur linux-2.6.16.16/drivers/telephony/Makefile h6300_dev/drivers/telephony/Makefile
+--- linux-2.6.16.16/drivers/telephony/Makefile	2006-05-11 04:56:24.000000000 +0300
++++ h6300_dev/drivers/telephony/Makefile	2005-10-06 02:34:39.000000000 +0300
+@@ -2,6 +2,7 @@
+ # Makefile for drivers/telephony
+ #
+ 
+-obj-$(CONFIG_PHONE) += phonedev.o
+-obj-$(CONFIG_PHONE_IXJ) += ixj.o
+-obj-$(CONFIG_PHONE_IXJ_PCMCIA) += ixj_pcmcia.o
++obj-$(CONFIG_PHONE)				+= phonedev.o
++obj-$(CONFIG_PHONE_IXJ)			+= ixj.o
++obj-$(CONFIG_PHONE_IXJ_PCMCIA)	+= ixj_pcmcia.o
++obj-$(CONFIG_GSM_H6300)			+= omap/
+diff -Naur linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.c h6300_dev/drivers/telephony/omap/h6300_gsm_led.c
+--- linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/telephony/omap/h6300_gsm_led.c	2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,40 @@
++/* 
++ * GSM interface driver helper for controlling bluetooth leds available in iPAQ h6300.
++ * 
++ * Copyright (C) 2005 Mika Laitio  <lamikr@cc.jyu.fi>
++ * 
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++/* 
++ * Low level access for disabling h6300 gsm led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_clear_gsm_led(int led_num)
++{
++	printk(KERN_NOTICE "h6300_gsm_led.c h6300_clear_gsm_led() done\n");
++	//hx4700_set_led(led_num, 0, 16);
++}
++EXPORT_SYMBOL(h6300_clear_gsm_led);
++
++/* 
++ * Low level access for setting up the gsm led.
++ *
++ * TODO: implement for h6300 
++ */
++void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time)
++{
++	printk(KERN_NOTICE "h6300_gsm_led.c h6300_set_gsm_led() done\n");
++}
++EXPORT_SYMBOL(h6300_set_gsm_led);
+diff -Naur linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.h h6300_dev/drivers/telephony/omap/h6300_gsm_led.h
+--- linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_led.h	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/telephony/omap/h6300_gsm_led.h	2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,10 @@
++#ifndef H6300_GSM_LED_H_
++#define H6300_GSM_LED_H_
++
++#define INDEX_GSM_LED	1
++
++void h6300_clear_gsm_led(int led_num);
++void h6300_set_gsm_led(int led_num, int duty_time, int cycle_time);
++
++
++#endif /*H6300_GSM_LED_H_*/
+diff -Naur linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_p5186.c h6300_dev/drivers/telephony/omap/h6300_gsm_p5186.c
+--- linux-2.6.16.16/drivers/telephony/omap/h6300_gsm_p5186.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/telephony/omap/h6300_gsm_p5186.c	2006-01-23 00:09:23.000000000 +0200
+@@ -0,0 +1,172 @@
++/* 
++ * Wavecom P5186 GPRS and GSM module driver for iPAQ h6300.
++ * 
++ * Copyright (C) 2005 Mika Laitio <lamikr@cc.jyu.fi>
++ * 
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++
++#include <asm/hardware.h>
++#include <asm/arch/gpio.h>
++
++#include <asm/arch/pca9535.h>
++#include <asm/arch/h6300_uart_info.h>
++#include "h6300_gsm_led.h"
++
++static void
++h6300_gsm_configure(struct uart_omap_port *up, int enable)
++{
++	printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() started, enable = %d\n", enable);
++	
++	// printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable );
++	if (enable == 0) {
++		pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_OFF);	// turn off gpio
++		mdelay(5);
++		h6300_clear_gsm_led(INDEX_GSM_LED);
++	}
++	else if (enable == 1) {
++		pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON);	// turn on gpio
++		mdelay(5);				
++	}
++	else if (enable == 2) {
++		h6300_set_gsm_led(INDEX_GSM_LED, 16, 16);
++	}
++	printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_configure() done\n");
++}
++
++static void
++h6300_gsm_set_txrx(struct uart_omap_port *up, int txrx)
++{
++	printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_set_txrx(), txrx = %d done\n", txrx);
++	/* do nothing */
++}
++
++static int
++h6300_gsm_get_txrx(struct uart_omap_port *up)
++{
++	printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_get_txrx() done\n");
++	/* do nothing */
++	return 0;
++}
++
++static int
++h6300_gsm_probe(struct platform_device *pdev)
++{
++	int	ii;
++	int	curVal;
++	
++	struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data;
++/*
++	printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_probe() started\n");	
++	for (ii = 0; ii < 8; ii++)
++	{
++		curVal	= pca9535_gpio_read(ii);
++		printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++	}
++	for (ii = 10; ii < 18; ii++)
++	{
++		curVal	= pca9535_gpio_read(ii);
++		printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++	}
++	printk(KERN_NOTICE "\nfirst check done\n");
++*/
++	pca9535_gpio_direction(GPIO_I2C_GPRS_RESET, GPIO_DIR_OUTPUT);	// set gpio direction to be output
++	pca9535_gpio_write(GPIO_I2C_GPRS_RESET, GPIO_VALUE_ON);	// turn on gpio
++	mdelay(200);
++	
++	pca9535_gpio_direction(GPIO_I2C_MIC_OP_EN, GPIO_DIR_OUTPUT);	// set gpio direction to be output
++	pca9535_gpio_write(GPIO_I2C_MIC_OP_EN, GPIO_VALUE_ON);	// turn on gpio
++	mdelay(200);
++
++	pca9535_gpio_direction(GPIO_I2C_SPK_OP_PD, GPIO_DIR_OUTPUT);	// set gpio direction to be output
++	pca9535_gpio_write(GPIO_I2C_SPK_OP_PD, GPIO_VALUE_ON);	// pd = pulldown?, normal off = on
++
++	mdelay(200);
++	
++	//pca9535_gpio_direction(
++	/* configure bluetooth UART */
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD);
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD);
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD);
++	//h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD);
++
++	funcs->configure	= h6300_gsm_configure;
++	funcs->set_txrx		= h6300_gsm_set_txrx;
++	funcs->get_txrx		= h6300_gsm_get_txrx;
++
++	/* Make sure the LED is off */
++	h6300_clear_gsm_led(INDEX_GSM_LED);	
++/*	
++	for (ii = 0; ii < 8; ii++)
++	{
++		curVal	= pca9535_gpio_read(ii);
++		printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++	}
++	for (ii = 10; ii < 18; ii++)
++	{
++		curVal	= pca9535_gpio_read(ii);
++		printk(KERN_NOTICE "I2C[%d] = %d ", ii, curVal);
++	}
++*/	
++	printk(KERN_NOTICE "\nh6300_gsm_p5186.c h6300_gsm_probe() done\n");
++		
++	return 0;
++}
++
++static int
++h6300_gsm_remove(struct platform_device *pdev)
++{
++	struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data;
++	
++	printk(KERN_NOTICE "h6300_gsm_p5186.c h6300_gsm_remove() started\n");	
++
++	pca9535_gpio_write(GPIO_I2C_GPRS_RESET, 0);	// turn off gpio
++	
++	funcs->configure	= NULL;
++	funcs->set_txrx		= NULL;
++	funcs->get_txrx		= NULL;
++
++	/* Make sure the LED is off */
++	h6300_clear_gsm_led(INDEX_GSM_LED);
++	
++	printk(KERN_NOTICE "h6300_gsm_p5186.c, h6300_gsm_remove() done\n");
++
++	return 0;
++}
++
++static struct platform_driver gsm_driver = {
++	.probe    = h6300_gsm_probe,
++	.remove   = h6300_gsm_remove,
++	.driver = {
++		.name	= "h6300_gsm",
++	},
++};
++
++static int __init
++h6300_gsm_init(void)
++{
++	printk(KERN_NOTICE "h6300 GSM Driver init()\n");
++	return platform_driver_register(&gsm_driver);
++}
++
++static void __exit
++h6300_gsm_exit(void)
++{
++	printk(KERN_NOTICE "h6300 GSM Driver exit()\n");
++	platform_driver_unregister(&gsm_driver);
++}
++
++module_init(h6300_gsm_init);
++module_exit(h6300_gsm_exit);
++
++MODULE_AUTHOR("Mika Laitio, <lamikr@cc.jyu.fi>");
++MODULE_DESCRIPTION("iPAQ h6300 Wavecom P5186 GPRS and GSM module driver.");
++MODULE_LICENSE("GPL");
++
+diff -Naur linux-2.6.16.16/drivers/telephony/omap/Makefile h6300_dev/drivers/telephony/omap/Makefile
+--- linux-2.6.16.16/drivers/telephony/omap/Makefile	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/telephony/omap/Makefile	2005-10-06 02:34:39.000000000 +0300
+@@ -0,0 +1,6 @@
++#
++# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers.
++#
++
++h6300_gsm-objs			:= h6300_gsm_led.o h6300_gsm_p5186.o
++obj-$(CONFIG_GSM_H6300)	+= h6300_gsm.o
+diff -Naur linux-2.6.16.16/drivers/usb/gadget/omap_udc.c h6300_dev/drivers/usb/gadget/omap_udc.c
+--- linux-2.6.16.16/drivers/usb/gadget/omap_udc.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/usb/gadget/omap_udc.c	2006-04-24 20:53:29.000000000 +0300
+@@ -60,7 +60,8 @@
+ #undef	USB_TRACE
+ 
+ /* bulk DMA seems to be behaving for both IN and OUT */
+-#define	USE_DMA
++//#define	USE_DMA
++#undef USE_DMA
+ 
+ /* ISO too */
+ #define	USE_ISO
+@@ -2147,7 +2148,7 @@
+ 	/* boards that don't have VBUS sensing can't autogate 48MHz;
+ 	 * can't enter deep sleep while a gadget driver is active.
+ 	 */
+-	if (machine_is_omap_innovator() || machine_is_omap_osk())
++	if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_omap_h6300())
+ 		omap_vbus_session(&udc->gadget, 1);
+ 
+ done:
+@@ -2170,7 +2171,7 @@
+ 	if (udc->dc_clk != NULL)
+ 		omap_udc_enable_clock(1);
+ 
+-	if (machine_is_omap_innovator() || machine_is_omap_osk())
++	if (machine_is_omap_innovator() || machine_is_omap_osk() || machine_is_omap_h6300())
+ 		omap_vbus_session(&udc->gadget, 0);
+ 
+ 	if (udc->transceiver)
+@@ -2791,7 +2792,7 @@
+ 		hmc = HMC_1510;
+ 		type = "(unknown)";
+ 
+-		if (machine_is_omap_innovator()) {
++		if (machine_is_omap_innovator() || machine_is_omap_h6300()) {
+ 			/* just set up software VBUS detect, and then
+ 			 * later rig it so we always report VBUS.
+ 			 * FIXME without really sensing VBUS, we can't
+diff -Naur linux-2.6.16.16/drivers/usb/host/ohci-omap.c h6300_dev/drivers/usb/host/ohci-omap.c
+--- linux-2.6.16.16/drivers/usb/host/ohci-omap.c	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/usb/host/ohci-omap.c	2006-02-06 15:36:21.000000000 +0200
+@@ -353,11 +353,7 @@
+ 	if (IS_ERR(usb_host_ck))
+ 		return PTR_ERR(usb_host_ck);
+ 
+-	if (!cpu_is_omap1510())
+-		usb_dc_ck = clk_get(0, "usb_dc_ck");
+-	else
+-		usb_dc_ck = clk_get(0, "lb_ck");
+-
++	usb_dc_ck = clk_get(0, "usb_dc_ck");
+ 	if (IS_ERR(usb_dc_ck)) {
+ 		clk_put(usb_host_ck);
+ 		return PTR_ERR(usb_dc_ck);
+diff -Naur linux-2.6.16.16/drivers/video/omap/lcd_h6300.c h6300_dev/drivers/video/omap/lcd_h6300.c
+--- linux-2.6.16.16/drivers/video/omap/lcd_h6300.c	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/drivers/video/omap/lcd_h6300.c	2006-04-24 20:53:29.000000000 +0300
+@@ -0,0 +1,159 @@
++/*
++ * File: drivers/video/omap_new/lcd-h6300.c
++ *
++ * LCD panel support for the TI OMAP1510 Innovator board
++ *
++ * Copyright (C) 2004 Nokia Corporation
++ * Author: Imre Deak <imre.deak@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <asm/io.h>
++
++#include <asm/arch/pca9535.h>
++#include <asm/arch/omapfb.h>
++
++/* #define OMAPFB_DBG 1 */
++
++#include "debug.h"
++
++//static struct clk *h6300_lcd_ck;
++
++static int h6300_panel_init(struct omapfb_device *fbdev)
++{
++	DBGENTER(1);
++/*
++	if ((h6300_lcd_ck = clk_get (NULL, "lcd_ck")) == NULL) {
++		printk(KERN_ERR "Unable to get the clock LCD_CK!!!\n");
++		return -EPERM;
++	} clk_enable(h6300_lcd_ck);
++*/
++	DBGLEAVE(1);
++	printk(KERN_INFO "lcd_h6300.c: h6300_panel_init() done\n");
++	return 0;
++}
++
++static void h6300_panel_cleanup(void)
++{
++	DBGENTER(1);
++/*
++	if (h6300_lcd_ck) {
++		clk_disable(h6300_lcd_ck);
++		clk_put(h6300_lcd_ck);
++		h6300_lcd_ck = NULL;
++	}
++*/
++	DBGLEAVE(1);
++	printk(KERN_INFO "lcd_h6300.c: h6300_panel_cleanup() done\n");
++}
++
++static int h6300_panel_enable(void)
++{
++	DBGENTER(1);
++	DBGLEAVE(1);
++	printk(KERN_INFO "lcd_h6300.c: h6300_panel_enable() done\n");
++	return 0;
++}
++
++static void h6300_panel_disable(void)
++{
++	DBGENTER(1);
++	DBGLEAVE(1);
++	printk(KERN_INFO "lcd_h6300.c: h6300_panel_disable() done\n");	
++}
++
++static unsigned long h6300_panel_get_caps(void)
++{
++	printk(KERN_INFO "lcd_h6300.c: h6300_panel_get_caps() called\n");	
++	return 0;
++}
++
++struct lcd_panel h6300_panel = {
++	.name		= "h6300",
++	.config		= OMAP_LCDC_PANEL_TFT,
++
++	.bpp		= 16,
++	.data_lines	= 16,
++	.x_res		= 240,
++	.y_res		= 320,
++	.pixel_clock	= 21000,
++	.hsw		= 12,
++	.hfp		= 10,
++	.hbp		= 10,
++	.vsw		= 3,
++	.vfp		= 10,
++	.vbp		= 3,
++	.pcd		= 0,
++
++	.init		= h6300_panel_init,
++	.cleanup	= h6300_panel_cleanup,
++	.enable		= h6300_panel_enable,
++	.disable	= h6300_panel_disable,
++	.get_caps	= h6300_panel_get_caps,
++};
++
++static int h6300_panel_probe(struct platform_device *pdev)
++{
++	DBGENTER(1);
++	omapfb_register_panel(&h6300_panel);
++	return 0;
++}
++
++static int h6300_panel_remove(struct platform_device *pdev)
++{
++	DBGENTER(1);
++	return 0;
++}
++
++static int h6300_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
++{
++	DBGENTER(1);
++	pca9535_gpio_write(GPIO3, HI);
++	return 0;
++}
++
++static int h6300_panel_resume(struct platform_device *pdev)
++{
++	DBGENTER(1);
++	pca9535_gpio_write(GPIO3, LOW);
++	return 0;
++}
++
++struct platform_driver h6300_panel_driver = {
++	.probe		= h6300_panel_probe,
++	.remove		= h6300_panel_remove,
++	.suspend	= h6300_panel_suspend,
++	.resume		= h6300_panel_resume,
++	.driver		= {
++		.name	= "lcd_h6300",
++		.owner	= THIS_MODULE,
++	},
++};
++
++static int h6300_panel_drv_init(void)
++{
++	return platform_driver_register(&h6300_panel_driver);
++}
++
++static void h6300_panel_drv_cleanup(void)
++{
++	platform_driver_unregister(&h6300_panel_driver);
++}
++
++module_init(h6300_panel_drv_init);
++module_exit(h6300_panel_drv_cleanup);
+diff -Naur linux-2.6.16.16/drivers/video/omap/Makefile h6300_dev/drivers/video/omap/Makefile
+--- linux-2.6.16.16/drivers/video/omap/Makefile	2006-05-17 21:41:30.000000000 +0300
++++ h6300_dev/drivers/video/omap/Makefile	2006-02-21 23:54:33.000000000 +0200
+@@ -23,6 +23,7 @@
+ objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
+ objs-y$(CONFIG_MACH_OMAP_PERSEUS2) += lcd_p2.o
+ objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
++objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_H6300) += lcd_h6300.o
+ 
+ objs-y$(CONFIG_FB_OMAP_LCD_LPH8923) += lcd_lph8923.o
+ 
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/board-h6300.h h6300_dev/include/asm-arm/arch-omap/board-h6300.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/board-h6300.h	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/include/asm-arm/arch-omap/board-h6300.h	2006-04-24 20:53:29.000000000 +0300
+@@ -0,0 +1,40 @@
++/*
++ * linux/include/asm-arm/arch-omap/board-innovator.h
++ *
++ * Copyright (C) 2001 RidgeRun, 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef __ASM_ARCH_OMAP_H6300_H
++#define __ASM_ARCH_OMAP_H6300_H
++
++#ifndef OMAP_SDRAM_DEVICE
++#define OMAP_SDRAM_DEVICE				D256M_1X16_4B
++#endif
++
++#define OMAP1510P1_IMIF_PRI_VALUE		0x00
++#define OMAP1510P1_EMIFS_PRI_VALUE		0x00
++#define OMAP1510P1_EMIFF_PRI_VALUE		0x00
++
++#define NR_FPGA_IRQS					24
++#define NR_IRQS                 		IH_BOARD_BASE + NR_FPGA_IRQS
++
++#endif /* __ASM_ARCH_OMAP_H6300_H */
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/h6300_uart_info.h h6300_dev/include/asm-arm/arch-omap/h6300_uart_info.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/h6300_uart_info.h	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/include/asm-arm/arch-omap/h6300_uart_info.h	2005-10-14 18:55:31.000000000 +0300
+@@ -0,0 +1,33 @@
++/*
++ * Support file for calling h6300 uart configuration functions.
++ * Used at least by h6300_bt driver.
++ * 
++ * Copyright (c) 2005 SDG Systems, LLC
++ * 2005-03-29   Todd Blumer     Converted  basic structure to support hx4700
++ * 2005-10-03   Mika Laitio (lamikr@cc.jyu.fi)	Reorganized for the iPAQ h6300 bt driver.
++ */
++
++#ifndef _H6300_UART_INFO_H
++#define _H6300_UART_INFO_H
++
++#include "omap_serial.h"
++
++#define GPIO_BT_PWR_EN 3
++#define GPIO_N_BT_RST 9
++
++#define GPIO_I2C_GPRS_RESET 16
++#define GPIO_I2C_MIC_OP_EN 10
++#define GPIO_I2C_SPK_OP_PD 11
++
++#define GPIO_VALUE_OFF	0
++#define GPIO_VALUE_ON	1
++
++#define GPIO_DIR_OUTPUT 1
++
++struct h6300_uart_funcs {
++	void (*configure)( struct uart_omap_port *up, int state);
++	void (*set_txrx)( struct uart_omap_port *up, int txrx);
++	int (*get_txrx)( struct uart_omap_port *up);
++};
++
++#endif
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/hardware.h h6300_dev/include/asm-arm/arch-omap/hardware.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/hardware.h	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/include/asm-arm/arch-omap/hardware.h	2006-02-06 15:36:21.000000000 +0200
+@@ -290,6 +290,10 @@
+ #include "board-innovator.h"
+ #endif
+ 
++#ifdef CONFIG_MACH_OMAP_H6300
++#include "board-h6300.h"
++#endif
++
+ #ifdef CONFIG_MACH_OMAP_H2
+ #include "board-h2.h"
+ #endif
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/mux.h h6300_dev/include/asm-arm/arch-omap/mux.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/mux.h	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/include/asm-arm/arch-omap/mux.h	2006-05-18 00:38:24.000000000 +0300
+@@ -320,6 +320,13 @@
+ 	P15_1610_UWIRE_CS3,
+ 	N15_1610_UWIRE_CS1,
+ 
++	/* OMAP-1510 uWire */
++	P15_1510_UWIRE_CS3,
++	N14_1510_UWIRE_CS0,
++	V19_1510_UWIRE_SCLK,
++	W21_1510_UWIRE_SDO,
++	U18_1510_UWIRE_SDI,
++
+ 	/* OMAP-1610 Flash */
+ 	L3_1610_FLASH_CS2B_OE,
+ 	M8_1610_FLASH_CS2B_WE,
+@@ -384,6 +391,7 @@
+ 	T20_1610_LOW_PWR,
+ 
+ 	/* MCLK Settings */
++	R10_1510_MCLK_ON,
+ 	V5_1710_MCLK_ON,
+ 	V5_1710_MCLK_OFF,
+ 	R10_1610_MCLK_ON,
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/omap-alsa.h h6300_dev/include/asm-arm/arch-omap/omap-alsa.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/omap-alsa.h	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/include/asm-arm/arch-omap/omap-alsa.h	2006-03-08 13:28:16.000000000 +0200
+@@ -1,6 +1,6 @@
+ /*
+  * linux/include/asm-arm/arch-omap/omap-alsa.h
+- *
++ * 
+  * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
+  *
+  * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/omap_serial.h h6300_dev/include/asm-arm/arch-omap/omap_serial.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/omap_serial.h	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/include/asm-arm/arch-omap/omap_serial.h	2005-10-04 00:58:34.000000000 +0300
+@@ -0,0 +1,62 @@
++/*
++ * Omap/h6300 serial driver private interface. 
++ * Code originates from the pxa-serial.h available in the handheld org drivers
++ * for iPAQ PXA4700.
++ *
++ * Copyright (c) 2005 SDG Systems, LLC
++ * 2005-03-29   Todd Blumer     Converted  basic structure to support hx4700
++ * 2005-10-03   Mika Laitio (lamikr@cc.jyu.fi)	Reorganized for the iPAQ h6300 bt driver.
++ */
++ 
++#ifndef _OMAP_SERIAL_H
++#define _OMAP_SERIAL_H
++
++#define OMAP_SERIAL_TX 1
++#define OMAP_SERIAL_RX 2
++
++#include <linux/tty.h>
++#include <linux/serial_core.h>
++
++struct platform_omap_serial_funcs;
++
++struct uart_omap_port {
++	struct uart_port			port;
++	unsigned char				ier;
++	unsigned char				lcr;
++	unsigned char				mcr;
++	unsigned int    			lsr_break_flag;
++	unsigned int				cken;
++	char					*name;
++	struct platform_omap_serial_funcs	*pf;
++};
++
++/* A pointer to such a structure can be contained in the platform_data
++ * field of every PXA UART platform_device. If the field is NULL, the
++ * serial port works as usual.
++ *
++ * For the sake of simplicity/performance no one of the function pointers
++ * in the structure below can be NULL.
++ */
++struct platform_omap_serial_funcs {
++	/* Platform-specific function to initialize whatever is connected
++         to this serial port... enable=1 -> enable transceiver,
++         0 -> disable transceiver. */
++	void (*configure) (struct uart_omap_port *up, int enable);
++        /* Platform-specific function to enable or disable the individual
++           transmitter/receiver submodules. On transceivers without echo
++           cancellation (e.g. SIR) transmitter always has priority, e.g.
++           if both bits are set, only the transmitter is enabled. */
++        void (*set_txrx) (struct uart_omap_port *up, int txrx);
++	/* Get the current state of tx/rx (see bitflags above) */
++	int (*get_txrx) (struct uart_omap_port *up);
++};
++
++/*
++ * The variables below are located in arch/arm/mach-omap/board_h6300.c
++ * Machine-specific code may want to put a pointer to a static
++ * platform_pxa_serial_funcs structure in the dev.platform_data
++ * field of the respective port device.
++ */
++extern struct platform_device btuart_device;
++
++#endif
+diff -Naur linux-2.6.16.16/include/asm-arm/arch-omap/pca9535.h h6300_dev/include/asm-arm/arch-omap/pca9535.h
+--- linux-2.6.16.16/include/asm-arm/arch-omap/pca9535.h	1970-01-01 02:00:00.000000000 +0200
++++ h6300_dev/include/asm-arm/arch-omap/pca9535.h	2005-10-25 03:24:45.000000000 +0300
+@@ -0,0 +1,39 @@
++#ifndef _PCA9535_H
++#define _PCA9535_H
++
++enum  pca9535_gpios {
++	GPIO0 = 0,
++	GPIO1 = 1,
++	GPIO2 = 2,
++	GPIO3 = 3,
++	GPIO4 = 4,
++	GPIO5 = 5,
++	GPIO6 = 6,
++	GPIO7 = 7,
++	GPIO8 = 8,
++	GPIO9 = 9,
++	GPIO10 = 10,
++	GPIO11 = 11,
++	GPIO12 = 12,
++	GPIO13 = 13,
++	GPIO14 = 14,
++	GPIO15 = 15,
++	GPIO16 = 16,
++	GPIO17 = 17
++};
++
++enum gpio_values {
++	HI	= 0,
++	LOW	= 1
++};
++
++enum gpio_direction {
++	GPIO_INPUT	= 0,
++	GPIO_OUTPUT	= 1
++};
++
++extern int pca9535_gpio_read(int gpio);
++extern int pca9535_gpio_write(int gpio, unsigned char val);	
++extern int pca9535_gpio_direction(int gpio, unsigned char direction);
++
++#endif
+diff -Naur linux-2.6.16.16/Makefile h6300_dev/Makefile
+--- linux-2.6.16.16/Makefile	2006-05-17 21:41:27.000000000 +0300
++++ h6300_dev/Makefile	2006-05-18 01:45:17.000000000 +0300
+@@ -11,7 +11,7 @@
+ # expect to learn how to build the kernel reading this file.
+ 
+ # Add custom flags here to avoid conflict with updates
+-EXTRAVERSION := $(EXTRAVERSION)-omap2
++EXTRAVERSION := $(EXTRAVERSION)-omap1-h6300
+ 
+ # Do not print "Entering directory ..."
+ MAKEFLAGS += --no-print-directory
+diff -Naur linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101.c h6300_dev/sound/arm/omap/omap-alsa-tsc2101.c
+--- linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101.c	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/sound/arm/omap/omap-alsa-tsc2101.c	2006-03-30 23:15:31.000000000 +0300
+@@ -96,7 +96,11 @@
+ static snd_pcm_hardware_t tsc2101_snd_omap_alsa_playback = {
+ 	.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ 		 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),	
+-	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
++#ifdef CONFIG_MACH_OMAP_H6300
++	.formats = (SNDRV_PCM_FMTBIT_S8),
++#else
++ 	.formats = (SNDRV_PCM_FMTBIT_S16_LE),
++#endif
+ 	.rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
+ 		  SNDRV_PCM_RATE_16000 |
+ 		  SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
+@@ -136,7 +140,7 @@
+ };
+ 
+ /* 
+- * Simplified write for tsc Audio
++ * Simplified write for tsc2101 audio registers.
+  */
+ inline void tsc2101_audio_write(u8 address, u16 data)
+ {
+@@ -144,7 +148,7 @@
+ }
+ 
+ /* 
+- * Simplified read for tsc  Audio
++ * Simplified read for tsc2101 audio registers.
+  */
+ inline u16 tsc2101_audio_read(u8 address)
+ {
+@@ -246,14 +250,17 @@
+ #endif				/* #ifdef TSC_MASTER */
+ 	tsc2101_audio_write(TSC2101_AUDIO_CTRL_3, data);
+ 
+-	/* program the PLLs */
++	/* Program the PLLs. This code assumes that the 12 Mhz MCLK is in use.
++         * If MCLK rate is something else, these values must be changed.
++	 * See the tsc2101 specification for the details.
++	 */
+ 	if (rate_reg_info[count].fs_44kHz) {
+-		/* 44.1 khz - 12 MHz Mclk */
++		/* samplerate = (44.1kHZ / x), where x is int. */
+ 		tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
+ 				PLL1_PVAL(1) | PLL1_I_VAL(7));	/* PVAL 1; I_VAL 7 */
+ 		tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x1490));	/* D_VAL 5264 */
+ 	} else {
+-		/* 48 khz - 12 Mhz Mclk */
++		/* samplerate = (48.kHZ / x), where x is int. */
+ 		tsc2101_audio_write(TSC2101_PLL_PROG_1, PLL1_PLLSEL |
+ 			       PLL1_PVAL(1) | PLL1_I_VAL(8));	/* PVAL 1; I_VAL 8 */
+ 		tsc2101_audio_write(TSC2101_PLL_PROG_2, PLL2_D_VAL(0x780));	/* D_VAL 1920 */
+@@ -317,21 +324,14 @@
+ 		       CODEC_CLOCK);
+ 	}
+ 	curRate	= (uint)clk_get_rate(tsc2101_mclk);
+-	DPRINTK("old clock rate = %d\n", curRate);
+ 	if (curRate != CODEC_CLOCK) {
+ 		err	= clk_set_rate(tsc2101_mclk, CODEC_CLOCK);
+ 		if (err) {
+ 			printk(KERN_WARNING
+ 			       "Cannot set MCLK clock rate for TSC2101 CODEC, error code = %d\n", err);
+-			//return -ECANCELED;
++			return -ECANCELED;
+ 		}
+ 	}
+-	else
+-	{
+-		printk(KERN_INFO
+-		       "omap_alsa_tsc2101_clock_on(), no need to change rate, no need to change clock rate, rate already %d Hz.\n",
+-		       CODEC_CLOCK);
+-	}
+ 	err		= clk_enable(tsc2101_mclk);
+ 	curRate		= (uint)clk_get_rate(tsc2101_mclk);
+ 	curUseCount	= clk_get_usecount(tsc2101_mclk);
+@@ -349,8 +349,7 @@
+ }
+ 
+ /*
+- * Do some sanity check, turn clock off and then turn
+- *  codec audio off
++ * Do some sanity check, turn clock off and then turn codec audio off
+  */
+ int tsc2101_clock_off(void) 
+ {
+@@ -374,10 +373,6 @@
+ 	tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
+ 			    ~(CPC_SP1PWDN | CPC_SP2PWDN | CPC_BASSBC));
+ 	DPRINTK("audio codec off\n");
+-#ifdef DUMP_TSC2101_AUDIO_REGISTERS
+-	printk("tsc2101_clock_off()\n");
+-	dump_tsc2101_audio_reg();
+-#endif	
+ 	return 0;	
+ }
+ 
+@@ -420,18 +415,22 @@
+ };
+ 
+ static int __init omap_alsa_tsc2101_init(void)
+-{
+-	int err;
+-	
++{	
+ 	ADEBUG();
+-	err = platform_driver_register(&omap_alsa_driver);
+-
+-	return err;
++#ifdef DUMP_TSC2101_AUDIO_REGISTERS
++	printk("omap_alsa_tsc2101_init()\n");
++	dump_tsc2101_audio_reg();
++#endif
++	return platform_driver_register(&omap_alsa_driver);
+ }
+ 
+ static void __exit omap_alsa_tsc2101_exit(void)
+ {
+ 	ADEBUG();
++#ifdef DUMP_TSC2101_AUDIO_REGISTERS
++	printk("omap_alsa_tsc2101_exit()\n");
++	dump_tsc2101_audio_reg();
++#endif
+ 	platform_driver_unregister(&omap_alsa_driver);
+ }
+ 
+diff -Naur linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.c h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.c
+--- linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.c	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.c	2006-05-10 02:42:13.000000000 +0300
+@@ -50,47 +50,53 @@
+ //#define M_DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
+ #define M_DPRINTK(ARGS...)  		/* nop */
+ 
++#define CHECK_BIT(INDX, ARG) (((ARG) & TSC2101_BIT(INDX)) >> INDX)
++#define IS_UNMUTED(INDX, ARG) (((CHECK_BIT(INDX, ARG)) == 0))
++
+ #define DGC_DALVL_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
+ #define DGC_DARVL_EXTRACT(ARG) ((ARG & 0x007f))
+-#define GET_DGC_DALMU_BIT_VALUE(ARG)  (((ARG) & TSC2101_BIT(15)) >> 15)
+-#define GET_DGC_DARMU_BIT_VALUE(ARG)  (((ARG) & TSC2101_BIT(7)) >> 7)
+-#define IS_DGC_DALMU_UNMUTED(ARG)  (((GET_DGC_DALMU_BIT_VALUE(ARG)) == 0))
+-#define IS_DGC_DARMU_UNMUTED(ARG) (((GET_DGC_DARMU_BIT_VALUE(ARG)) == 0))
+ 
+ #define HGC_ADPGA_HED_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
+-#define GET_DGC_HGCMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15)
+-#define IS_DGC_HGCMU_UNMUTED(ARG) (((GET_DGC_HGCMU_BIT_VALUE(ARG)) == 0))
+-
+ #define HNGC_ADPGA_HND_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
+-#define GET_DGC_HNGCMU_BIT_VALUE(ARG) (((ARG) & TSC2101_BIT(15)) >> 15)
+-#define IS_DGC_HNGCMU_UNMUTED(ARG) (((GET_DGC_HNGCMU_BIT_VALUE(ARG)) == 0))
++#define BGC_ADPGA_BGC_EXTRACT(ARG) ((ARG & 0x7f00) >> 8)
+ 
+ static int current_playback_target	= PLAYBACK_TARGET_LOUDSPEAKER;
+ static int current_rec_src 		= REC_SRC_SINGLE_ENDED_MICIN_HED;
+ 
++/* 
++ * Simplified write for the tsc2101 audio registers.
++ */
++inline void omap_tsc2101_audio_write(u8 address, u16 data)
++{
++	omap_tsc2101_write(PAGE2_AUDIO_CODEC_REGISTERS, address, data);
++}
++
++/* 
++ * Simplified read for the tsc2101 audio registers.
++ */
++inline u16 omap_tsc2101_audio_read(u8 address)
++{
++	return (omap_tsc2101_read(PAGE2_AUDIO_CODEC_REGISTERS, address));
++}
++
+ /*
+- * Used for switching between TSC2101 recourd sources.
+- * Logic is adjusted from the TSC2101 OSS code.
++ * For selecting tsc2101 recourd source.
+  */
+-static int set_record_source(int val)
++static void set_record_source(int val)
+ {
+ 	u16	data;
+-	int	maskedVal;
+ 	
+-	FN_IN;
+-	maskedVal	= 0xe0 & val;	
+-
+-	data	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_MIXER_PGA_CTRL);
++	/* Mute Analog Sidetone
++	 * Analog sidetone gain db?
++	 * Input selected by MICSEL connected to ADC
++	 */
++	data	= MPC_ASTMU | MPC_ASTG(0x45);
+ 	data	&= ~MPC_MICSEL(7); /* clear all MICSEL bits */
+-	data	|= maskedVal;
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-				TSC2101_MIXER_PGA_CTRL,
+-				data);
++	data	|= MPC_MICSEL(val);
++	data	|= MPC_MICADC;
++	omap_tsc2101_audio_write(TSC2101_MIXER_PGA_CTRL, data);
++	
+ 	current_rec_src	= val;
+-
+-	FN_OUT(0);
+-	return 0;
+ }
+ 
+ /*
+@@ -147,32 +153,34 @@
+ 	volL	= get_mixer_volume_as_dac_gain_control_volume(mixerVolL);
+ 	volR	= get_mixer_volume_as_dac_gain_control_volume(mixerVolR);
+ 	
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
+ 	/* keep the old mute bit settings */
+ 	val	&= ~(DGC_DALVL(OUTPUT_VOLUME_MIN) | DGC_DARVL(OUTPUT_VOLUME_MIN));
+ 	val	|= DGC_DALVL(volL) | DGC_DARVL(volR);
+ 	retVal	= 2;
+ 	if (retVal) {
+-		omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_DAC_GAIN_CTRL, 
+-				val);
++		omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
+ 	}
+ 	M_DPRINTK("to registry: left = %d, right = %d, total = %d\n", DGC_DALVL_EXTRACT(val), DGC_DARVL_EXTRACT(val), val);
+ 	return retVal;
+ }
+ 
+-int dac_gain_control_unmute_control(int muteLeft, int muteRight)
++/**
++ * If unmuteLeft/unmuteRight == 0  --> mute
++ * If unmuteLeft/unmuteRight == 1 --> unmute
++ */
++int dac_gain_control_unmute(int unmuteLeft, int unmuteRight)
+ {
+ 	u16 val;
+ 	int count;
+ 
+ 	count	= 0;
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
+ 	/* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
+ 	 * so if values are same, it's time to change the registry value.
+ 	 */
+-	if (muteLeft == GET_DGC_DALMU_BIT_VALUE(val)) {
+-		if (muteLeft == 0) {
++	if (unmuteLeft != IS_UNMUTED(15, val)) {
++		if (unmuteLeft == 0) {
+ 			/* mute --> turn bit on */
+ 			val	= val | DGC_DALMU;
+ 		}
+@@ -182,8 +190,8 @@
+ 		}
+ 		count++;
+ 	} /* L */
+-	if (muteRight == GET_DGC_DARMU_BIT_VALUE(val)) {
+-		if (muteRight == 0) {
++	if (unmuteRight != IS_UNMUTED(7, val)) {
++		if (unmuteRight == 0) {
+ 			/* mute --> turn bit on */
+ 			val	= val | DGC_DARMU;
+ 		}
+@@ -194,14 +202,47 @@
+ 		count++;
+ 	} /* R */
+ 	if (count) {
+-		omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL, val);
++		omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);
+ 		M_DPRINTK("changed value, is_unmuted left = %d, right = %d\n", 
+-			IS_DGC_DALMU_UNMUTED(val),
+-			IS_DGC_DARMU_UNMUTED(val));
++			IS_UNMUTED(15, val),
++			IS_UNMUTED(7, val));
+ 	}
+ 	return count;	
+ }
+ 
++/**
++ * unmute: 0 --> mute, 1 --> unmute
++ * page2RegIndx: Registry index in tsc2101 page2.
++ * muteBitIndx: Index number for the bit in registry that indicates whether muted or unmuted.
++ */
++int adc_pga_unmute_control(int unmute, int page2regIndx, int muteBitIndx)
++{
++	int count;
++	u16 val;
++	
++	count	= 0;
++	val 	= omap_tsc2101_audio_read(page2regIndx);
++	/* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
++	 * so if the values are same, it's time to change the registry value...
++	 */
++	if (unmute != IS_UNMUTED(muteBitIndx, val)) {
++		if (unmute == 0) {
++			/* mute --> turn bit on */
++			val	= val | TSC2101_BIT(muteBitIndx);
++		}
++		else {
++			/* unmute --> turn bit off */
++			val	= val & ~TSC2101_BIT(muteBitIndx);
++		}
++		M_DPRINTK("changed value, is_unmuted = %d\n", IS_UNMUTED(muteBitIndx, val));
++		count++;
++	}
++	if (count) {
++		omap_tsc2101_audio_write(page2regIndx, val);
++	}
++	return count;
++}
++
+ /*
+  * Converts the DGC registry value read from the TSC2101 registry to 
+  * Alsa mixer volume format (0 - 100).
+@@ -271,14 +312,11 @@
+ 	/* Convert 0 -> 100 volume to 0x0(min) -> 0x7D(max) volume range */
+ 	/* NOTE: 0 is minimum volume and not mute */
+ 	volume	= get_mixer_volume_as_headset_gain_control_volume(mixerVol);	
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HEADSET_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
+ 	/* preserve the old mute settings */
+ 	val	&= ~(HGC_ADPGA_HED(INPUT_VOLUME_MAX));
+ 	val	|= HGC_ADPGA_HED(volume);
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-			TSC2101_HEADSET_GAIN_CTRL,
+-			val);	
++	omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);	
+ 	retVal	= 1;
+ 	
+ 	M_DPRINTK("to registry = %d\n", val);	
+@@ -305,71 +343,37 @@
+ 	 * NOTE: 0 is minimum volume and not mute 
+ 	 */
+ 	volume	= get_mixer_volume_as_headset_gain_control_volume(mixerVol);
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
+ 	/* preserve the old mute settigns */
+ 	val	&= ~(HNGC_ADPGA_HND(INPUT_VOLUME_MAX));
+ 	val	|= HNGC_ADPGA_HND(volume);
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-			TSC2101_HANDSET_GAIN_CTRL,
+-			val);
++	omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
+ 	retVal	= 1;
+ 	
+ 	M_DPRINTK("to registry = %d\n", val);	
+ 	return retVal;
+ }
+ 
+-void init_record_sources(void)
+-{
+-	/* Mute Analog Sidetone
+-	 * analog sidetone gain db?
+-	 * Cell Phone In not connected to ADC
+-	 * Input selected by MICSEL connected to ADC
+-	 */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-			  TSC2101_MIXER_PGA_CTRL,
+-			  MPC_ASTMU | MPC_ASTG(0x40) | ~MPC_CPADC | MPC_MICADC);
+-	/* Set record source, Select MIC_INHED input for headset */
+-	set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);	
+-}
+-
+ void set_loudspeaker_to_playback_target(void)
+ {
+-	u16	val;
+-
+-	/* power down sp1, sp2 and loudspeaker */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_CODEC_POWER_CTRL,
++	/* power down SPK1, SPK2 and loudspeaker */
++	omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
+ 			CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);	
+ 	/* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
+ 	 * 1dB AGC hysteresis
+ 	 * MICes bias 2V
+ 	 */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-			TSC2101_AUDIO_CTRL_4, 
+-			AC4_MB_HED(0));
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
+ 
+ 	/* DAC left and right routed to SPK1/SPK2
+ 	 * SPK1/SPK2 unmuted
+-	 * keyclicks routed to SPK1/SPK2
+-	 */
+-	val	= AC5_DIFFIN |
++	 * Keyclicks routed to SPK1/SPK2 */
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5, 
++			AC5_DIFFIN |
+ 			AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
+-			AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
+-			AC5_HDSCPTC;
+-	val	= val & ~AC5_HDSCPTC;
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_AUDIO_CTRL_5,
+-			val);
+-	
+-	/* powerdown spk1/out32n and spk2 */
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-				TSC2101_POWERDOWN_STS);
+-	val	= val & ~(~PS_SPK1FL | ~PS_HNDFL | PS_LSPKFL);
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_POWERDOWN_STS,
+-			val);
+-
+-	/* routing selected to SPK1 goes to OUT8P/OUT84 alsa. (loudspeaker)
++			AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2);
++	
++	/* routing selected to SPK1 goes also to OUT8P/OUT8N. (loudspeaker)
+ 	 * analog sidetone routed to loudspeaker
+ 	 * buzzer pga routed to loudspeaker
+ 	 * keyclick routing to loudspeaker
+@@ -381,43 +385,242 @@
+ 	 * Enable loudspeaker short protection control (0 = enable protection)
+ 	 * VGND short protection control (0 = enable protection)
+ 	 */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_AUDIO_CTRL_6,
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
+ 			AC6_SPL2LSK | AC6_AST2LSK | AC6_BUZ2LSK | AC6_KCL2LSK |
+-			AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO |
+-			~AC6_MUTLSPK | ~AC6_MUTSPK2 | ~AC6_LDSCPTC | ~AC6_VGNDSCPTC);
++			AC6_CPI2LSK | AC6_MIC2CPO | AC6_SPL2CPO);
+ 	current_playback_target	= PLAYBACK_TARGET_LOUDSPEAKER;
+ }
+ 
+ void set_headphone_to_playback_target(void)
+ {
+-	/* power down sp1, sp2 and loudspeaker */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_CODEC_POWER_CTRL,
++	/* power down SPK1, SPK2 and loudspeaker */
++	omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
+ 			CPC_SP1PWDN | CPC_SP2PWDN | CPC_LDAPWDF);
+ 	/* ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled */
+ 	/* 1dB AGC hysteresis */
+ 	/* MICes bias 2V */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-				TSC2101_AUDIO_CTRL_4, 
+-				AC4_MB_HED(0));
+-
+-	/* DAC left and right routed to SPK2 */
+-	/* SPK1/2 unmuted */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_AUDIO_CTRL_5,
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, AC4_MB_HED(0));
++				
++	/* DAC left and right routed to SPK1/SPK2
++	 * SPK1/SPK2 unmuted
++	 * Keyclicks routed to SPK1/SPK2 */
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
+ 			AC5_DAC2SPK1(3) | AC5_AST2SPK1 | AC5_KCL2SPK1 |
+ 			AC5_DAC2SPK2(3) | AC5_AST2SPK2 | AC5_KCL2SPK2 |
+ 			AC5_HDSCPTC);
+-
+-	/* OUT8P/N muted, CPOUT muted */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_AUDIO_CTRL_6,
++			
++	/* OUT8P/OUT8N muted, CPOUT muted */
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
+ 			AC6_MUTLSPK | AC6_MUTSPK2 | AC6_LDSCPTC |
+ 			AC6_VGNDSCPTC);
+ 	current_playback_target	= PLAYBACK_TARGET_HEADPHONE;
+ }
+ 
++void set_telephone_to_playback_target(void)
++{
++	/* 
++	 * 0110 1101 0101 1100
++	 * power down MICBIAS_HED, Analog sidetone, SPK2, DAC, 
++	 * Driver virtual ground, loudspeaker. Values D2-d5 are flags.
++	 */	 
++	omap_tsc2101_audio_write(TSC2101_CODEC_POWER_CTRL,
++			CPC_MBIAS_HED | CPC_ASTPWD | CPC_SP2PWDN | CPC_DAPWDN |
++			CPC_VGPWDN | CPC_LSPWDN);
++			
++	/* 
++	 * 0010 1010 0100 0000
++	 * ADC, DAC, Analog Sidetone, cellphone, buzzer softstepping enabled
++	 * 1dB AGC hysteresis
++	 * MICes bias 2V
++	 */
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4,
++			AC4_MB_HND | AC4_MB_HED(0) | AC4_AGCHYS(1) | 
++			AC4_BISTPD | AC4_ASSTPD | AC4_DASTPD);
++	printk("set_telephone_to_playback_target(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
++			
++	/* 
++	 * 1110 0010 0000 0010
++	 * DAC left and right routed to SPK1/SPK2
++	 * SPK1/SPK2 unmuted
++	 * keyclicks routed to SPK1/SPK2
++	 */	 
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_5,
++			AC5_DIFFIN | AC5_DAC2SPK1(3) | 
++		  	AC5_CPI2SPK1 | AC5_MUTSPK2);
++	
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_6,
++			AC6_MIC2CPO | AC6_MUTLSPK | 
++			AC6_LDSCPTC | AC6_VGNDSCPTC | AC6_CAPINTF);
++	current_playback_target	= PLAYBACK_TARGET_CELLPHONE;
++}
++
++/*
++ * 1100 0101 1101 0000
++ * 
++ * #define MPC_ASTMU           TSC2101_BIT(15)
++ * #define MPC_ASTG(ARG)       (((ARG) & 0x7F) << 8)
++ * #define MPC_MICSEL(ARG)     (((ARG) & 0x07) << 5)
++ * #define MPC_MICADC          TSC2101_BIT(4)
++ * #define MPC_CPADC           TSC2101_BIT(3)
++ * #define MPC_ASTGF           (0x01)
++ */
++static void set_telephone_to_record_source(void)
++{
++	u16	val;
++	
++	/* 
++	 * D0       = 0: 
++	 * 		--> AGC is off for handset input.
++	 *		--> ADC PGA is controlled by the ADMUT_HDN + ADPGA_HND
++	 *          (D15, D14-D8)
++	 * D4 - D1  = 0000 
++	 * 		--> AGC time constant for handset input, 
++	 * 		attack time = 8 mc, decay time = 100 ms
++	 * D7 - D5  = 000
++	 * 		--> AGC Target gain for handset input = -5.5 db
++	 * D14 - D8 = 011 1100
++	 * 		--> ADC handset PGA settings = 60 = 30 db
++	 * D15 		= 0
++	 * 		--> Handset input ON (unmuted)
++	 */
++	val	= 0x3c00;	// 0011 1100 0000 0000 = 60 = 30
++	omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);
++	
++	/*
++	 * D0		= 0
++	 * 		--> AGC is off for headset/Aux input
++	 * 		--> ADC headset/Aux PGA is contoller by ADMUT_HED + ADPGA_HED
++	 *          (D15, D14-D8)
++	 * D4 - D1	= 0000 
++	 * 		--> Agc constant for headset/Aux input,
++	 *      	attack time = 8 mc, decay time = 100 ms      
++	 * D7 - D5	= 000
++	 * 		--> AGC target gain for headset input = -5.5 db
++	 * D14 - D8 = 000 0000
++	 * 		--> Adc headset/AUX pga settings = 0 db
++	 * D15		= 1
++	 * 		--> Headset/AUX input muted
++	 * 
++	 * Mute headset aux input
++	 */
++	val	= 0x8000;	// 1000 0000 0000 0000
++	omap_tsc2101_audio_write(TSC2101_HEADSET_GAIN_CTRL, val);
++	set_record_source(REC_SRC_MICIN_HND_AND_AUX1);
++
++	// hacks start
++	/* D0		= flag, Headset/Aux or handset PGA flag
++	 * 		--> & with 1 (= 1 -->gain applied == pga register settings)
++	 * D1		= 0, DAC channel PGA soft stepping control
++	 * 		--> 0.5 db change every WCLK
++	 * D2		= flag, DAC right channel PGA flag
++	 * 		--> & with 1
++	 * D3		= flag, DAC left channel PGA flag
++	 * 		-- > & with 1
++	 * D7 - D4	= 0001, keyclick length
++	 * 		--> 4 periods key clicks
++	 * D10 - D8 = 100, keyclick frequenzy
++	 * 		--> 1 kHz, 
++	 * D11		= 0, Headset/Aux or handset soft stepping control
++	 * 		--> 0,5 db change every WCLK or ADWS
++	 * D14 -D12 = 100, Keyclick applitude control
++	 * 		--> Medium amplitude
++	 * D15		= 0, keyclick disabled
++	 */
++	val	= omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_2);
++	val	= val & 0x441d;
++	val	= val | 0x4410;	// D14, D10, D4 bits == 1
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_2, val);
++
++	/*
++	 * D0		= 0	(reserved, write always 0)
++	 * D1		= flag,
++	 * 			--> & with 1
++	 * D2 - D5	= 0000 (reserved, write always 0000)
++	 * D6		= 1
++	 * 			--> MICBIAS_HND = 2.0 v
++	 * D8 - D7	= 00
++	 * 			--> MICBIAS_HED = 3.3 v
++	 * D10 - D9	= 01, 
++	 * 			--> Mic AGC hysteric selection = 2 db
++	 * D11		= 1, 
++	 * 			--> Disable buzzer PGA soft stepping
++	 * D12		= 0,
++	 * 			--> Enable CELL phone PGA soft stepping control
++	 * D13		= 1
++	 * 			--> Disable analog sidetone soft stepping control
++	 * D14		= 0
++	 * 			--> Enable DAC PGA soft stepping control
++	 * D15		= 0,
++	 * 			--> Enable headset/Aux or Handset soft stepping control
++	 */
++	val	= omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4);
++	val	= val & 0x2a42;	// 0010 1010 0100 0010
++	val	= val | 0x2a40;	// bits D13, D11, D9, D6 == 1
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_4, val);
++	printk("set_telephone_to_record_source(), TSC2101_AUDIO_CTRL_4 = %d\n", omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_4));
++	/*
++	 * D0		= 0
++	 * 		--> reserved, write always = 0
++	 * D1		= flag, read only
++	 * 		--> & with 1
++	 * D5 - D2	= 1111, Buzzer input PGA settings
++	 * 		--> 0 db
++	 * D6		= 1,
++	 * 		--> power down buzzer input pga
++	 * D7		= flag, read only
++	 * 		--> & with 1
++	 * D14 - D8	= 101 1101
++	 * 		--> 12 DB
++	 * D15		= 0
++	 * 		--> power up cell phone input PGA
++	 */
++	val	= omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
++	val	= val & 0x5dfe;
++	val	= val | 0x5dfe;	// bits, D14, D12, D11, D10, D8, D6, D5,D4,D3,D2
++	omap_tsc2101_audio_write(TSC2101_BUZZER_GAIN_CTRL, val);
++	
++	/* D6 - D0	= 000 1001
++	 * 		--> -4.5 db for DAC right channel volume control
++	 * D7		= 1
++	 * 		-->  DAC right channel muted
++	 * D14 - D8 = 000 1001
++	 * 		--> -4.5 db for DAC left channel volume control
++	 * D15 		= 1
++	 * 		--> DAC left channel muted
++	 */
++	//val	= omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
++	val	= 0x8989;
++	omap_tsc2101_audio_write(TSC2101_DAC_GAIN_CTRL, val);	
++	
++	/*  0000 0000 0100 0000
++	 * 
++	 * D1 - D0	= 0
++	 * 		--> GPIO 1 pin output is three stated
++	 * D2		= 0
++	 * 		--> Disaple GPIO2 for CLKOUT mode
++	 * D3		= 0
++	 * 		--> Disable GPUI1 for interrupt detection
++	 * D4		= 0
++	 * 		--> Disable GPIO2 for headset detection interrupt
++	 * D5		= reserved, always 0
++	 * D7 - D6	= 01
++	 * 		--> 8 ms clitch detection
++	 * D8		= reserved, write only 0
++	 * D10 -D9	= 00
++	 * 		--> 16 ms de bouncing programmatitily 
++	 *          for glitch detection during headset detection
++	 * D11		= flag for button press
++	 * D12		= flag for headset detection
++	 * D14-D13	= 00
++	 * 		--> type of headset detected = 00 == no stereo headset deected
++	 * D15		= 0
++	 * 		--> Disable headset detection
++	 * 
++	 * */
++	val	= 0x40;
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, val);	
++}
++
+ /*
+  * Checks whether the headset is detected.
+  * If headset is detected, the type is returned. Type can be
+@@ -433,8 +636,7 @@
+ 	u16	curVal;
+ 	
+ 	curType	= 0;	/* not detected */
+-	curVal	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-					TSC2101_AUDIO_CTRL_7);
++	curVal	= omap_tsc2101_audio_read(TSC2101_AUDIO_CTRL_7);
+ 	curDetected	= curVal & AC7_HDDETFL;
+ 	if (curDetected) {
+ 		printk("headset detected, checking type from %d \n", curVal);
+@@ -461,13 +663,10 @@
+ 	 * AGC enable for handset input
+ 	 * Handset input not muted
+ 	 */
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HANDSET_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
+ 	val	= val | HNGC_AGCEN_HND;	
+ 	val	= val & ~HNGC_ADMUT_HND;
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-			TSC2101_HANDSET_GAIN_CTRL,
+-			val);	
++	omap_tsc2101_audio_write(TSC2101_HANDSET_GAIN_CTRL, val);	
+ 			
+ 	/* mic input volume control
+ 	 * SET_MIC in the OSS driver 
+@@ -479,7 +678,7 @@
+ 	 */
+ 	set_mixer_volume_as_dac_gain_control_volume(DEFAULT_OUTPUT_VOLUME, DEFAULT_OUTPUT_VOLUME);	
+ 	/* unmute */
+-	dac_gain_control_unmute_control(1, 1);
++	dac_gain_control_unmute(1, 1);
+ }
+ 
+ /*
+@@ -490,11 +689,11 @@
+ 	FN_IN;
+ 	
+ 	/* Headset/Hook switch detect enabled */
+-	omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2,
+-			TSC2101_AUDIO_CTRL_7,
+-			AC7_DETECT);
++	omap_tsc2101_audio_write(TSC2101_AUDIO_CTRL_7, AC7_DETECT);
+ 
+-	init_record_sources();
++	/* Select headset to record source (MIC_INHED)*/
++	set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
++	/* Init loudspeaker as a default playback target*/
+ 	init_playback_targets();
+ 
+ 	FN_OUT(0);
+@@ -503,7 +702,7 @@
+ static int __pcm_playback_target_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
+ {
+ 	static char *texts[PLAYBACK_TARGET_COUNT] = {
+-        	"Loudspeaker", "Headphone"
++        	"Loudspeaker", "Headphone", "Cellphone"
+ 	};
+ 
+ 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+@@ -533,12 +732,18 @@
+ 	if ((curVal >= 0) &&
+ 	    (curVal < PLAYBACK_TARGET_COUNT) &&
+ 	    (curVal != current_playback_target)) {		
+-		if (curVal == 0) {
+-			set_loudspeaker_to_playback_target();		
++		if (curVal == PLAYBACK_TARGET_LOUDSPEAKER) {
++			set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HED);
++			set_loudspeaker_to_playback_target();
+ 		}
+-		else {
++		else if (curVal == PLAYBACK_TARGET_HEADPHONE) {
++			set_record_source(REC_SRC_SINGLE_ENDED_MICIN_HND);
+ 			set_headphone_to_playback_target();
+ 		}
++		else if (curVal == PLAYBACK_TARGET_CELLPHONE) {
++			set_telephone_to_record_source();
++			set_telephone_to_playback_target();
++		}
+ 		retVal	= 1;
+ 	}
+ 	return retVal;
+@@ -563,7 +768,7 @@
+ 	u16 volR;	
+ 	u16 val;
+ 	
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
+ 	M_DPRINTK("registry value = %d!\n", val);
+ 	volL	= DGC_DALVL_EXTRACT(val);
+ 	volR	= DGC_DARVL_EXTRACT(val);
+@@ -603,16 +808,16 @@
+  */
+ static int __pcm_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+ {
+-	u16 val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_DAC_GAIN_CTRL);
++	u16 val	= omap_tsc2101_audio_read(TSC2101_DAC_GAIN_CTRL);
+ 	
+-	ucontrol->value.integer.value[0]	= IS_DGC_DALMU_UNMUTED(val);
+-	ucontrol->value.integer.value[1]	= IS_DGC_DARMU_UNMUTED(val);
++	ucontrol->value.integer.value[0]	= IS_UNMUTED(15, val);	// left
++	ucontrol->value.integer.value[1]	= IS_UNMUTED(7, val);	// right
+ 	return 0;
+ }
+ 
+ static int __pcm_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+ {
+-	return dac_gain_control_unmute_control(ucontrol->value.integer.value[0], 
++	return dac_gain_control_unmute(ucontrol->value.integer.value[0], 
+ 					ucontrol->value.integer.value[1]);
+ }
+ 
+@@ -630,8 +835,7 @@
+ 	u16 val;
+ 	u16 vol;
+ 	
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HEADSET_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
+ 	M_DPRINTK("registry value = %d\n", val);
+ 	vol	= HGC_ADPGA_HED_EXTRACT(val);
+ 	vol	= vol & ~HGC_ADMUT_HED;
+@@ -662,38 +866,17 @@
+  */
+ static int __headset_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+ {
+-	u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HEADSET_GAIN_CTRL);
+-	ucontrol->value.integer.value[0]	= IS_DGC_HGCMU_UNMUTED(val);
++	u16 val = omap_tsc2101_audio_read(TSC2101_HEADSET_GAIN_CTRL);
++	ucontrol->value.integer.value[0]	= IS_UNMUTED(15, val);
+ 	return 0;
+ }
+ 
+ static int __headset_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+ {
+-	int count = 0;
+-	u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HEADSET_GAIN_CTRL);
+-	/* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
+-	 * so if values are same, it's time to change the registry value...
+-	 */
+-	if (ucontrol->value.integer.value[0] == GET_DGC_HGCMU_BIT_VALUE(val)) {
+-		if (ucontrol->value.integer.value[0] == 0) {
+-			/* mute --> turn bit on */
+-			val	= val | HGC_ADMUT_HED;
+-		}
+-		else {
+-			/* unmute --> turn bit off */
+-			val	= val & ~HGC_ADMUT_HED;
+-		}
+-		count++;
+-		M_DPRINTK("changed value, is_unmuted = %d\n", IS_DGC_HGCMU_UNMUTED(val));
+-	}
+-	if (count) {
+-		omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HEADSET_GAIN_CTRL, 
+-				val);
+-	}
+-	return count;
++	// mute/unmute headset
++	return adc_pga_unmute_control(ucontrol->value.integer.value[0],
++				TSC2101_HEADSET_GAIN_CTRL,
++				15);
+ }
+ 
+ static int __handset_playback_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
+@@ -710,7 +893,7 @@
+ 	u16 val;
+ 	u16 vol;
+ 	
+-	val	= omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
++	val	= omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
+ 	M_DPRINTK("registry value = %d\n", val);
+ 	vol	= HNGC_ADPGA_HND_EXTRACT(val);
+ 	vol	= vol & ~HNGC_ADMUT_HND;
+@@ -740,42 +923,74 @@
+  */
+ static int __handset_playback_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+ {
+-	u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
+-	ucontrol->value.integer.value[0]	= IS_DGC_HNGCMU_UNMUTED(val);
++	u16 val = omap_tsc2101_audio_read(TSC2101_HANDSET_GAIN_CTRL);
++	ucontrol->value.integer.value[0]	= IS_UNMUTED(15, val);
+ 	return 0;
+ }
+ 
+ static int __handset_playback_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
+ {
+-	int count = 0;
+-	u16 val = omap_tsc2101_read(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, TSC2101_HANDSET_GAIN_CTRL);
+-	
+-	/* in alsa mixer 1 --> on, 0 == off. In tsc2101 registry 1 --> off, 0 --> on
+-	 * so if values are same, it's time to change the registry value...
+-	 */
+-	if (ucontrol->value.integer.value[0] == GET_DGC_HNGCMU_BIT_VALUE(val)) {
+-		if (ucontrol->value.integer.value[0] == 0) {
+-			/* mute --> turn bit on */
+-			val	= val | HNGC_ADMUT_HND;
+-		}
+-		else {
+-			/* unmute --> turn bit off */
+-			val	= val & ~HNGC_ADMUT_HND;
+-		}
+-		M_DPRINTK("changed value, is_unmuted = %d\n", IS_DGC_HNGCMU_UNMUTED(val));
+-		count++;
+-	}
+-	if (count) {
+-		omap_tsc2101_write(TSC2101_AUDIO_CODEC_REGISTERS_PAGE2, 
+-				TSC2101_HANDSET_GAIN_CTRL, 
+-				val);
+-	}
+-	return count;
++	// handset mute/unmute
++	return adc_pga_unmute_control(ucontrol->value.integer.value[0],
++				TSC2101_HANDSET_GAIN_CTRL,
++				15);
++}
++
++static int __cellphone_input_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
++{
++	uinfo->type 			= SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count			= 1;
++	uinfo->value.integer.min	= 0;
++	uinfo->value.integer.max	= 1;
++	return 0;
++}
++
++/* When BGC_MUT_CP (bit 15) = 1, power down cellphone input pga.
++ * When BGC_MUT_CP = 0, power up cellphone input pga.
++ */
++static int __cellphone_input_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
++{
++	u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
++	ucontrol->value.integer.value[0]	= IS_UNMUTED(15, val);
++	return 0;
++}
++
++static int __cellphone_input_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
++{
++	return adc_pga_unmute_control(ucontrol->value.integer.value[0],
++				TSC2101_BUZZER_GAIN_CTRL,
++				15);	
++}
++
++static int __buzzer_input_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 
++{
++	uinfo->type 			= SNDRV_CTL_ELEM_TYPE_BOOLEAN;
++	uinfo->count			= 1;
++	uinfo->value.integer.min	= 0;
++	uinfo->value.integer.max	= 1;
++	return 0;
++}
++
++/* When BGC_MUT_BU (bit 6) = 1, power down cellphone input pga.
++ * When BGC_MUT_BU = 0, power up cellphone input pga.
++ */
++static int __buzzer_input_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
++{
++	u16 val = omap_tsc2101_audio_read(TSC2101_BUZZER_GAIN_CTRL);
++	ucontrol->value.integer.value[0]	= IS_UNMUTED(6, val);
++	return 0;
++}
++
++static int __buzzer_input_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 
++{
++	return adc_pga_unmute_control(ucontrol->value.integer.value[0],
++				TSC2101_BUZZER_GAIN_CTRL,
++				6);	
+ }
+ 
+ static snd_kcontrol_new_t tsc2101_control[] __devinitdata = {
+ 	{
+-		.name  = "Playback Playback Route",
++		.name  = "Target Playback Route",
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.index = 0,
+ 		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+@@ -801,7 +1016,7 @@
+ 	}, {
+ 		.name  = "Headset Playback Volume",
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		.index = 1,
++		.index = 0,
+ 		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ 		.info  = __headset_playback_volume_info,
+ 		.get   = __headset_playback_volume_get,
+@@ -809,7 +1024,7 @@
+ 	}, {
+ 		.name  = "Headset Playback Switch",
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		.index = 1,
++		.index = 0,
+ 		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ 		.info  = __headset_playback_switch_info,
+ 		.get   = __headset_playback_switch_get,
+@@ -817,7 +1032,7 @@
+ 	}, {
+ 		.name  = "Handset Playback Volume",
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		.index = 2,
++		.index = 0,
+ 		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ 		.info  = __handset_playback_volume_info,
+ 		.get   = __handset_playback_volume_get,
+@@ -825,12 +1040,28 @@
+ 	}, {
+ 		.name  = "Handset Playback Switch",
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+-		.index = 2,
++		.index = 0,
+ 		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ 		.info  = __handset_playback_switch_info,
+ 		.get   = __handset_playback_switch_get,
+ 		.put   = __handset_playback_switch_put,
+-	}	
++	}, {
++		.name  = "Cellphone Input Switch",
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.index = 0,
++		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
++		.info  = __cellphone_input_switch_info,
++		.get   = __cellphone_input_switch_get,
++		.put   = __cellphone_input_switch_put,
++	}, {
++		.name  = "Buzzer Input Switch",
++		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++		.index = 0,
++		.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
++		.info  = __buzzer_input_switch_info,
++		.get   = __buzzer_input_switch_get,
++		.put   = __buzzer_input_switch_put,
++	}
+ };
+ 
+ #ifdef CONFIG_PM
+diff -Naur linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.h h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.h
+--- linux-2.6.16.16/sound/arm/omap/omap-alsa-tsc2101-mixer.h	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/sound/arm/omap/omap-alsa-tsc2101-mixer.h	2006-03-30 23:15:31.000000000 +0300
+@@ -56,20 +56,21 @@
+ #define INPUT_VOLUME_MAX		0x7D
+ #define INPUT_VOLUME_RANGE		(INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
+ 
+-#define PLAYBACK_TARGET_COUNT		0x02
++#define PLAYBACK_TARGET_COUNT		0x03
+ #define PLAYBACK_TARGET_LOUDSPEAKER	0x00
+ #define PLAYBACK_TARGET_HEADPHONE	0x01
++#define PLAYBACK_TARGET_CELLPHONE	0x02
+ 
+ /* following are used for register 03h Mixer PGA control bits D7-D5 for selecting record source */
+ #define REC_SRC_TARGET_COUNT		0x08
+-#define REC_SRC_SINGLE_ENDED_MICIN_HED	MPC_MICSEL(0)	// oss code referred to MIXER_LINE
+-#define REC_SRC_SINGLE_ENDED_MICIN_HND	MPC_MICSEL(1)	// oss code referred to MIXER_MIC
+-#define REC_SRC_SINGLE_ENDED_AUX1	MPC_MICSEL(2)
+-#define REC_SRC_SINGLE_ENDED_AUX2	MPC_MICSEL(3)
+-#define REC_SRC_MICIN_HED_AND_AUX1	MPC_MICSEL(4)
+-#define REC_SRC_MICIN_HED_AND_AUX2	MPC_MICSEL(5)
+-#define REC_SRC_MICIN_HND_AND_AUX1	MPC_MICSEL(6)
+-#define REC_SRC_MICIN_HND_AND_AUX2	MPC_MICSEL(7)
++#define REC_SRC_SINGLE_ENDED_MICIN_HED	0x00	// oss code referred to MIXER_LINE
++#define REC_SRC_SINGLE_ENDED_MICIN_HND	0x01	// oss code referred to MIXER_MIC
++#define REC_SRC_SINGLE_ENDED_AUX1	0x02
++#define REC_SRC_SINGLE_ENDED_AUX2	0x03
++#define REC_SRC_MICIN_HED_AND_AUX1	0x04
++#define REC_SRC_MICIN_HED_AND_AUX2	0x05
++#define REC_SRC_MICIN_HND_AND_AUX1	0x06
++#define REC_SRC_MICIN_HND_AND_AUX2	0x07
+ 
+ #define DEFAULT_OUTPUT_VOLUME		90	// default output volume to dac dgc
+ #define DEFAULT_INPUT_VOLUME		20	// default record volume
+diff -Naur linux-2.6.16.16/sound/oss/Kconfig h6300_dev/sound/oss/Kconfig
+--- linux-2.6.16.16/sound/oss/Kconfig	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/sound/oss/Kconfig	2006-02-06 15:36:21.000000000 +0200
+@@ -13,8 +13,8 @@
+ 
+ config SOUND_OMAP_TSC2101
+ 	tristate "TSC2101 Stereo Codec"
+-	depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4 || MACH_OMAP_APOLLON)
+-	select OMAP_TSC2101 if ( MACH_OMAP_H2 || MACH_OMAP_H3 )
++	depends on SOUND_OMAP && ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4 || MACH_OMAP_APOLLON || MACH_OMAP_H6300)
++	select OMAP_TSC2101 if ( MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H6300 )
+ 	select OMAP_UWIRE if ARCH_OMAP1
+ 	---help---
+ 	  Tsc2101 Audio Codec Driver for OMAP will be enabled.
+diff -Naur linux-2.6.16.16/sound/oss/omap-audio-tsc2101.c h6300_dev/sound/oss/omap-audio-tsc2101.c
+--- linux-2.6.16.16/sound/oss/omap-audio-tsc2101.c	2006-05-17 21:41:31.000000000 +0300
++++ h6300_dev/sound/oss/omap-audio-tsc2101.c	2006-04-02 00:23:01.000000000 +0300
+@@ -48,7 +48,7 @@
+ #include "omap-audio.h"
+ #include "omap-audio-dma-intfc.h"
+ #include <asm/arch/mcbsp.h>
+-#ifdef CONFIG_ARCH_OMAP16XX
++#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_MACH_OMAP_H6300)
+ #include <../drivers/ssi/omap-uwire.h>
+ #include <asm/arch/dsp_common.h>
+ #elif defined(CONFIG_ARCH_OMAP24XX)
+@@ -73,10 +73,16 @@
+ 
+ #ifdef CONFIG_ARCH_OMAP16XX
+ #define PLATFORM_NAME "OMAP16XX"
++#elif CONFIG_MACH_OMAP_H6300
++#define PLATFORM_NAME "OMAP15XX"
+ #elif defined(CONFIG_ARCH_OMAP24XX)
+ #define PLATFORM_NAME "OMAP2"
+ #endif
+ 
++#if CONFIG_ARCH_OMAP16XX
++#define OMAP_DSP_BASE        0xE0000000
++#endif
++
+ /* Define to set the tsc as the master w.r.t McBSP */
+ #define TSC_MASTER
+ 
+@@ -123,7 +129,7 @@
+ /*********** Debug Macros ********/
+ /* To Generate a rather shrill tone -test the entire path */
+ //#define TONE_GEN
+-/* To Generate a tone for each keyclick - test the tsc,spi paths*/
++///* To Generate a tone for each keyclick - test the tsc,spi paths*/
+ //#define TEST_KEYCLICK
+ /* To dump the tsc registers for debug */
+ //#define TSC_DUMP_REGISTERS
+@@ -230,6 +236,17 @@
+ };
+ 
+ static struct omap_mcbsp_reg_cfg initial_config = {
++#ifdef CONFIG_MACH_OMAP_H6300
++	.spcr2 = 0x0005,
++	.spcr1 = 0x0005,
++	.rcr2  = 0x8041,
++	.rcr1  = 0x8041,
++	.xcr2  = 0x00a1,
++	.xcr1  = 0x00a1,
++	.srgr2 = 0xb000,
++	.srgr1 = 0xb000,
++	.pcr0  = 0x0081,
++#else
+ 	.spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ 	.spcr1 = RINTM(3) | RRST,
+ 	.rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+@@ -253,6 +270,7 @@
+ #endif				/* tsc Master defs */
+ 
+ #endif				/* platform specific inits */
++#endif /* CONFIG_MACH_OMAP_H6300 */
+ };
+ 
+ /***************************** MODULES SPECIFIC FUNCTION PROTOTYPES ********************/
diff --git a/packages/linux/linux-h6300-omap1_2.6.16.16.bb b/packages/linux/linux-h6300-omap1_2.6.16.16.bb
new file mode 100644
index 0000000000..e270cd87a2
--- /dev/null
+++ b/packages/linux/linux-h6300-omap1_2.6.16.16.bb
@@ -0,0 +1,19 @@
+DESCRIPTION = "Linux kernel for HP iPAQ h6300 series OMAP1510 based phones."
+MAINTAINER = "Mika Laitio <lamikr@cc.jyu.fi>"
+SECTION = "kernel"
+LICENSE = "GPL"
+
+SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.16.tar.bz2 \
+	   http://www.muru.com/linux/omap/patches/patch-2.6.16-omap2.bz2;patch=1 \
+           file://linux-2.6.16.16.patch;patch=1 \
+           file://linux-h6300-omap2-2.6.16.16.patch;patch=1 \
+           file://defconfig"
+
+S = "${WORKDIR}/linux-2.6.16"
+
+inherit kernel
+
+do_configure_prepend() {
+	install -m 0644 ${WORKDIR}/defconfig ${S}/.config
+        oe_runmake oldconfig
+}
-- 
cgit v1.2.3